Что означает "var that = this;" в JavaScript?

в файле JavaScript я увидел:

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

какова цель объявления that и назначении его this?

6 ответов


Я собираюсь начать этот ответ с иллюстрацией:

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 как псевдоним. Редко бывает очевидно, о чем идет речь, особенно если функции длиннее пары строк. Я!--14-->всегда использовать более описательное имя. В приведенных выше примерах я бы, вероятно, использовал clickedEl.


С Крокфорд

по соглашению, мы делаем частный это переменная. Это использовано для того чтобы сделать объект, доступный для частного методы. Это делается для ошибка в языке 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 думает, его зовут Дэйв!--4-->

UsesThis думает, что это называется undefined


это хак, чтобы сделать внутренние функции (функции, определенные внутри других функций) больше работают, как они должны. В 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 не требуется, если вы делаете обходной путь с использованием 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, а не на созданный объект.

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

демо

решение выше будет assing this to that тогда мы можем и получить доступ к свойству name внутри sayHi способ от that, поэтому это можно вызвать без проблем внутри вызова DOM.

другое решение-назначить пустой that object и добавьте к нему свойства и методы, а затем верните его. Но с этим решением вы потеряли 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();
                    }
                });
            }

        });
    });`

таким образом, вы можете видеть, что значение this-это два разных значения в зависимости от целевого элемента DOM, но когда вы добавляете "это" в код выше, вы изменяете значение "это", которое вы нацеливаете.

`$(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 > p > a "потому что значение var that = this; поэтому, даже если мы находимся в "this"= '.our-work-single-page', все еще мы можем использовать" это " для управления предыдущим элементом DOM.