Javascript Prototypal Inheritance - Truly understanding the concept

感情迁移 提交于 2019-12-25 06:33:27

问题


I was looking at this video explanation(https://www.youtube.com/watch?v=qMO-LTOrJaE) of JS prototypal inheritance. There's something I don't understand. Let me explain

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

But as soon as you add the following line to the Grizzly constructor,

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

you're able to access everything from the parent, not just it's prototype

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

However, inheriting in the below fashion, gives the child access to everything in the parent even without the line //Bear.call(this) in the Child constructor.

Grizzly.prototype = new Bear();

So it truly inherits everything this way. Can someone explain what's this behavior and why it happens ?

Also what are the different ways of inheriting in JavaScript. Which one is the best to use considering best practices and why.


回答1:


There's something I don't understand. Let me explain

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

In the code snippet shared above, grizzly1.hasFur is undefined as the constructor function for Bear is not yet executed. The line Grizzly.prototype = Object.create(Bear.prototype); just inherits the parent prototypal methods and properties.

But as soon as you add the following line to the Grizzly constructor,

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 is now true because now within the constructor function of grizzly, the constructor class for Bear is invoked changing its context using a call. The this. hasFur gets its true value assigned in this operation as here due to the changed context, this now refers to the instance of grizzly.

However, inheriting in the below fashion, gives the child access to everything in the parent even without the line //Bear.call(this) in the Child constructor. Grizzly.prototype = new Bear();

What happens here is, a new instance of the Bear class is created. Now any instance of the class Bear can have access to the prototypal methods and internal properties defined while instantiating the constructor class i.e. function Bear. Now after the instance being created, this gets assigned to the prototypal chain of Grizzly. So any new instance of Grizzly not only access the internal properties of Grizzly, but also behaves as a new instance of the Bear class.

Also what are the different ways of inheriting in JavaScript

I would definitely suggest you to study design patterns. You can google out different books for it. I loved reading JavaScript: The Good Parts and Learning JavaScript Design Patterns. You might love some other books for clearing up your fundamentals. There are few countable things in Javascript like these, closures, etc., which needs crystal clear conceptions.

Which one is the best to use considering best practices and why.

The best practice in prototypal inheritance ,I prefer,is: In the constructor class say A

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

So see declare only those properties and methods inside the constructor class, which you wanna keep private. Rest keep it exposed in prototype chain.

Hope this helps.




回答2:


Check this out:

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

alert(new Bear().hasFur);

See how this does gives you true in the alert box. Think, why is this working, and not for your example?

Thought about it?

It's because in this code:

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

You're assigning the function to Bear, so it's accessible by new Bear() not Bear.prototype. This will work:

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); 


来源:https://stackoverflow.com/questions/38819688/javascript-prototypal-inheritance-truly-understanding-the-concept

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!