Что значит «вар это = это»? значит в JavaScript? - PullRequest
340 голосов
/ 03 февраля 2011

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

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

Какова цель объявления that и присвоения его this?

Ответы [ 6 ]

473 голосов
/ 03 февраля 2011

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

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.

103 голосов
/ 03 февраля 2011

С Крокфорд

По договоренности мы создаем приватную переменную , которая .Это используется, чтобы сделать объект доступным для приватных методов.Это обходной путь для ошибки в спецификации языка ECMAScript, которая приводит к неправильной установке this для внутренних функций.

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 думает, что это называется Dave

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

82 голосов
/ 16 июня 2012

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

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

8 голосов
/ 15 ноября 2015

Использование 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);
};
3 голосов
/ 01 ноября 2014

Иногда 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;
};
2 голосов
/ 01 декабря 2015

Вот пример `

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

...