什么'var that = this;' 用JavaScript表示?

Chr*_*ris 346 javascript this

在JavaScript文件中,我看到:

function Somefunction(){
   var that = this; 
   ... 
}
Run Code Online (Sandbox Code Playgroud)

声明that和分配给它的目的是什么this

lon*_*day 478

我将以一个例子开始这个答案:

var colours = ['red', 'green', 'blue'];
document.getElementById('element').addEventListener('click', function() {
    // this is a reference to the element clicked on

    var that = this;

    colours.forEach(function() {
        // this is undefined
        // that is a reference to the element clicked on
    });
});
Run Code Online (Sandbox Code Playgroud)

我的回答最初用jQuery证明了这一点,它只是略有不同:

$('#element').click(function(){
    // this is a reference to the element clicked on

    var that = this;

    $('.elements').each(function(){
        // this is a reference to the current element in the loop
        // that is still a reference to the element clicked on
    });
});
Run Code Online (Sandbox Code Playgroud)

由于this通过调用新函数更改范围时经常更改,因此无法使用它来访问原始值.将其别名化以that允许您仍然可以访问原始值this.

就个人而言,我不喜欢使用that别名.很少有人明白它的含义,特别是如果函数长于几行.我总是使用更具描述性的别名.在我上面的例子中,我可能会使用clickedEl.

  • 我通常选择`var self = this;`."that"这个词似乎意味着变量是什么但是"这个". (142认同)
  • @David是的我认为****有点误导.但是,如果正如克罗克福德所说,这是一个惯例,沿着那条路走下去是明智的.我完全赞同你,但更有道理. (12认同)
  • @ElRonnoco:这是对权威的吸引力.如果我们只做"名人"所说的我们应该做的事情,我们就会走向灾难. (7认同)
  • @El Ronnoco,但是"他有一头白发和一头胡须,他的态度让人想起一个脾气暴躁的老人,他骂孩子们从他的草坪上下车." - http://blogging.compendiumblog.com/blog/software-for-humans/0/0/on-becoming-a-douglas-crockford-fanboy ;-p (4认同)
  • `forEach`函数接受第二个可选参数,即函数的绑定.`colours.forEach(function(){/*'this'绑定正确 - >*/},这个);`所以应该添加一个注释,`var that = this`不是_actually_需要`forEach` . (3认同)

El *_*oco 105

来自Crockford

按照惯例,我们做一个私有的是 可变的.这用于使对象可用于私有方法.这是为在ECMAScript的语言规范的错误导致一种变通方法这个不正确地对内部函数来设定.

JS小提琴

function usesThis(name) {
    this.myName = name;

    function returnMe() {
        return this;        //scope is lost because of the inner function
    }

    return {
        returnMe : returnMe
    }
}

function usesThat(name) {
    var that = this;
    this.myName = name;

    function returnMe() {
        return that;            //scope is baked in with 'that' to the "class"
    }

    return {
        returnMe : returnMe
    }
}

var usesthat = new usesThat('Dave');
var usesthis = new usesThis('John');
alert("UsesThat thinks it's called " + usesthat.returnMe().myName + '\r\n' +
      "UsesThis thinks it's called " + usesthis.returnMe().myName);
Run Code Online (Sandbox Code Playgroud)

这提醒......

用途认为它叫做戴夫

UsesThis认为它被称为undefined

  • 我不冒犯.很高兴看到有人在downvoting时发表评论! (16认同)
  • Crockford回答的问题是```变量在他的例子中根本没用过.它看起来好像只是创建一个持有`this`的变量对其余的代码做了一些事情. (4认同)
  • 我看了,不明白,因为它没有细节,在Google上搜索,找到了这个页面.我再次指出同一句话.因此,downvote. (3认同)
  • 这是一个公平的观点,我会说,不熟悉JavaScript的人很难从我的答案中把握这个概念.我确实做了很简单的回答(我确实链接到你用Google搜索的页面..)我说lonesomeday的答案是最清楚的,尽管我仍然喜欢它在普通的JS中而不是jQuery的例子. (3认同)
  • 谢谢,总结一下对我来说. (2认同)

Way*_*inn 84

这是一个让内部函数(在其他函数中定义的函数)更像它们应该工作的hack.在javascript中,当你在另一个函数中定义一个函数时,this自动将其设置为全局范围.这可能会令人困惑,因为您希望this具有与外部函数中相同的值.

var car = {};
car.starter = {};

car.start = function(){
    var that = this;

    // you can access car.starter inside this method with 'this'
    this.starter.active = false;

    var activateStarter = function(){
        // 'this' now points to the global scope
        // 'this.starter' is undefined, so we use 'that' instead.
        that.starter.active = true;

        // you could also use car.starter, but using 'that' gives
        // us more consistency and flexibility
    };

    activateStarter();

};
Run Code Online (Sandbox Code Playgroud)

当您将函数创建为对象的方法(如car.start示例中),然后在该方法内创建函数(如activateStarter)时,这是一个特别的问题.在顶级方法中this指向对象它是(在这种情况下car)的方法,但在内部函数中this现在指向全局范围.这是一种痛苦.

在两个作用域中按惯例创建要使用的变量是javascript的这个非常普遍的问题的解决方案(尽管它在jquery函数中也很有用).这就是使用非常通用的声音名称的that原因.这是一个容易识别的惯例,克服了语言的缺点.

就像El Ronnoco对Douglas Crockford的暗示一样,这是一个好主意.

  • 我想这比接受的答案更有用.因为它澄清了Crockford发明"那个"的原因,而关于jQuery的答案却没有. (8认同)
  • 这实际上是一个比接受的答案更好的例子.道格拉斯说,它解释了"ECMAScript语言规范中的一个错误导致内部函数设置不正确". (4认同)

小智 8

使用的that是不是真的有必要,如果你与使用的解决办法call()apply():

var car = {};
car.starter = {};

car.start = function(){
    this.starter.active = false;

    var activateStarter = function(){
        // 'this' now points to our main object
        this.starter.active = true;
    };

    activateStarter.apply(this);
};
Run Code Online (Sandbox Code Playgroud)