'var that = this;' 是什么意思 在 JavaScript 中是什么意思?

IT技术 javascript this
2021-01-25 12:10:45

在我看到的 JavaScript 文件中:

function Somefunction(){
   var that = this; 
   ... 
}

声明that并将其分配this给它的目的是什么?

6个回答

我将用一个插图开始这个答案:

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
    });
});

我的回答最初用 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
    });
});

因为this通过调用新函数更改作用域时经常会发生变化,所以无法通过使用它来访问原始值。将其别名为 tothat允许您仍然访问this.

就个人而言,我不喜欢使用thatas 别名。它所指的内容很少是显而易见的,尤其是当函数长度超过几行时。总是使用更具描述性的别名。在我上面的例子中,我可能会使用clickedEl.

我通常和var self = this;. 这个词that似乎暗示变量是任何 BUT this
2021-03-12 12:10:45
@ElRonnoco:不过,这是对权威的呼吁。如果我们只做“名人”所说的我们应该做的事情,我们就会走向灾难。
2021-03-12 12:10:45
@El Ronnoco,但是“他头发花白,胡须凌乱,他的举止让人想起一个脾气暴躁的老人,他对孩子们大喊大叫,让他离开草坪。” - blogging.compendiumblog.com/blog/software-for-humans/0/0/... ;-p
2021-03-23 12:10:45
@David 是的,我认为有点误导。但是,如果正如克罗克福德所说,这是一种惯例,那么沿着这条路走下去是否明智。不过我完全同意你的看法,这更有意义。
2021-04-02 12:10:45
forEach函数采用第二个可选参数是该函数的绑定。colours.forEach(function(){/* 'this' is bound correctly --> */}, this);因此,一个音符应该说,var that = this是不是真正需要用forEach
2021-04-03 12:10:45

克罗克福德

按照惯例,我们将该 变量设为私有这用于使对象可用于私有方法。这是为在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);

这提醒...

用途那认为它叫戴夫

UsesThis 认为它​​被称为 undefined

这是一个公平的观点,我会说不熟悉 JavaScript 的人很难仅从我的回答中理解这个概念。我确实回答得很简短(我确实链接到了你用谷歌搜索过的页面……)我会说孤独日的答案是最清楚的,尽管我仍然更喜欢纯 JS 而不是 jQuery 示例。
2021-03-10 12:10:45
我无意冒犯。很高兴看到有人在投票时发表评论!
2021-03-20 12:10:45
我读过,不明白,因为它没有细节,在谷歌上搜索,找到了这个页面。我再次指向同一句话的地方。因此投反对票。
2021-03-23 12:10:45
谢谢,对我来说总结得很好。
2021-03-31 12:10:45
Crockford 的答案的问题that在于他的示例中根本没有使用变量。它看起来好像只是创建一个变量持有this对其余代码做了一些事情。
2021-04-01 12:10:45

这是一种使内部函数(在其他函数中定义的函数)更像它们应该工作的方法。在 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();

};

当您将函数创建为对象的方法(如car.start示例中)然后在该方法中创建函数(如activateStarter时,这尤其是一个问题在顶级方法中this指向对象,它是(在本例中为 )的方法,car但在内部函数中this现在指向全局作用域。这是一种痛苦。

创建一个在两个范围内按约定使用的变量是解决这个非常普遍的 javascript 问题的解决方案(尽管它在 jquery 函数中也很有用)。这就是使用非常通用的名称的that原因。这是克服语言缺陷的一种易于识别的约定。

就像 El Ronnoco 暗示道格拉斯·克罗克福德(Douglas Crockford)认为这是个好主意一样。

@kakacii 谢谢。现在固定。
2021-03-10 12:10:45
这实际上是一个更好的例子然后接受的答案。它解释了 Douglas 所说的“ECMAScript 语言规范中的一个错误,导致内部函数的设置不正确”。
2021-03-22 12:10:45
我想这是比接受的答案更有用的答案。因为它阐明了为什么 Crockford 发明了“那个”而关于 jQuery 的答案没有。
2021-04-09 12:10:45
不过,您可能希望使其语法正确。我知道这更像是一个错字,但它可能会让 JavaScript 初学者感到困惑,因为这个问题更像是初学者。我的意思是应该是:var car = {}; car.starter = {};car.start = function(){...}
2021-04-09 12:10:45

使用的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);
};

有时this可以引用另一个范围并引用其他内容,例如假设您想在 DOM 事件中调用构造函数方法,在这种情况下this将引用 DOM 元素而不是创建的对象。

HTML

<button id="button">Alert Name</button>

JS

var Person = function(name) {
  this.name = name;
  var that = this;
  this.sayHi = function() {
    alert(that.name);
  };
};

var ahmad = new Person('Ahmad');
var element = document.getElementById('button');
element.addEventListener('click', ahmad.sayHi); // => Ahmad

演示

上面的解决方案将this帮助that我们可以访问方法中的 name 属性sayHifrom that,因此可以在 DOM 调用中调用它而不会出现问题。

另一种解决方案是分配一个空that对象并为其添加属性和方法,然后返回它。但是使用此解决方案,您丢失prototype了构造函数的 。

var Person = function(name) {
  var that = {};
  that.name = name;
  that.sayHi = function() {
    alert(that.name);
  };
  return that;
};