8.0 KiB
title | localeTitle |
---|---|
this reference | эта ссылка |
this
ссылка
В JavaScript каждая функция имеет this
ссылку, автоматически создаваемую при ее объявлении. Эта ссылка очень похожа на this
ссылку на других языках на основе классов, таких как Java или C # (JavaScript - это язык, основанный на прототипе, и не понятие «класс»): он указывает, какой объект вызывает функцию (этот объект иногда называемый контекстом ). Однако в JavaScript this
ссылка внутри функций может быть привязана к различным объектам в зависимости от того, где вызывается функция . Вот 5 основных правил для this
привязки в JavaScript:
Правило 1
Когда функция вызывается в глобальной области, this
ссылка по умолчанию привязана к глобальному объекту ( window
в браузере или global
в Node.js). Например:
function foo() {
this.a = 2;
}
foo();
console.log(a); // 2
Примечание. Если вы объявляете функцию foo()
выше в строгом режиме, вы вызываете эту функцию в глобальной области, this
будет undefined
и присваивание this.a = 2
будет Uncaught TypeError
исключение this.a = 2
.
Правило 2
Рассмотрим ниже пример:
function foo() {
this.a = 2;
}
var obj = {
foo: foo
};
obj.foo();
console.log(obj.a); // 2
Очевидно, что в приведенном выше фрагменте функция foo()
вызывается с контекстом, является объектом obj
и this
ссылка теперь привязана к obj
. Поэтому, когда функция вызывается с объектом контекста, this
ссылка будет привязана к этому объекту.
Правило 3
.call
, .apply
и .bind
могут быть использованы на сайте вызова, чтобы явно привязать this
. Использование .bind(this)
- это то, что вы можете увидеть в довольно многих компонентах React.
var foo = function() {
console.log(this.bar)
}
foo.call({ bar: 1 }) // 1
Вот краткий пример того , как каждый из них используется , чтобы связать this
:
.call()
:fn.call(thisObj, fnParam1, fnParam2)
.apply()
:fn.apply(thisObj, [fnParam1, fnParam2])
.bind()
:const newFn = fn.bind(thisObj, fnParam1, fnParam2)
Правило 4
function Point2D(x, y) {
this.x = x;
this.y = y;
}
var p1 = new Point2D(1, 2);
console.log(p1.x); // 1
console.log(p1.y); // 2
То, что вы должны заметить, это функция Point2D
new
ключевым словом, и this
ссылка привязана к объекту p1
. Поэтому, когда функция вызывается с new
ключевым словом, она создаст новый объект, и this
ссылка будет привязана к этому объекту.
Примечание. Когда вы вызываете функцию с new
ключевым словом, мы также называем ее конструкторной функцией .
Правило 5
JavaScript определяет значение this
во время выполнения, исходя из текущего контекста. Таким образом, this
может иногда указывать на то, что вы ожидаете.
Рассмотрим этот пример класса Cat с методом под названием makeSound()
, следуя шаблону в правиле 4 (выше) с помощью функции-конструктора и new
ключевого слова.
var Cat = function(name, sound) {
this.name = name;
this.sound = sound;
this.makeSound = function() {
console.log( this.name + ' says: ' + this.sound );
};
}
var kitty = new Cat('Fat Daddy', 'Mrrooowww');
kitty.makeSound(); // Fat Daddy says: Mrrooowww
Теперь давайте попробуем дать кошке способ annoy()
людей, повторяя его звук 100 раз, каждые полсекунды.
var Cat = function(name, sound) {
this.name = name;
this.sound = sound;
this.makeSound = function() {
console.log( this.name + ' says: ' + this.sound );
};
this.annoy = function() {
var count = 0, max = 100;
var t = setInterval(function() {
this.makeSound(); // <-- this line fails with `this.makeSound is not a function`
count++;
if (count === max) {
clearTimeout(t);
}
}, 500);
};
}
var kitty = new Cat('Fat Daddy', 'Mrrooowww');
kitty.annoy();
Это не работает, потому что внутри обратного вызова setInterval
мы создали новый контекст с глобальной областью, поэтому this
больше не указывает на наш экземпляр киски. В веб - браузере, this
будет вместо этого указывать на объект Window, который не имеет makeSound()
метод.
Несколько способов заставить его работать:
- Перед созданием нового контекста, присвоить
this
значение локальной переменной с именемme
, илиself
, или что вы хотите назвать его, и использовать эту переменную внутри функции обратного вызова.
var Cat = function(name, sound) {
this.name = name;
this.sound = sound;
this.makeSound = function() {
console.log( this.name + ' says: ' + this.sound );
};
this.annoy = function() {
var count = 0, max = 100;
var self = this;
var t = setInterval(function() {
self.makeSound();
count++;
if (count === max) {
clearTimeout(t);
}
}, 500);
};
}
var kitty = new Cat('Fat Daddy', 'Mrrooowww');
kitty.annoy();
- С ES6 вы можете не назначать
this
локальную переменную с помощью функции стрелки, которая связываетthis
с контекстом окружающего кода, где она определена.
var Cat = function(name, sound) {
this.name = name;
this.sound = sound;
this.makeSound = function() {
console.log( this.name + ' says: ' + this.sound );
};
this.annoy = function() {
var count = 0, max = 100;
var t = setInterval(() => {
this.makeSound();
count++;
if (count === max) {
clearTimeout(t);
}
}, 500);
};
}
var kitty = new Cat('Fat Daddy', 'Mrrooowww');
kitty.annoy();