【问题标题】:Do not modify context even using a function that modifies the context即使使用修改上下文的函数也不要修改上下文
【发布时间】:2014-09-28 18:34:34
【问题描述】:

也许标题听起来有点奇怪(请改进它)——但我需要针对以下情况的解决方案。我有以下代码:

var Foo = function () {
    this._hello = "world!";
};

Foo.prototype.bar = function () {
    console.log(this._hello);
};

var f = new Foo();
f.bar(); // => "world!"
f.bar.apply(this); // => undefined

我知道apply 改变了上下文,所以在bar 内部,this 将是全局对象(在第二次调用时)。

但我需要的是从Foo 函数访问this。我看到的解决方案是:

var Foo = function () {
   var self = this;
   self._hello = "world!";
   self.bar = function () {
      console.log(self._hello);
   };
};

但是,我会选择不在另一个函数中声明方法。

我更喜欢在同一列级别定义方法(仅用于代码样式):

var Foo = ...;
Foo.prototype.method = ...;

这可能吗?怎么样?

【问题讨论】:

  • 不要费心缩进你的代码。
  • 这不是“范围”,而是调用的上下文
  • 你为什么要在bar 上使用apply?你的电话看起来如何不仅仅是f.bar()
  • @Bergi 我希望能够做到:f = new Foo(); something.method(f.bar);。在这种情况下,f.bar 被另一个作用域调用。

标签: javascript class methods this


【解决方案1】:

您可以使用bind() method 处理these kinds of problems。而不是 something.method(f.bar) 调用 something.method(f.bar.bind(f)) 以获取始终在预期上下文 (f) 上调用的 bar 方法。

如果您不想在将bar 作为回调传递的每个位置都使用bind,您也可以将其放在构造函数中,默认为每个实例创建一个专用的绑定函数:

function Foo() {
    this._hello = "world!";
    this.bar = this.bar.bind(this);
}
Foo.prototype.bar = function () {
    console.log(this._hello);
};

var f = new Foo;
something.method(f.bar); // works!

【讨论】:

  • 应该是this._hello
  • 这是正确的解决方案,但我不推荐它,因为我猜它对内存不友好。
  • @IonicăBizău:为什么?它不应该比闭包解决方案对内存更友好。
【解决方案2】:

不可能通过像这样将函数分配给原型来做到这一点。

除非您直接将某些内容分配给f.bar(如在您的第二个示例和Bergi 的回答中),否则您将为f.bar 获得的值是对您分配给原型属性Foo.prototype.bar 的函数的引用。对于以Foo.prototype 为原型的任何其他对象,这将是完全相同的函数对象。此函数对象中没有对f 的引用。

那么当你调用f.bar()时,this如何引用f的值呢?这是一种特殊的语法,基本上等同于f.bar.apply(f)。只是您使用这种方法调用语法将this 设置为f 的值。对f.bar 的任何其他引用都只会评估为原型的单个共享函数对象。

如果您使用f.bar.apply(somethingElse) 调用它,this 现在设置为somethingElse,并且与f 的所有关联都将丢失。

这不是apply(...) 改变范围的问题。 fn.apply(x)fn 内将this 设置为x,而y.fn()this 设置为y

同样,在您的示例中,如果您将 f.bar 分配给一个变量,然后通过该变量而不是使用方法调用语法 f.bar() 调用它,您的 this 将是 window 对象(如果正在运行在浏览器中),您将再次获得undefined

var func=f.bar; // now func === Foo.prototype.bar
func(); // => undefined

另见How to find the object a function belongs to?

【讨论】:

    猜你喜欢
    • 2012-03-17
    • 2012-10-19
    • 2020-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-21
    • 1970-01-01
    • 2013-10-09
    相关资源
    最近更新 更多