-
1. Когда движок JS идёт по коду сверху вниз (интерпретирует код), на каждую ф-цию он
составляет свой контекст вызова. Контекст вызова - своеобразный "документ", который
полностью описывает функцию и всё, что с ней связано, а именно содержит информацию:
- имя ф-ции
- аргументы ф-ции
- где ф-ции в стеке вызова
- на что ссылается this в привязке к данной ф-ции
- и т.д.
-
2. На, что указывает this в данной конкретной ф-ции зависит от:
- строгий ("use strict") или не строгий режим
- вызывается ли ф-ция через оператор new или обычным способом
Листинг 3. this и ф-ции - базовый пример
function fn(){
"use strict"
console.log(this)
}
fn()
function fn2(){
console.log(this)
}
fn2()
function fn3(){
console.log(this)
}
new fn3()
-
3. Контекст вызова можно подменять с помощью методов bind, call,
apply, а значит переопределять об-т на, который будет указывать this данной
ф-ции
- bind - привязывает указанный this к ф-ции, но не вызывает её
(возвращает ф-цию)
Листинг 4. bind - привязывает this к ф-ции, возвращает новую ф-цию
function fn() {
console.log( this.a )
}
const obj = {
a: 2
}
fn()
const _fn = fn.bind(obj)
_fn()
- call - привязывает указанный this к ф-ции и вызывает её с
указанными аргументами
Листинг 5. call - привязывает this к ф-ции и вызывает её. Также можно передавать список аргументов
function fn() {
console.log(this.a + this.b)
}
const obj = {
a: 2,
b: 3
}
fn()
fn.call(obj)
Листинг 6. call - вместо this можно передавать что угодно
function fn(a, b) {
console.log(a + b)
}
fn(5,6)
fn.call(null, 5, 6)
- apply - привязывает указанный this к ф-ции и вызывает её с
указанными аргументами, которые передаются в виде массива
Листинг 7. apply - то же самое, что и call, но аргументы передаются массивом
function fn(a, b) {
console.log(a + b)
}
fn(5,6)
fn.apply(null, [5, 6])
Более сложные примеры по bind, call и apply см в документации и документе objects-inheritance.html
-
4. Стрелочные ф-ции не имеют своего контекста this, а значит this в них
указывает на об-т родительской области видимости (если у неё есть свой контекст), по отношению к
области видимости, где были созданы (! не вызваны). Раз у них нет своего контекста вызова
this, то его нельзя и подменить с помощью методов bind, call,
apply.
Листинг 8. Стрелочные ф-ции и this - простые примеры
"use strict";
const fn = () => {
console.log(this)
}
function fnc(){
console.log(this)
}
fn()
fnc()
Листинг 9. Стрелочные ф-ции и this - более cложные примеры
const fn = () => {
console.log(this)
}
const fn2 = () => {
const fn = () => {
console.log(this)
}
fn()
}
function fn3() {
"use strict";
const fn = () => {
console.log(this)
}
fn()
}
fn()
fn2()
fn3()
new fn3()
-
5. Если ф-ция вызывается с помощью оператора new, то её this всегда указывает на об-т этой ф-ции. Подробнее см документ function-constructor.html
Выводы по главе
1. Обычно this указывает на об-т, в области видимости которого находится
2. На, что указывает this в ф-ции зависит от того, в строгом или не строгом режиме ф-ция вызывается
3. this в ф-ции можно переопределить с помощью методов bind, call, apply. В ф-ции вызываемой через ключевое слово new (ф-ция - конструктор), this всегда указывает на об-т этой ф-ции
4. this в стрелочных ф-циях указывает на об-т роительской области видимости (если у него есть свой контекст). Привязать this к стрелочной ф-ции нельзя
5. В событиях DOM, this указывает на об-т элемента, на который установлено событие (если в качестве коллбека используется классическая, а не стрелочная ф-ция)
Упражнения
1. Создать об-т с полями firstName и lastName. Создать метод getFullName, который будет возвращать полное имя (firstName + lastName)
2. Сделать то же самое используя ф-цию конструктор
3. Посмотреть и вывести в консоль на что указывает this в обычной ф-ции (строгий режим), обычной ф-ции (не строгий режим), стрелочной ф-ции
4. Создать ф-цию, которая будет суммировать переданные в неё 3 числа. Ф-цию вызвать через call
5. Существует полученный с сервера об-т obj с полями a = 10, b = 20. Создать ф-цию, которая будет суммировать эти поля
и возвращать результат. Ф-ция не должна принимать параметров. Ф-цию вызвать через call, и привязать текущий об-т
6. Создать ф-цию, которая будет перемножать переданные в неё 3 числа. Ф-цию вызвать через apply
7. Сделать задание 5 через apply
8. В html разметке создать обычный текстовый инпут, на который поставить событие input. Вывести в консоль вводимый текст. В качестве об-та элемента использовать this