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

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

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

Какова цель объявления that и назначения его 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.

Ответ 2

От 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 called " + usesthat.returnMe().myName + '\r\n' +
      "UsesThis thinks it called " + usesthis.returnMe().myName);

Эти предупреждения...

UsesThat считает, что он называется Dave

UsesThis считает, что он называется undefined

Ответ 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. Это легко узнаваемая конвенция для преодоления недостатка на языке.

Как подсказывает Эль Ронноко Дуглас Крокфорд считает, что это хорошая идея.

Ответ 4

Использование 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);
};

Ответ 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

Демо

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

        });
    });`

Таким образом, вы можете видеть, что это значение два разных значения в зависимости от выбранного элемента DOM, но когда вы добавляете "это" в код выше, вы изменяете значение "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; поэтому, хотя мы находимся в "this"= '.our-work-single-page', мы можем использовать "это" для управления предыдущим элементом DOM.

Ответ 7

Для функций стрелок не требуется "this" и "that". Функции стрелок "this" работают так, как ожидалось. Подробнее см. Здесь ES6 In Depth: функции стрелок