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

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

声明它并将它赋值给它的目的是什么?


当前回答

从Crockford

按照惯例,我们创建一个private that 变量。这是用来制作 对象对私有对象可用 方法。这是一个变通方法 错误在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);

这个警报……

UsesThat认为它叫Dave UsesThis认为它是未定义的

其他回答

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

上面的解决方案将把这个传递给那个,然后我们可以从sayHi方法中访问name属性,所以在DOM调用中可以没有问题地调用这个。

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

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

从Crockford

按照惯例,我们创建一个private that 变量。这是用来制作 对象对私有对象可用 方法。这是一个变通方法 错误在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);

这个警报……

UsesThat认为它叫Dave UsesThis认为它是未定义的

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

这里有一个例子 `

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

        });
    });`

…(美元). css(“背景颜色”,“# ffe700”);//这里的"that"的值是"。Our-work-group > p > a"因为var that = this的值;所以即使我们在"this"= '。we -work-single-page’,我们仍然可以使用“that”来操作前面的DOM元素。

我将以一个例子开始回答这个问题:

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

因为当您通过调用新函数来更改作用域时,这个值经常会发生变化,因此您不能通过使用它来访问原始值。把它混叠成这样,你仍然可以访问这个的原始值。

就我个人而言,我不喜欢用那个作为别名。它指的是什么并不明显,特别是如果函数的长度超过几行。我总是用一个更有描述性的别名。在上面的例子中,我可能会使用clickedEl。