【问题标题】:Javascript that equal this when referencing function to variable将函数引用到变量时等于 this 的 Javascript
【发布时间】:2013-12-16 18:22:49
【问题描述】:

是的,这是另一个关于将 this 存储在变量 (that) 中的问题,但我对此感到困惑:

function Constructor(){
    this.key = 'my key'
};


Constructor.prototype.start = function(){
    var that = this;
    return (function (){
        console.log(that.key)
    }());

};

foo = new Constructor;
foo.start()

bar = new Constructor;
newFoo = bar.start
newFoo()

我想既然this 被存储为一个变量,我可以在不丢失范围的情况下传递start() 方法吗? 我知道这已被经常讨论,但我找不到适合这种特定情况的答案。

如何在不使用Constructor.apply(this) 的情况下取回newFoo() 中的范围?

谢谢

【问题讨论】:

  • 不会,你必须改变函数的工作方式,或者使用newFoo.apply(bar)传递适当的范围
  • 您能否举例说明您的预期输出是什么? T.J. 的答案是正确的,如果这是您要解决的问题。
  • 请告诉我为什么你不赞成这个?这是一个合理的问题,那么有什么问题?

标签: javascript oop this


【解决方案1】:

我想既然这是作为变量存储的,我可以绕过 start() 方法而不会失去作用域?

不,因为您仍在使用 this 的值,就像调用 start 时一样,只是间接调用。你可以在 inside Constructor:

function Constructor() {
    // ...other stuff...

    var that = this;
    this.start = function(){
         console.log(that.key)
    };

    // ...other stuff...
}

(...并删除你放在原型上的那个)。

现在你可以随心所欲地传递startthat 将是调用构造函数时 this 的值。 start 有一个持久的引用,该引用来自对构造函数的调用中的that 变量。

当然,代价是通过Constructor 创建的每个实例都有其自己的start 函数副本。大多数现代 JavaScript 引擎都足够聪明,可以重用函数的代码(但它们需要为每个 start 创建单独的函数实例,这只是它们可以重用的幕后代码)。

您的另一个选择不是在Constructorstart 内处理此问题,而是在/当您在其他地方提供start 的副本时使用Function#bind 处理它。 Function#bind 是 ECMAScript5 (ES5) 功能,但可以在旧引擎上进行填充。

例子:

// Nice boring constructor with `start` on the prototype
// Note I've made the key an argument; in your code, all of them had the same key
function Constructor(key) {
    this.key = key;
}
Constructor.prototype.start = function() {
    console.log(this.key);
};

// **********

// Using it
var c1 = new Constructor("c1");

// Use it normally
c1.start();                       // "c1" as you'd expect

// Use it forgetting that `this` will change
setTimeout(c1.start, 0);          // "undefined" - doh!

// Use it via Function#bind
setTimeout(c1.start.bind(c1), 0); // "c1"

更多(在我的博客上)

【讨论】:

  • 谢谢,但是有没有办法在 start() 方法中实现这一点,或者我真的需要为此使用构造函数吗?如果是这样那没问题,它只是为了测试
  • @ChristophHa: 如果你把start 放在原型上,你就不能把this 的值保存在that 中,因为你在那个时候没有访问那个值的权限时间。它在Constructor 中起作用的原因是,此时您可以访问您希望that 拥有的值。当然,您的另一个选择是使用Function#bind 如果/当您分发start 时,我会添加它。
  • 啊对,还没看到这个,解释的真好,期待你的博文:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-11
  • 1970-01-01
  • 2011-01-11
  • 2011-12-28
  • 1970-01-01
  • 2015-02-17
相关资源
最近更新 更多