什么“var that = this” 在JavaScript中的意思是?
在一个JavaScript文件中,我看到:
function Somefunction(){ var that = this; ... }
声明和分配它的目的是什么?
我将以一个例子开始这个答案:
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
作为别名。 这很less显而易见,特别是如果函数比两行更长。 我总是使用更具描述性的别名。 在我上面的例子中,我可能会使用clickedEl
。
从克罗克福德
按照惯例,我们做一个私人的variables。 这用于使对象可用于私有方法。 这是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);
这警报…
用途那认为它叫Dave
UsesThis认为它被称为undefined
这使得内部函数(在其他函数中定义的函数)的工作更像是他们应该做的。 在JavaScript中,当你在另一个函数里面定义一个函数的时候,会自动设置为全局范围。 这可能会令人困惑,因为您期望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(); };
当你创build一个函数作为一个对象的一个方法(例如car.start
),然后在该方法内创build一个函数(如activateStarter
)时,这是一个特别的问题。 在顶层方法中, this
指向的是对象(在本例中是car
)的方法,但是在内部函数中, this
指向了全局范围。 这是一个痛苦。
在这两个范围内创build一个按惯例使用的variables是javascript这个非常普遍的问题的一个解决scheme(尽pipe它在jquery函数中也很有用)。 这就是为什么使用非常普遍的冠冕堂皇的名字。 这是一个克服语言缺陷的容易识别的惯例。
就像El Ronnoco暗示道格拉斯 ·克罗克福德认为这是一个好主意。
如果使用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元素而不是创build的对象。
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
演示
上面的解决scheme将解决this
that
然后我们可以从里面访问sayHi
方法中的name属性,所以可以在DOM调用中没有问题的情况下调用它。
另一个解决scheme是分配一个空的对象并添加属性和方法,然后返回它。 但是用这个解决scheme,你失去了构造函数的prototype
。
var Person = function(name) { var that = {}; that.name = name; that.sayHi = function() { alert(that.name); }; return that; };
这是一个例子`
$(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(); } }); } }); });`
….. $(that).css(“background-color”,“#ffe700”); //这里“that”的值是“.our-work-group> p> a”,因为var的值是this; 所以尽pipe我们在“this”=“.our-work-single-page”,我们仍然可以使用“that”来操纵以前的DOM元素。