Полностью усвойте назначение this в JavaScript, рассейте туман, окружающий this, и поймите, кто определяет направление this После прочтения этой статьи вы сможете определить направление this до запуска кода.
Мы все видели это в функциях по-разному, но до сих пор не можем точно определить, к кому это относится в JavaScript, эта статья даст вам полное представление об этом.
5 больших правил
(1) Если новое ключевое слово появляется перед вызываемой функцией, механизм JavaScript создаст новый объект, и это в вызываемой функции указывает на вновь созданную функцию.
function ConstructorExample() {
console.log(this);
this.value = 10;
console.log(this);
}
new ConstructorExample();
// -> ConstructorExample {}
// -> ConstructorExample { value: 10 }
(2) Если функция запускается с помощью применения, вызова или привязки, то this в функции указывает на первый параметр входящей функции.
function fn() {
console.log(this);
}
var obj = {
value: 5
};
var boundFn = fn.bind(obj);
boundFn(); // -> { value: 5 }
fn.call(obj); // -> { value: 5 }
fn.apply(obj); // -> { value: 5 }
(3) Если функция является методом объекта, и объект использует точку для запуска функции, то this указывает на объект, функция которого является свойством этого объекта, то есть this указывает на объект слева периода.
var obj = {
value: 5,
printThis: function() {
console.log(this);
}
};
obj.printThis(); // -> { value: 5, printThis: ƒ }
(4) Если функция вызывается как FFI, это означает, что функция не соответствует ни одному из вышеперечисленных методов вызова, и это указывает на глобальный объект, которым является окно в браузере.
var obj = {
value: 5,
printThis: function() {
console.log(this);
}
};
obj.printThis(); // -> { value: 5, printThis: ƒ }
Обратите внимание, что правило 4 очень похоже на правило 3, за исключением того, что когда функция вызывается не как метод, она автоматически неявно программирует свойство глобального объекта — окна. То есть, когда мы вызываем fn(), это можно понимать как window.fn() Согласно третьему правилу this в функции fn() указывает на окно.
var obj = {
value: 5,
printThis: function() {
console.log(this);
}
};
obj.printThis(); // -> { value: 5, printThis: ƒ }
(5) Если вышеуказанные правила накапливаются, приоритет уменьшается с 1 до 4, и балл этого оценивается в соответствии с правилом с наивысшим приоритетом.
Применяйте правила на практике
Взгляните на пример кода и используйте приведенные выше правила, чтобы определить, на что это указывает.
var obj = {
value: 'hi',
printThis: function() {
console.log(this);
}
};
var print = obj.printThis;
obj.printThis(); // -> {value: "hi", printThis: ƒ}
print(); // -> Window {stop: ƒ, open: ƒ, alert: ƒ, ...}
obj.prinThis() , согласно третьему правилу это указывает на obj. Согласно четвертому правилу print() — это FFI, так что это указывает на window.
Фактически, приведенный выше пример также исследует разницу между вашим значением и ссылкой в JavaScript, вы можете прочитать эту статью:
Примитивные значения против эталонных значений в JavaScript.
Метод printThis в объекте obj на самом деле является ссылкой на адрес функции, когда мы присваиваем obj.printThis для печати, print также содержит ссылку на функцию, которая не имеет ничего общего с объектом obj. obj — это просто свойство, которое имеет ссылку на эту функцию.
Когда функция не запускается объектом obj, эта функция является FFI.
Применить несколько правил
При наличии нескольких вышеуказанных правил "выигрывает" правило с более высоким приоритетом. Если правило 2 и правило 3 существуют одновременно, правило 2 имеет приоритет:
var obj1 = {
value: 'hi',
print: function() {
console.log(this);
},
};
var obj2 = { value: 17 };
obj1.print.call(obj2); // -> { value: 17 }
Если Правило 1 и Правило 3 применяются одновременно, Правило 1 имеет приоритет:
var obj1 = {
value: 'hi',
print: function() {
console.log(this);
},
};
new obj1.print(); // -> print {}
Библиотека указана в коде?
Некоторые библиотеки привязывают этот указатель к более полезному объекту, например библиотека jQuery, в обработчиках событий этот указатель не привязывается к глобальному объекту, а привязывается к объекту элемента. Поэтому, если вы обнаружите что-то, что не может быть объяснено вышеуказанными 5 правилами, пожалуйста, прочитайте официальную документацию библиотеки, которую вы используете, чтобы узнать, как библиотека изменяет этот момент, обычно через метод привязки.