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

Это оповещения...

Использует, что думает, что это называется Дейв

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

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

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

демонстрация

Решение выше будет 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;
};

Вот пример

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

Другие вопросы по тегам