2013-03-07 2 views
3

Чтобы реализовать наследование в Javascript, обычно выполняются следующие два шага;Наследование на Javascript; вызов и прототип

Скажем, у меня есть базовый класс «животное»

var Animal = function(name){ 
this.name = name; 
} 

теперь я хочу, чтобы получить суб-класс «Собака» из того же самого. Поэтому я бы сказал

var Dog = function(name) { 
    Animal.call(this,name); 
} 

Поэтому я вызываю конструктор родительского класса из конструктора производного класса. Второй шаг - установить прототип следующим образом;

Dog.prototype = new Animal(); 

Теперь я могу получить доступ к любому из свойств класса «Животные» из моего производного класса Dog.

Итак, мой вопрос, почему эти два шага необходимы? Если мы просто вызвать конструктор базового класса с использованием

Animal.call(this,name); 

не то, что достаточно для реализации наследования?

Почему у нас также необходимо указать свойство прототипа, используя Dog.prototype = new Animal();?

Я хотел понять, что делает каждый из этих двух шагов?

+1

У вас нет ничего, чтобы * наследовать * здесь. – jAndy

+1

Поскольку «Animal» также может наследовать, используя цепочку прототипов. Просто вызов родительского конструктора не сохранит эту цепочку наследования. – Sim

+0

Является ли TRUE сказать, что call() просто наследует свойства базового класса, а второй шаг (установочный прототип) наследует методы из базового класса? – testndtv

ответ

0

Первый дело в том, что в JavaScript нет классического наследования, механизма, который мы знаем из C-языков, таких как Java, C# и так форт. В JavaScript повторное использование кода может быть выполнено с использованием прототипа-наследования. Единственное, что у нас есть, это объекты, блоки кода, которые живы и не нуждаются в создании экземпляров. Например: когда функция вызывается на объект - как метод, текущий объект проверяется, известна ли эта функция. Если он не найден, двигатель вызывает его прототип (который является другим объектом) и проверяет, известно ли имя функции и может быть вызвано. Когда не найден, вызывается прототип iths и так далее. Таким образом, устанавливая прототип объекта, можно организовать цепочку прототипов.

Чтобы ответить на ваш вопрос: ничего не нужно, его до вас, что вы хотите. Повторное использование кода - это то, что вы хотите, и наследование - это то, как вы можете это достичь (Stoyan Stefanov - JavaScript Patterns). В JavaScript больше возможностей для повторного использования кода.

Кроме того, это связано с текущим контекстом, а не всегда с текущим объектом.

+0

Итак, когда вы говорите, текущий объект проверяется, известна ли функция ... если нет, это прототип вызывается и так далее ... так что мы можем установить прототип для любого типа объекта ... например, если я проверяю на метод myMethod1() на myObject1, и если он не найден, могу ли я сделать следующий поиск в myObject2 ... ie Я как-то установил прототип (или родительский объект) myObject1 в myObject2 ... Можем ли мы показать пример ... – testndtv

+0

Ha! вы поняли! Настройка прототипа объектов проста: myobject.prototype = myobject2 – Andries

+0

Итак, это то же самое, что и установка связывания myobject '_proto_'._proto = myobject2 (Но '_proto_' недоступен во всех браузерах, кроме Firefox) – testndtv

2
var Animal = function(name){ 
    this.name = name; 
} 
Animal.prototype.sleep = function() { 
    console.log("Sleeping") 
} 

... 
// Without this line: 
Dog.prototype = new Animal(); 

// the following code will fail, since `d` does not contain `sleep` 
d = new Dog(); 
d.sleep(); 

Animal.call(this,name); просто вызывает функцию Animal, но с использованием того же this как вызывающей функции.

Dog.prototype = new Animal(); устанавливает прототип прототипа. Однако, может быть, Dog.prototype = Object.create(Animal.prototype).

+0

Я не уверен в этом 'Dog.prototype = Object.create()', потому что 'Object.create()' уже установит '.prototype' вновь созданного объекта с тем вы проходите. – jAndy

+0

@jAndy: Разве это не так? Вы хотите, чтобы «Dog.prototype .__ proto__' был« Animal.prototype », так что члены наследуются, но вы не хотите, чтобы« Dog.prototype »был полным экземпляром« Animal ». – Eric

+0

В этом случае да, вправо. Я неправильно понял. – jAndy

0

Второй шаг поможет вам наследовать прототипы. Представьте себе, что у нас есть более сложный класс:

function Animal(name) { 
    this.name = name; 
} 

// shared method 
Animal.prototype.say = function() { 
    alert(this.name); 
}; 

function Dog() { 
    Animal.apply(this, arguments); 
} 

Dog.prototype = new Animal(); 


var dog = new Dog('Cooper'); 
// method has been inherited 
dog.say(); // alerts 'Cooper' 

Вы можете попробовать это here

0

Там нет классов, ни подклассы, в JavaScript.

вызов и применение выполняют функцию в контексте другого «этого». То, что у вас есть в вашем примере кода, не требуется.

//Create your constructor function: 
var Animal = function(){} 

Animal.prototype = { 
    sleep: function(){ 
     console.log('zzz'); 
    }, 
    bark: function(name){ 
     console.log(name +' barks!'); 
    } 
} 

var dog = new Animal(); 

dog.sleep(); 
dog.bark('asdasd'); 
+0

'var cat = new Animal(); cat.bark ('кошка'); '. Я думаю, что ОП знает, что они хотят наследования здесь. – Eric

0

Здесь мы определяем функцию конструктора для Animal

var Animal = function(name){ 
    this.name = name; 
} 

Затем определим функцию конструктора для Dog и внутри него мы вызываем функцию конструктора Animal. Точно так же, как мы делаем super() в объектно-ориентированном дизайне на основе классов.

var Dog = function(name) { 
    Animal.call(this,name); 
} 

Тогда мы строим прототип Dog потребляя методы, определенные в прототипе Animal.Здесь не клонировать методы в Animal, но связь устанавливается между Dog и Animal с помощью которого он повторно использует методы в Animal

Dog.prototype = new Animal(); 

И продолжать расширение его добавления новых методов

Dog.prototype.showName = function(){ 
    // do something 
} 
1

код образца стоит тысячи слов :)

var Animal = function(name) { 
    this.name = name; 
} 
Animal.prototype.run = function() { 
    // do something 
}; 
var Dog = function(name) { 
    Animal.call(this, name); 
} 

var dog = new Dog('Puppy'); 
typeof dog.name; // "string" 
typeof dog.run; // "undefined" 
dog instanceof Animal; // false 
dog instanceof Dog; // true 

Dog.prototype = new Animal(); 

var dog = new Dog('Puppy'); 
typeof dog.name; // "string" 
typeof dog.run; // "function" 
dog instanceof Animal; // true 
dog instanceof Dog; // true 

Как вы можете видеть, если вы не используете Dog.prototype = new Animal();, Animal.prototype члены не будут наследоваться. Кроме того, экземпляры Dog не будут рассматриваться как экземпляры Animal.

Смежные вопросы