为什么我不能在方法

时间:2019-12-29 17:43:39

标签: javascript prototype

当我使用JavaScript原型继承对象并想通过以下方式使用它的方法时:

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

这不起作用,当Js Engine运行Son()时,它应该在其原型链中搜索act()

但是为什么它只能通过以下方式工作:

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

3 个答案:

答案 0 :(得分:2)

它的长短之处是您尝试使用该功能时act()不存在。

仅仅因为您希望SonFather继承并不意味着JS知道您要这样做。当您尝试使用act()时,JS不知道您想将SonFather结合起来……就JS而言,它们是完全不同的功能/对象/等。 。并具有所有JS知识的绝对零关系。

同样,您需要在适当的范围内使用实际的act函数-JS不知道您的意图是什么-您希望JS如何知道从哪个对象中提取act()。 。如果有一个Mother对象带有act方法怎么办?...

第一个代码段: 要解决此问题,只需构建一个act()函数...

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

第二个片段: 与尝试没什么不同:

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

第三摘要: 或者,如果您这样做:

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

第四段 或者您可以执行以下操作:

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

var Son = { 
  name:'Son'
} 

Son.__proto__ = Father; 

Son.act(); 

第五个片段 或..

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

答案 1 :(得分:0)

您需要做两件事:

1)写入prototype的{​​{1}}对象,而不是Son。有关差异的讨论,请参见this question。 (TL; DR:__proto是设置为对象/函数继承源的对象。prototype是生成的原型链,用于查找和解析对方法/属性的引用。)

2)使用__proto__关键字实例化Son

new

使用您当前的代码:

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

var Son = function(){ act(); } 期望在act()范围内本地定义的函数,而不是在其原型树上定义的函数。

答案 2 :(得分:0)

act不是对象的任何属性。它只是指向函数的变量。

当您尝试访问对象的属性时,只有Javascript首先检查该对象中是否存在该属性,如果不存在,则仅在其原型中进行搜索,直到原型为空为止。