В файле 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
.
От Crockford
По соглашению мы создаем , которыйпеременная. Это используется для объект, доступный частному методы. Это временное решение для ошибка в языке 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 called " + usesthat.returnMe().myName + '\r\n' +
"UsesThis thinks it called " + usesthis.returnMe().myName);
Эти предупреждения...
UsesThat считает, что он называется Dave
UsesThis считает, что он называется undefined
Это взломать внутренние функции (функции, определенные внутри других функций), которые работают больше, чем должны. В 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
, тогда мы можем и получить доступ к свойству 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", на которое вы нацеливаете.
`$(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.
Для функций стрелок не требуется "this" и "that". Функции стрелок "this" работают так, как ожидалось. Подробнее см. Здесь ES6 In Depth: функции стрелок