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

时间:2011-02-03 13:21:51

标签: javascript this

在我看到的JavaScript文件中:

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

宣布that并将其分配给this的目的是什么?

6 个答案:

答案 0 :(得分:469)

我将以插图开始这个答案:

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

答案 1 :(得分:103)

来自Crockford

  

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

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认为它被称为未定义

答案 2 :(得分:82)

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

};

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

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

像El Ronnoco的提示Douglas Crockford认为这是一个好主意。

答案 3 :(得分:8)

如果您使用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);
};

答案 4 :(得分:2)

有时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,然后我们可以从sayHi访问that方法中的name属性,这样就可以在没有问题的情况下调用DOM调用。

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

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

答案 5 :(得分:2)

这是一个例子  `

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

        });
    });`

因此,根据您定位的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();
                    }
                });
            }

        });
    });`

..... $(那).css(“background-color”,“#ffe700”); //这里的“那个”值是“.our-work-group&gt; p&gt; a”因为var的值= this;所以即使我们处于“this”=“.our-work-single-page”,我们仍然可以使用“that”来操纵以前的DOM元素。