【问题标题】:What does 'var that = this;' mean in JavaScript?'var that = this;' 是什么意思?在 JavaScript 中是什么意思?
【发布时间】:2011-06-20 16:10:31
【问题描述】:

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

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

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

【问题讨论】:

标签: javascript this


【解决方案1】:

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

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在你调用一个新函数改变作用域时经常会发生变化,所以你不能通过使用它来访问原始值。将其别名为 that 仍允许您访问 this 的原始值。

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

【讨论】:

  • 我通常选择var self = this;that 这个词似乎暗示变量是任何东西,但 this
  • @David 是的,我认为 有点误导。但是,如果正如克罗克福德所说,这是一个惯例,那么走这条路是否明智。不过我完全同意你的看法,这更有意义。
  • @El Ronnoco,但“他的头发花白,胡须凌乱,他的举止让人想起一个脾气暴躁的老人,他对孩子们大喊大叫,让他们离开他的草坪。” - blogging.compendiumblog.com/blog/software-for-humans/0/0/… ;-p
  • @ElRonnoco:不过,这是对权威的诉求。如果我们只做“名人”说我们应该做的事,我们就会走向灾难。
  • forEach 函数接受第二个可选参数,它是函数的绑定。 colours.forEach(function(){/* 'this' is bound correctly --> */}, this); 所以应该添加一个注释,var that = this 实际上不需要 forEach
【解决方案2】:

来自Crockford

按照惯例,我们将 设为私有 多变的。这是用来制作 私人可用的对象 方法。这是一个解决方法 ECMAScript 语言中的错误 导致 this 的规范 内部函数设置不正确。

JS Fiddle

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

这会提醒...

UsesThat 认为它叫 Dave

UsesThis 认为它​​被称为 undefined

【讨论】:

  • 谢谢,对我来说总结得很好。
  • 我看了,没看懂,因为没有详细信息,在谷歌上搜索,找到了这个页面。我再次指向同一句话的地方。因此投反对票。
  • 这是一个公平的观点,我想说不熟悉 JavaScript 的人很难仅从我的回答中掌握这个概念。我确实非常简短地回答了(并且我确实链接到了您在 Google 上搜索的页面..)我会说 lonesomeday 的答案是最清楚的,尽管我仍然更喜欢纯 JS 而不是 jQuery 示例。
  • 我无意冒犯。很高兴看到有人投反对票!
  • Crockford 的答案的问题是 that 变量在他的示例中根本没有使用。它看起来好像只是创建一个持有 this 的变量对其余代码有作用​​。
【解决方案3】:

这是一种使内部函数(在其他函数中定义的函数)更像它们应该工作的技巧。在 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 认为这是个好主意。

【讨论】:

  • 我想这是一个比接受的答案更有用的答案。因为它阐明了为什么 Crockford 发明了“那个”,而关于 jQuery 的答案却没有。
  • 这实际上是一个比公认答案更好的例子。它解释了 Douglas 所说的“ECMAScript 语言规范中的错误导致内部函数设置不正确”的情况。
  • 您可能希望使其语法正确。我知道这更像是一个错字,但它可能会使 javascript 初学者感到困惑,因为这个问题更像是初学者。我的意思是它应该是: var car = {}; car.starter = {};car.start = function(){...}
  • @kakacii 谢谢。现已修复。
【解决方案4】:

如果您使用call()apply() 进行变通,则实际上不需要使用that

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

【讨论】:

    【解决方案5】:

    有时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
    

    Demo

    上面的解决方案会将this 分配给that,然后我们可以从that 访问sayHi 方法中的name 属性,因此可以在DOM 调用中毫无问题地调用它。

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

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

    【讨论】:

      【解决方案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("background-color", "#ffe700"); //这里“that”的值为".our-work-group > p > a" 因为 var that = this 的值;所以即使我们在 "this"= '.our-work-single-page',我们仍然可以使用 "that" 来操作之前的 DOM 元素。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-11
        • 2014-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-29
        • 2011-11-18
        • 1970-01-01
        相关资源
        最近更新 更多