У файлі JavaScript я побачив:
function Somefunction(){
var that = this;
...
}
Яка мета декларування that
та присвоєння this
цього?
У файлі JavaScript я побачив:
function Somefunction(){
var that = this;
...
}
Яка мета декларування that
та присвоєння this
цього?
Відповіді:
Почну цю відповідь із ілюстрації:
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
.
var self = this;
. Слово , that
здається, має на увазі змінну нічого АЛЕ this
.
forEach
Функція приймає другий необов'язковий аргумент , який є зв'язування функції. colours.forEach(function(){/* 'this' is bound correctly --> */}, this);
Тому слід додати примітку, var that = this
яка насправді не потрібна forEach
.
За умовою ми робимо приватну цю змінну. Це використовується, щоб об'єкт став доступним приватним методам. Це тимчасове рішення для помилки в специфікації ECMAScript мови , який викликає це повинен бути встановлений неправильно для внутрішніх функцій.
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);
Це сповіщення ...
ВикористанняТа думає, що це називається Дейв
ВикористанняЦе вважає, що це називається невизначеним
that
змінна взагалі не використовується в його прикладі. Це робить його схожим на те, що просто створення змінної холдингу this
щось робить для решти коду.
Це злом, щоб внутрішні функції (функції, визначені всередині інших функцій) працювали так, як повинні. У 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
. Це легко впізнавана умова подолання недоліку в мові.
Як Ель Ронноко натякає на Дугласа Крокфорда, вважає, що це гарна ідея.
Використання 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
цього ми можемо і доступ до властивості імені всередині 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", на яке орієнтуєтесь.
`$(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.