Прототип Javascript, как наследовать класс?
Мне нужно отношение наследования между двумя классами в Javascript. Мне нравится объявлять свойства внутри Конструктора; Для методов, прототип:
function Animal(){
this.someProperty = 'someProperty';
this.init();
}
Animal.prototype = {
init : function(){ }
anotherMethod : function(){ }
}
Я думаю, что объявление таких методов приносит больше читабельности, чем:
Animal.prototype.init = function(){ }
Animal.prototype.anotherMethod = function(){}
Но когда мне нужно унаследовать один класс от другого, я не нахожу способ сделать это по-своему. Это не работает:
Cat.prototype = new Animal();
Cat.prototype = {
init : function(){ }
}
Я знаю, что я могу сделать это следующим образом:
Cat.prototype = new Animal();
Cat.prototype.init = function(){ }
Cat.prototype.anotherMethod = function(){ }
но есть ли способ сделать это по-моему?
5 ответов
Делая это
Cat.prototype = new Animal();
Cat.prototype = {
init : function(){ }
}
Вы перезаписываете первое объявление, чтобы оно не получало методы Animal.
В javascript вы можете делать наследование только используя прототип
Cat.prototype = new Animal();
Cat.prototype.init = function(){ }
Вы должны расширить прототип вместо его замены, если вы хотите сохранить синтаксис, аналогичный тому, который вы используете в настоящее время.
Например, с lodash вы используете assign
как это:
_.assign(Cat.prototype, {
init : function(){ }}
);
Во-первых, настройте наследование, используя Object.create
Далее, если вы хотите использовать один объект для расширения другого объекта, вы можете скопировать дескрипторы его свойств в другой, используя Object.getOwnPropertyDescriptor
а также Object.defineProperty
например,
function copyAtoB(A, B) {
var d = Object.getOwnPropertyNames(A),
i;
for (i = 0; i < d.length; ++i)
Object.defineProperty(
B,
d[i],
Object.getOwnPropertyDescriptor(A, d[i])
);
return B;
}
function Animal() {
this.isAnimal = true;
// etc
}
Animal.prototype = Object.create(null); // Animal doesn't inherit from anything
copyAtoB({
foo: function () { console.log('foo'); }
}, Animal.prototype);
function Cat() {
Animal.call(this); // the Animal constructor helps build cats
this.isCat = true;
// etc
}
Cat.prototype = Object.create(Animal.prototype); // Cat inherits from Animal
copyAtoB({
bar: function () { console.log('bar'); }
}, Cat.prototype);
Теперь у нас есть
var cat = new Cat();
cat.isCat; // true
cat.isAnimal; // true
cat.foo(); // logs "foo"
cat.bar(); // logs "bar"
Вы можете использовать метод расширения.
Cat.prototype.extend({
init : function(){ }
}, new Animal());
function extend(destination, source) {
Object.keys(source).forEach(function (key) {
if(typeof destination[key] === 'undefined') {
destination[key] = source[key]
}
}
}
Проверьте некоторые подходы наследования, чтобы получить наследство, работающее:
Пример из первой ссылки, который может подвести итог, который похож, но немного отличается:
function Mammal(name){
this.name=name;
this.offspring=[];
}
Mammal.prototype.haveABaby=function(){
var newBaby=new Mammal("Baby "+this.name);
this.offspring.push(newBaby);
return newBaby;
}
Mammal.prototype.toString=function(){
return '[Mammal "'+this.name+'"]';
}
Cat.prototype = new Mammal(); // Here's where the inheritance occurs
Cat.prototype.constructor=Cat; // Otherwise instances of Cat would have a constructor of Mammal
function Cat(name){
this.name=name;
}
Cat.prototype.toString=function(){
return '[Cat "'+this.name+'"]';
}
var someAnimal = new Mammal('Mr. Biggles');
var myPet = new Cat('Felix');
alert('someAnimal is '+someAnimal); // results in 'someAnimal is [Mammal "Mr. Biggles"]'
alert('myPet is '+myPet); // results in 'myPet is [Cat "Felix"]'
myPet.haveABaby(); // calls a method inherited from Mammal
alert(myPet.offspring.length); // shows that the cat has one baby now
alert(myPet.offspring[0]);
Существуют некоторые структуры, которые фокусируются на наследовании прототипов, которые помогут вам решить некоторые вопросы.