Javascript Prototypal Inheritance - 真正理解这个概念

时间:2016-08-08 00:03:26

标签: javascript inheritance prototypal-inheritance

我正在查看JS原型继承的视频解释(https://www.youtube.com/watch?v=qMO-LTOrJaE)。 有些事情我不明白。让我解释一下



var Bear = function(type) { //PARENT
  this.type;
  this.hasFur = true;
}

Bear.prototype.kingdom = 'Animalia'; //ASSIGNING TO PARENT'S PROTOTYPE

var Grizzly = function(type) { //CHILD
  this.species = 'Brown Bear';
}

Grizzly.prototype = Object.create(Bear.prototype); //INHERITING FROM PARENT

var grizzly1 = new Grizzly('grizzly');

console.log(grizzly1.hasFur); //prints undefined //members in parent's constructor not accessible
console.log(grizzly1.kingdom); //prints Animalia //however, members in parent's prototype is accessible




但是只要将以下行添加到Grizzly构造函数中,

var Grizzly = function(type){
  Bear.call(this, type); //ADDED
  this.species = 'Brown Bear';
}

你能够从父母那里获取所有东西,而不仅仅是它的原型

console.log(grizzly1.hasFur);  //prints true
console.log(grizzly1.kingdom); //prints Animalia

但是,以下面的方式继承,即使在Child构造函数中没有@Bear.call(this)行,也允许子进入父对象中的所有内容。

Grizzly.prototype = new Bear();

所以它真的以这种方式继承了一切。有人可以解释这种行为是什么以及它发生的原因吗?

还有什么不同的JavaScript继承方式。考虑最佳实践以及原因,最好使用哪一个。

2 个答案:

答案 0 :(得分:4)

  

有些事我不明白。让我解释一下

var Bear = function(type) { //PARENT
  this.type;
  this.hasFur = true;
}

Bear.prototype.kingdom = 'Animalia'; //ASSIGNING TO PARENT'S PROTOTYPE

var Grizzly = function(type) { //CHILD
  this.species = 'Brown Bear';
}

Grizzly.prototype = Object.create(Bear.prototype); //INHERITING FROM PARENT

var grizzly1 = new Grizzly('grizzly');

console.log(grizzly1.hasFur); //prints undefined //members in parent's constructor not accessible
console.log(grizzly1.kingdom); //prints Animalia //however, members in parent's prototype is accessible

在上面分享的代码段中,grizzly1.hasFurundefined,因为Bear的构造函数尚未执行。第Grizzly.prototype = Object.create(Bear.prototype);行只是继承父原型方法和属性。

  

但是只要将以下行添加到Grizzly构造函数中,

var Bear = function(type) { //PARENT
  this.type;
  this.hasFur = true;
}

Bear.prototype.kingdom = 'Animalia'; //ASSIGNING TO PARENT'S PROTOTYPE

var Grizzly = function(type) { //CHILD
  Bear.call(this, type); //ADDED
  this.species = 'Brown Bear';
}

Grizzly.prototype = Object.create(Bear.prototype); //INHERITING FROM PARENT

var grizzly1 = new Grizzly('grizzly');

console.log(grizzly1.hasFur); //prints undefined //members in parent's constructor not accessible
console.log(grizzly1.kingdom);

grizzly1.hasFur现在是true,因为现在在grizzly的构造函数中,调用Bear的构造函数类,使用call更改其上下文。由于上下文已更改,this. hasFur会在此操作中分配其true值,this现在引用grizzly的实例。

  

但是,以下面的方式继承,即使在Child构造函数中没有//Bear.call(this)行,也允许子进入父对象中的所有内容。   Grizzly.prototype = new Bear();

这里发生的是,创建了一个Bear类的新实例。现在Bear类的任何实例都可以访问在实例化构造函数类(即function Bear时定义的原型方法和内部属性。现在,在创建实例之后,将其分配给Grizzly的原型链。因此Grizzly的任何新实例不仅访问Grizzly的内部属性,而且还充当Bear类的新实例。

  

还有哪些在JavaScript中继承的方式

我肯定建议你研究设计模式。你可以谷歌出来不同的书籍。我喜欢阅读 JavaScript:好的部分学习JavaScript设计模式。你可能会喜欢其他一些书来清理你的基础知识。 Javascript中有很多可数的东西,如这些,闭包等,需要清晰的概念。

  

考虑最佳做法及其原因,最好使用哪一个。

我更喜欢原型继承的最佳实践是: 在构造函数类中说A

function A () {
   this.privateProp = something;
}
A.prototype.public = something;

所以请参阅声明构造函数类中的那些属性和方法,您希望保持私有。将其暴露在原型链中。

希望这有帮助。

答案 1 :(得分:2)

检查出来:

var Bear = function(type){ //PARENT
  this.type;
  this.hasFur = true;
}

alert(new Bear().hasFur);

了解此 如何在警告框中为您提供true。想想,为什么这样做,而不是你的例子?

想到了吗?

这是因为在这段代码中:

var Bear = function(type){ //PARENT
  this.type;
  this.hasFur = true;
}

您将该功能分配给Bear,因此new Bear()无法Bear.prototype访问该功能。这将有效:

Bear.prototype.kingdom = 'Animalia'; //ASSIGNING TO PARENT'S PROTOTYPE

var Grizzly = function(type){ //CHILD
  this.species = 'Brown Bear';
}

Grizzly.prototype = Object.create(new Bear()); // Modified line

var grizzly1 = new Grizzly();

alert(grizzly1.hasFur);  // Prints true now.
alert(grizzly1.kingdom);