Отслеживание того, на что ссылается this в функции JavaScript, может быть сложным и временами запутанным. Цель этой статьи — сделать это ключевое слово более понятным раз и навсегда, так что давайте начнем.
‘это’вне функции.
В контексте глобального выполнения this принимает значение глобального объекта ( globalв Node JS и окно в браузере).
var globalObject = this; /* Node js */ globalObject === global; //true /* Browser */ globalObject === window; //true
this внутри функции.
Значение thisвнутри функциизадается во время вызова функции с использованием любого из методов доступа к свойствам (' . ' или ' [ ] ').
- Когда функция вызывается с помощью ‘ . ’, this устанавливается на соответствующий объект контекста.
- Когда функция вызывается без использования оператора ' . ', this по умолчанию будет глобальным объектом (этот тип функции обычно называется «простой вызов»).
Теперь давайте попробуем несколько примеров, чтобы прояснить мою точку зрения.
- Пример 1:
function f1() { return this; } var myObj = { method: f1 } f1() === global; //true myObj.method() === myObj; //true
- Пример 2:
var myObj = { method: function() { return this; } } myObj.method() === myObj; //true var f = myObj.method; f() === global; //true
Здесь обратите внимание, что хотя функция находится внутри myObj, ее это значение устанавливается как глобальное при использовании ссылки.
- Пример 3:
function add(a, b, callback) { callback(a + b); } var myObj = { p: 1, q: 2, findSum: function() { add(this.p, this.q, function(sum) { console.log(sum); console.log(this === global); }); } }; myObj.findSum(); */ prints the following output. 3 true */
Здесь обратный вызов вызывается простым вызовом, поэтому this по умолчанию будет глобальным. Поскольку это относится к каждому обратному вызову в JS, мы можем сделать вывод ..
Каждая функция обратного вызова имеет привязку this global, если иное this не задано явно .
Достаточно примеров, теперь мы посмотрим, как изменить это поведение по умолчанию…
вызвать() и применить():
Всякий раз, когда функция вызывается, она может привязываться к контексту по нашему выбору с помощью call() или apply().
function greetPerson (firstName, secondName) { var greetings = this.greet + ' ' + firstName + ' ' + secondName; console.log(greetings); } var obj1 = { greet: 'Hello' }; var obj2 = { greet: 'Ola' }; /* call({context}, param1, param2...) */ greetPerson.call(obj1, 'Pavan', 'Varma') // Hello Pavan Varma greetPerson.call(obj2, 'Pavan', 'Varma') // Ola Pavan Varma /* apply({context},[param1, param2...]) */ greetPerson.apply(obj1, ['Pavan', 'Varma']) // Hello Pavan Varma greetPerson.apply(obj2, ['Pavan', 'Varma']) // Ola Pavan Varma
связать():
У каждой функции есть метод-прототипbind, который при вызове с каким-либо объектом создает новую копию этой функции, привязанную к этому объекту.
function greetPerson (firstName, secondName) { var greetings = this.greet + ' ' + firstName + ' ' + secondName; console.log(greetings); } var obj1 = { greet: 'Hello' }; var obj2 = { greet: 'Ola' }; /* A new function bound to obj1 */ var greetPersonHello = greetPerson.bind(obj1); greetPersonHello('Pavan', 'Varma'); // Hello Pavan Varma greetPerson.call(obj2, 'Pavan', 'Varma'); // Ola Pavan Varma
JavaScript использует эти приемы за кулисами для реализации функций конструктора.
function Person(firstName, secondName) { this.firstName = firstName; this.secondName = secondName; } var p = new Person('Pavan', 'Varma');
Ключевое слово new создает совершенно новый пустой объект, вызывает указанную функцию с this, установленным для этого объекта, а затем возвращает его (Вы также можете видеть, что функция ничего не возвращает).
Это все, что касается этого, удачного программирования (-_-).