Введение
this - это специальный идентификатор, который определяется в области видимости функции.
Основные преимущества this заключаются в том, что он позволяет переиспользовать функции.
function foo(num) {
console.log("foo" + num);
this.count++;
}
foo.count = 0;
var i;
for (i = 0; i < 10; i++) {
if (i > 5) {
foo(i);
}
}
// foo: 6
// foo: 7
// foo: 8
// foo: 9Функция foo() была вызвана 0 раз!!!
Это так, потому что this.count указывает не на объект , а на созданную глобальную переменную.
this не связана с областью видимости так, как мы это понимаем.
Что такое this ?
При вызове функции активируется “запись активации”, также называемая контекстом выполнения.
Запись содержит информацию откуда была вызвана функция (стек вызовов) , как она вызвана, какие параметры были переданы и так далее.
Одни из свойств этой записи при передачи является ссылка this .
Первое правило: use strict
#useStrict Если действует режим strict : глобальный объект на момент исполнения используется для связывания по умолчанию, поэтому, вместо этого присваивается undefined.
function foo() {
"use strict";
console.log(this.a);
}
var a = 2;
foo(); // TypeError this is undefinedНо, при этом
function foo () {
console.log(this.a)
var a = 2
}
...
(function) () {
"use strict"
foo() //2
} ()
Второе правило: Неявное связывание
- Наличие у места вызова контекстного объекта - владельца.
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
foo: foo, // вызывает функцию foo
};
obj.foo(); //2- Для теста вызова важен только верхний и последний уровень
function foo() {
console.log(this.a);
}
var obj2 = {
a: 42,
foo: foo, // вызывает функцию foo()
};
var obj1 = {
a: 2,
obj2: obj2, // вызывает var obj2
};
obj1.obj2.foo; //42- Неявная потеря
this
ключевое: теряется связывание, возвращается связывание по умолчанию - глобального объекта или undefined.
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
foo: foo,
};
var bar = obj.foo;
var a = "oops, Global!"; // глобальное свойство
bar(); // oops, Global!- Потеря связывания
thisобратными вызовами.
Третье правило: Явное связывание
В первом параметре метода содержится объект, который используется для this
Мы напрямую указываем какое значение должно использоваться для this
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
};
foo.call(obj); //2- Жёсткое связывание
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
};
var bar = function () {
foo.call(obj);
};
bar(); //2
setTimeOut(bar, 1000); //2
bar.call(window); //2- Контексты вызовов API
Функции многих библиотек , а также многие … поддерживают context, который избавляет нас от необходимости использовать#bind, чтобы функция гарантировала использование this.
function foo(el) {
console.log(el, this.id);
}
var obj = {
id: "awesome",
}[(1, 2, 3)].forEach(foo, obj);Четвёртое правило: Связывание с new
Когда функция вызывается после оператора new (такие вызовы называются вызовами-конструкторами), они автоматически выполняют следующие действия:
- Конструируются как новый объект
- Производят его связывание с
[[Prototype]] - Сконструированный объект назначается в качестве связывания
thisдля этого вызова функции - Если функция не возвращает свой альтернативный объект, то вызов функции автоматически возвращает сконструированный объект.
function foo(a) {
this.a = a;
}
var bar = new foo(2);
console.log(bar.a); //2Определение this
- Функция вызова с new
- Функция вызвана с call и apply
- Функция вызвана с контекстом
thisпо умолчанию приuse strictлибо undefined или global
Исключения:
Если передать в this (call, bind и apply) значение null или undefined , то значения фактически игнорируются.
function foo() {
console.log(this.a);
}
var a = 2;
foo.call(null); //2Лексическое поведение this
Лексическая область видимости стрелочной функции:
function foo() {
return (a) => {
//`this` здесь лексически наследуется от foo()
console.log(this.a);
};
}
var obj1 = {
a: 2,
};
var obj2 = {
a: 3,
};
var bar = foo.call(obj1);
bar.call(obj2); // 2, а не 3!Лексическое связывание стрелочной функции не может быть переопределено даже с new. Распространённое использование - это колбеки.
call, bind, apply
Объекты существуют в двух форматах:
- литеральной
var myObj = {
key: value,
};- конструированной
var myObj = new Object();
myObj.key = value;
var myObj = {
a: 4,
writable: true,
configurable: false,
enumerable: true,
};