访问原型父级
Accessing prototype parent
假设我有一个 Posts
class。
我能做到:
Posts.prototype.foo = function () {
console.log(this);
}
当我调用 post1.foo()
(post1
是 Posts
class 的实例)时,控制台输出的 this
将是等于 post1
。
现在考虑以下场景:
Posts.prototype.baz = {
foo: function () {
console.log(this);
},
bar: [1,2,3,4]
}
现在当我执行 post1.baz.foo()
时,this
的值不再是 post1
,而是 {foo: ..., bar: ...}
.
我的问题是:在第二种情况下,如何从 foo
中访问 post1
?
如果可以更改调用此方法的方式,则可以在 baz
中访问 this
。例如:
post1.baz.foo.call(post1);
将在您的 foo
帖子 class 函数实例中创建 this
并将 console.log
更正对象。
您遇到了一个有趣的问题。你所做的不是 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
并将其绑定到实例。此方法最常用于 "private" 变量,但当您需要将计算数据添加到 class 或在您的情况下声明特定范围时也很有用。
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),
您可能想仔细看看为什么需要 class 原型上的嵌套对象。你能把它分解成所有平面原型方法吗?它是不需要在每个 class 实例上实例化的数据,并且可以从其他地方提取出来吗?
只要你有一个 "this" 关键字,它绑定到的对象取决于调用站点。仅在呼叫站点上。这里有更深入的讨论 you don't know js。我强烈建议你阅读那个。但是,如果你让我过度简化它,可以这样考虑:
每当你执行一个函数时,它大致就像你在做以下事情:
//default binding
fn() ~ fn.call(window)
// the default binding of this, is window, or undefined in strict mode.
但是,您可以使用
调用该函数
//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
。对于规则 2,您将 this
绑定到 baz
。您想要的是显式调用 post1.baz.foo.call(post1);
。
浅见如下
那真的很丑,所以我能感受到你的痛苦。它之所以如此复杂,是因为您正在 违背语言的原则 。这可能是因为您试图以 java 方式进行继承。
最后,还有一个绑定,但要避免它:new
。如果可以,永远不要使用新的。 JS不是java,new的行为很迷惑。如果要实例化新对象,使用Object.create.
假设我有一个 Posts
class。
我能做到:
Posts.prototype.foo = function () {
console.log(this);
}
当我调用 post1.foo()
(post1
是 Posts
class 的实例)时,控制台输出的 this
将是等于 post1
。
现在考虑以下场景:
Posts.prototype.baz = {
foo: function () {
console.log(this);
},
bar: [1,2,3,4]
}
现在当我执行 post1.baz.foo()
时,this
的值不再是 post1
,而是 {foo: ..., bar: ...}
.
我的问题是:在第二种情况下,如何从 foo
中访问 post1
?
如果可以更改调用此方法的方式,则可以在 baz
中访问 this
。例如:
post1.baz.foo.call(post1);
将在您的 foo
帖子 class 函数实例中创建 this
并将 console.log
更正对象。
您遇到了一个有趣的问题。你所做的不是 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
并将其绑定到实例。此方法最常用于 "private" 变量,但当您需要将计算数据添加到 class 或在您的情况下声明特定范围时也很有用。
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),
您可能想仔细看看为什么需要 class 原型上的嵌套对象。你能把它分解成所有平面原型方法吗?它是不需要在每个 class 实例上实例化的数据,并且可以从其他地方提取出来吗?
只要你有一个 "this" 关键字,它绑定到的对象取决于调用站点。仅在呼叫站点上。这里有更深入的讨论 you don't know js。我强烈建议你阅读那个。但是,如果你让我过度简化它,可以这样考虑:
每当你执行一个函数时,它大致就像你在做以下事情:
//default binding
fn() ~ fn.call(window)
// the default binding of this, is window, or undefined in strict mode.
但是,您可以使用
调用该函数//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
。对于规则 2,您将 this
绑定到 baz
。您想要的是显式调用 post1.baz.foo.call(post1);
。
浅见如下
那真的很丑,所以我能感受到你的痛苦。它之所以如此复杂,是因为您正在 违背语言的原则 。这可能是因为您试图以 java 方式进行继承。
最后,还有一个绑定,但要避免它:new
。如果可以,永远不要使用新的。 JS不是java,new的行为很迷惑。如果要实例化新对象,使用Object.create.