Що означає 'var що = це;' означає в JavaScript?


351

У файлі JavaScript я побачив:

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

Яка мета декларування thatта присвоєння thisцього?


3
можливий дублікат var self = this?
Бергі

6
Злом "цей" і "той" не потрібен для функцій стрілок. З функціями стрілки "це" працює як очікувалося. Дивіться тут для більш детальної інформації ES6 In Depth: Функції стрілки
satguru srivastava

1
тут поняття цього пояснюється scotch.io/@alZami/understanding-this-in-javascript
AL-zami

Чудове пояснення щодо таємничої такої поведінки, заснованої на контексті тут
RBT

Останнє та оновлене пояснення можна знайти тут
Сукрит Гупта

Відповіді:


486

Почну цю відповідь із ілюстрації:

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.


149
Я, як правило, йду з var self = this;. Слово , thatздається, має на увазі змінну нічого АЛЕ this.
Девід Мердок

13
@David Так. Я вважав, що це дещо вводить в оману. Але якщо, як каже Крокфорд, це умова, чи розумно йти цим шляхом. Я повністю згоден з вами, але має набагато більше сенсу.
El Ronnoco

4
@El Ronnoco, але "У нього сиве волосся і страшна борода. Його манера приводити до уваги буркучого старого, який кричить на дітей, щоб зійти з його газону". - blogging.compendiumblog.com/blog/software-for-humans/0/0/… ;-p
Девід Мердок

7
@ElRonnoco: Хоча це звернення до влади. Якщо ми коли-небудь робимо те, що «знамениті люди» кажуть, що нам слід робити, ми прямуємо до катастрофи.
Гонки легкості на орбіті

3
forEachФункція приймає другий необов'язковий аргумент , який є зв'язування функції. colours.forEach(function(){/* 'this' is bound correctly --> */}, this);Тому слід додати примітку, var that = thisяка насправді не потрібна forEach.
Метт Кларксон

107

З Крокфорда

За умовою ми робимо приватну цю змінну. Це використовується, щоб об'єкт став доступним приватним методам. Це тимчасове рішення для помилки в специфікації 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);

Це сповіщення ...

ВикористанняТа думає, що це називається Дейв

ВикористанняЦе вважає, що це називається невизначеним


2
Дякую, підсумовує це досить добре для мене.
Кріс

3
Я прочитав це, не зрозумів, бо не мав деталей, шукав в Google, знайшов цю сторінку. Де мене знову вказують на те саме речення. Звідси і низхідний рух.
Депутат Адітія

3
Це справедливо, я б сказав, що хтось незнайомий JavaScript не матиме труднощів зрозуміти це поняття лише з моєї відповіді. Я відповів дуже коротко (і я посилався на сторінку, яку ви гуглили ..) Я б сказав, що відповідь одинокого дня є найяснішою, хоча я б все-таки вважав за краще це в простому JS, а не в прикладі jQuery.
El Ronnoco

16
Я не ображаюся. Приємно бачити когось, хто коментує, коли викликає супровід!
El Ronnoco

4
Проблема у відповіді Крокфорда полягає в тому, що thatзмінна взагалі не використовується в його прикладі. Це робить його схожим на те, що просто створення змінної холдингу thisщось робить для решти коду.
r3m0t

86

Це злом, щоб внутрішні функції (функції, визначені всередині інших функцій) працювали так, як повинні. У 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
Я вважаю, що це корисніша відповідь, ніж прийнята. Тому що це з'ясовує причину, чому Крокфорд винайшов "те", поки відповідь про jQuery не відповідає.
Костянтин Смолянін

4
Це насправді кращий приклад, ніж прийнята відповідь. Це пояснює, що це як "помилка в специфікації мови ECMAScript, яка призводить до неправильного встановлення внутрішніх функцій", - сказав Дуглас.
kakacii

1
Можливо, ви хочете зробити граматику правильною. Я знаю, що це більше схоже на помилку друку, але це може заплутати початківців JavaScript, оскільки це питання більше для початківців. Я маю на увазі, що це має бути: var car = {}; car.starter = {}; car.start = function () {...}
kakacii

1
@kakacii Дякую Виправлено зараз.
Вейлон Флінн

9

Використання 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

Іноді 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цього ми можемо і доступ до властивості імені всередині sayHiметоду зthat , так що це може бути викликано без проблем всередині виклику DOM.

Інше рішення - призначити порожній thatоб’єкт і додати до нього властивості та методи, а потім повернути його. Але з цим рішенням ви втратили prototypeконструктор.

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

2

Ось приклад `

$(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 ("фон-колір", "# ffe700"); // Тут значення "що" є ".our-work-group> p> a", оскільки значення var що = це; тому, навіть якщо ми знаходимося на "this" = '.our-work-one-page', ми все одно можемо використовувати "that" для маніпулювання попереднім елементом DOM.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.