JavaScript 中的“var that = this;”是什么意思?

What does 'var that = this;' mean in JavaScript?

提问人:Chris 提问时间:2/3/2011 最后编辑:El RonnocoChris 更新时间:11/21/2019 访问量:147164

问:

在一个JavaScript文件中,我看到:

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

声明并分配给它的目的是什么?thatthis

javascript 这个

评论

3赞 Bergi 1/14/2015
var self = this 的可能重复项?
9赞 satguru srivastava 4/27/2017
箭头函数不需要“this”和“that”hack。使用箭头功能,“this”按预期工作。有关更多详细信息,请参阅此处 ES6 深度分析:箭头函数
1赞 AL-zami 9/11/2017
这里解释这个概念 scotch.io/@alZami/understanding-this-in-javascript
0赞 RBT 10/23/2017
这里是基于上下文的神秘这种行为的一个很好的解释
1赞 Sukrit Gupta 5/10/2019
最新和更新的解释可以在这里找到

答:

117赞 El Ronnoco 2/3/2011 #1

克罗克福德

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

这会提醒...

用途认为它叫戴夫

用途这认为它被称为未定义

评论

2赞 Chris 2/3/2011
谢谢,对我来说总结得很好。
3赞 Aditya M P 2/21/2013
我读了它,不明白,因为它没有细节,在谷歌上搜索,找到了这个页面。我再次指向同一句话。因此投了反对票。
3赞 El Ronnoco 2/21/2013
这是一个公平的观点,我想说不熟悉 JavaScript 的人很难仅从我的回答中掌握这个概念。我确实回答得非常简短(我确实链接到了你用谷歌搜索的页面..)我会说 lonesomeday 的答案是最清楚的,尽管我仍然更喜欢纯 JS 而不是 jQuery 示例。
17赞 El Ronnoco 2/22/2013
我不冒犯。很高兴看到有人在投反对票时发表评论!
5赞 r3m0t 7/4/2013
Crockford回答的问题是,他的示例中根本没有使用该变量。它看起来好像只是创建一个变量持有对代码的其余部分做了一些事情。thatthis
520赞 lonesomeday 2/3/2011 #2

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

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

由于在通过调用新函数更改范围时会频繁更改,因此无法使用它访问原始值。将其别名化允许您仍能访问 的原始值。thisthatthis

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

评论

162赞 David Murdoch 2/3/2011
我通常和.这个词似乎暗示变量是 BUT .var self = this;thatthis
13赞 El Ronnoco 2/3/2011
@David 是的,我认为这有点误导。但是,如果像克罗克福德所说的那样,这是一个惯例,那么走这条路是否明智。不过,我完全同意你的看法,这更有意义。
5赞 David Murdoch 2/4/2011
@El Ronnoco,但“他有一头白发,胡须凌乱,他的举止让人想起一个脾气暴躁的老人,他对孩子们大喊大叫,让他们从草坪上下来 blogging.compendiumblog.com/blog/software-for-humans/0/0/
8赞 Lightness Races in Orbit 1/18/2013
@ElRonnoco:不过,这是对权威的诉求。如果我们只做“名人”说我们应该做的事情,我们就会走向灾难。
5赞 Matt Clarkson 4/8/2015
该函数采用第二个可选参数,即函数的绑定。 因此,应该添加一个实际上不需要的注释。forEachcolours.forEach(function(){/* 'this' is bound correctly --> */}, this);var that = thisforEach
91赞 Waylon Flinn 6/17/2012 #3

这是一个使内部函数(在其他函数中定义的函数)更像它们应该的那样工作的技巧。在 javascript 中,当您在另一个函数中定义一个函数时,会自动设置为全局范围。这可能会造成混淆,因为您希望具有与外部函数中相同的值。thisthis

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.startactivateStarterthiscarthis

创建一个变量以在两个作用域中按约定使用是 javascript 这个非常普遍的问题的解决方案(尽管它在 jquery 函数中也很有用)。这就是为什么使用听起来非常笼统的名称的原因。这是一个易于识别的约定,用于克服语言中的缺点。that

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

评论

8赞 Konstantin Smolyanin 7/17/2013
我想这是比公认的答案更有用的答案。因为它澄清了为什么Crockford发明了“那个”,而关于jQuery的答案却没有。
5赞 kakacii 7/22/2013
这实际上是一个比公认的答案更好的例子。Douglas说,它解释了“ECMAScript语言规范中的一个错误,导致内部函数的设置不正确”。
1赞 kakacii 7/22/2013
不过,您可能希望使其语法正确。我知道这更像是一个错别字,但它可能会让 javascript 初学者感到困惑,因为这个问题更像是初学者。我的意思是它应该是:var car = {};汽车启动器 = {};car.start = 函数(){...}
3赞 Ahmad Ajmi 11/1/2014 #4

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

[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

演示

上面的解决方案将保证我们可以从 中访问方法中的 name 属性,因此可以在 DOM 调用中毫无问题地调用它。thisthatsayHithat

另一种解决方案是分配一个空对象并向其添加属性和方法,然后返回它。但是使用这个解决方案,你失去了构造函数。thatprototype

var Person = function(name) {
  var that = {};
  that.name = name;
  that.sayHi = function() {
    alert(that.name);
  };
  return that;
};
11赞 Adela 11/15/2015 #5

如果您使用 or 进行解决方法,则实际上没有必要使用 :thatcall()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);
};
2赞 stacksonstacksonstacks 12/1/2015 #6

下面是一个示例 `

$(document).ready(function() {
        var lastItem = null;
        $(".our-work-group > p > a").click(function(e) {
            e.preventDefault();

            var item = $(this).html(); //Here value of "this" is ".our-work-group > p > a"
            if (item == lastItem) {
                lastItem = null;
                $('.our-work-single-page').show();
            } else {
                lastItem = item;
                $('.our-work-single-page').each(function() {
                    var imgAlt = $(this).find('img').attr('alt'); //Here value of "this" is '.our-work-single-page'. 
                    if (imgAlt != item) {
                        $(this).hide();
                    } else {
                        $(this).show();
                    }
                });
            }

        });
    });`

因此,您可以看到 this 的值是两个不同的值,具体取决于您目标的 DOM 元素,但是当您将“that”添加到上面的代码中时,您将更改目标“this”的值。

`$(document).ready(function() {
        var lastItem = null;
        $(".our-work-group > p > a").click(function(e) {
            e.preventDefault();
            var item = $(this).html(); //Here value of "this" is ".our-work-group > p > a"
            if (item == lastItem) {
                lastItem = null;
                var that = this;
                $('.our-work-single-page').show();
            } else {
                lastItem = item;
                $('.our-work-single-page').each(function() {
                   ***$(that).css("background-color", "#ffe700");*** //Here value of "that" is ".our-work-group > p > a"....
                    var imgAlt = $(this).find('img').attr('alt'); 
                    if (imgAlt != item) {
                        $(this).hide();
                    } else {
                        $(this).show();
                    }
                });
            }

        });
    });`

.....$(that).css(“背景色”, “#ffe700”);这里 “that” 的值是 “.our-work-group > p > a”,因为 var 的值 = this;因此,即使我们在 “this”= '.our-work-single-page',我们仍然可以使用 “that” 来操作以前的 DOM 元素。