简体   繁体   中英

Why can't I refer to the inherited method from JavaScript prototype within method

When I use JavaScript prototype to inherit a object and want to use it's method in the following way:

 var Father = { name:'Father', act:function(){ console.log('the name is '+this.name); } } var Son = function(){ act(); } Son.__proto__ = Father; Son();

This doesn't work, when Js Engine run Son() , it should search act() through it's prototype chain.

But why it only works the following way:

 var Father = { name:'Father', act:function(){ console.log('the name is '+this.name); } } var Son = { name:'Son' } Son.__proto__=Father; Son.act();

The long and short of it is the function act() does not exist when you are trying to use it.

Just because you want Son to inherit from Father does not mean JS knows you want to do that. When you are trying to using act() JS has no idea you are wanting to tie Son to Father ... as far as JS is concerned they are completely different functions/objects/etc.. and have absolutely ZERO relation for all JS knows.

Again, you need to use an actual act function within the appropriate scope - JS has no clue what your intentions are - how do you expect JS to know which object to pull act() from... What if there was a Mother object with an act method?...

First Snippet: To resolve this, just build an act() function...

 var Father = { name:'Father', act:function(){ console.log('the name is '+this.name); } } function act() { return this.name; } var Son = function(){ act(); } Son.__proto__ = Father; Son.act();

Second Snippet: It's no different than trying:

 var Father = { name:'Father', act:function(){ console.log('the name is '+this.name); } } var Son = function(){ // using 'act();' here is no different than trying: somethingThatDoesntExist(); } Son.__proto__ = Father; try { Son(); } catch { console.log("Oh no error\\r\\n\\r\\n"); } // If you don't assign anything.. // It will work... because of inheritence.. Son = {} // MAKING SON AN OBJECT NOT A FUNCTION Son.__proto__ = Father; // If you don't change the name, it will log: 'the name is Father' Son.name = "Son"; console.log("Son as an object {} ... we had to do `Son.name = 'Son'` here"); Son.act(); console.log(""); // But if you change Son to be a function, then inherit, you dont have to // change the name... 2 completely different things.... Son = function(){} Son.__proto__ = Father; console.log("Son as an function(){} ... we DID NOT have to do `Son.name = 'Son'` here since Son.name will be the name of the function, which is Son"); Son.act();

Third Snippet: Or if you did:

 var Father = { name: 'Father', act: function() { console.log('the name is ' + this.name); } } var Son = function() { function act() { return this.name; } } Son.__proto__ = Father; Son.act();

Fourth Snippet Or you can do:

 var Father = { name:'Father', act:function(){ console.log('the name is '+this.name); } } var Son = { name:'Son' } Son.__proto__ = Father; Son.act();

Fifth Snippet Or..

 var Father = { name:'Father', act:function(){ console.log('the name is '+this.name); } } var Son = { anythingYouWantHere: function() { console.log("anythingYouWantHere " + this.name); } } try { Son.act() // YOU WILL GET AN ERROR HERE } catch { console.log("YOU WILL GET AN ERROR HERE"); } Son.__proto__ = Father; Son.act(); // the name is Father Son.anythingYouWantHere(); // anythingYouWantHere Father Son.name = "Son"; Son.act(); // the name is Son Son.anythingYouWantHere(); // anythingYouWantHere Son Son.act = function() { console.log("I have now changed act! the name is " + this.name); } Son.act(); // I have now changed act! the name is Son

You need to do two things:

1) Write the prototype object of Son , not __proto . For a discussion of the difference, see this question . (TL;DR: prototype is the object set as the source from which the object/function inherits. __proto__ is the resultant prototype chain that is used to look up and resolve references to methods/properties.)

2) Instantiate Son with the new keyword.

var Father = {
  name:'Father',
  act:function(){
    return 'hello';
  }
}
var Son = function(){}
Son.prototype = Father; //<-- prototype, not __proto__
let foo = new Son(); //<-- instantiate with 'new'
foo.act(); //"hello";

With your current code:

var Son = function(){
   act();
}

act() expects a function defined locally in the scope of Son , not one defined on its prototype tree.

act is not any property of an object. it is just a variable that points to a function.

When you try to access a property of an object then only Javascript first check if the property exists in that object or not, if it does not then only it search in its prototype until a prototype is null.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM