当我使用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();
答案 0 :(得分:2)
它的长短之处是您尝试使用该功能时act()
不存在。
仅仅因为您希望Son
从Father
继承并不意味着JS知道您要这样做。当您尝试使用act()
时,JS不知道您想将Son
与Father
结合起来……就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首先检查该对象中是否存在该属性,如果不存在,则仅在其原型中进行搜索,直到原型为空为止。