Прототип 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]);

Существуют некоторые структуры, которые фокусируются на наследовании прототипов, которые помогут вам решить некоторые вопросы.

Другие вопросы по тегам