假设我有一个Posts
课程。
我能做到:
Posts.prototype.foo = function () {
console.log(this);
}
当我调用post1.foo()
(post1
为Posts
类的实例)时,控制台输出的this
将等于post1
}。
现在考虑以下情况:
Posts.prototype.baz = {
foo: function () {
console.log(this);
},
bar: [1,2,3,4]
}
现在当我post1.baz.foo()
时,this
的值不再是post1
,而是{foo: ..., bar: ...}
。
我的问题是:在第二种情况下,如何从post1
内访问foo
?
答案 0 :(得分:2)
你正在遇到一个有趣的问题。您正在做的不是Javascript中的常见模式(将嵌套对象分配给原型),表面看起来应该可以正常工作。
Javascript this
以两种方式解决。如果您正在使用new
实例化一个函数,this
将成为对该实例化对象的引用(如您所知)。
但是,this
也可以解析为父对象。也就是说,此代码将记录'bar'
:
var obj = {
prop: 'bar',
log: function() { console.log( this.prop ); }
};
obj.log();
因为this
引用了函数所在的对象。这就是您案件中发生的事情。范围正在提前解决。
除此之外:如果该功能没有嵌套在对象中,并且您不使用new
,this
将成为全局对象(window
浏览器)。
执行此操作的正确方法可能在Posts的构造函数中,您可以在其中设置this.whatever
并将其绑定到实例。这种方法最常用于"私人"变量,但是当你需要向你的类添加计算数据时,或者在你的情况下,声明特定的范围时,它也很有用。
function Posts() {
var self = this;
this.baz = {
foo: function () {
console.log(self);
},
bar: [1,2,3,4]
}
}
你也可以这样做:
...
this.baz = {
foo: function () {
console.log(this);
}.bind(this),
您可能需要仔细查看为什么需要类原型上的嵌套对象。你能把它分解成所有平面原型方法吗?它是不是需要在每个类实例上实例化的数据,并且可以在其他地方拉出来?
答案 1 :(得分:1)
每当你有一个“this”关键字时,它受到限制的对象取决于调用站点。只在通话网站上。这是一个更深入的讨论you don't know js。我强烈建议你阅读。但是,如果你让我简化它,请考虑这种方式:
每当执行一个函数时,就好像你在执行以下操作一样:
//implicit binding
obj.fn() ~ fn.call(ojb)
// in this case you are implicitly binding this as the obj
然而,您可以使用
调用该函数call
或者,如果您想要明确,请使用apply
或//explicit bining
fn.call(obj)
//this is explicitly binding obj as this.
:
post1.baz.foo()
这些的优先级是明确的>隐含的>默认值。
在您的情况下,您正在运行.baz
:您的呼叫网站为this
。对于规则2,您将baz
绑定到post1.baz.foo.call(post1);
。您想要的是明确并致电new
。
谦卑的意见如下
这真是太丑了,所以我感到痛苦。它之所以如此复杂,是因为你正在使用来对抗语言。这可能是因为您尝试以java方式继承。
最后,还有一个绑定,但要避免它:{{1}}。如果可以,永远不要使用新的。 JS不是java,而new的行为非常混乱。如果要实例化新对象,请使用Object.create。
答案 2 :(得分:0)
如果您可以更改此方法的调用方式,则可以访问this
内的baz
。例如:
post1.baz.foo.call(post1);
将在this
Posts类的函数实例中生成foo
并console.log
更正对象。