Всего 3 минуты для JavaScript «Это»

JavaScript this раздражает и вызывает некоторые проблемы, которые сложно исследовать.

Я прочитал много статей о JavaScript this и нашел самый быстрый способ его понять.

Контрольный опрос

Сможете ответить на выход 2 звонка?

var obj = {
  showThis: function(){
    console.log(this)
  }
}
var a = obj.showThis
obj.showThis() // this is obj
a() // this is window

Если вы не понимаете поведения здесь. Эта статья может помочь.

Как вызывалась функция Javascript

В ES6 есть 3 способа вызова функции.

func(a1, a2) 
obj.child.method(a1, a2)
func.call(context, a1, a2)

Фактически, первые 2 метода можно преобразовать в 3-й.

//func(a1, a2) 
func.call(undefined, a1, a2)
//obj.child.method(a1, a2) 
obj.child.method.call(obj.child, a1, a2)

Нам нужно только помнить func.call(context, a1, a2).

И this - это context в аргументах.

Давай еще раз посмотрим викторину

Прямой вызов функции

var obj = {
  showThis: function(){
    console.log(this)
  }
}
var a = obj.showThis
a.call(undefined) //a()
//output: window

Но мы получили window not undefined, почему? Поскольку в браузере существует правило, согласно которому, если контекст имеет значение null или undefined, контекстом по умолчанию является окно. (в строгом режиме вывод будет неопределенным)

Если вы хотите получить объект из этого, вы можете написать так:

var obj = {
  showThis: function(){
    console.log(this)
  }
} 
var a = obj.showThis
a.call(obj)
//output: obj

Вызов метода объекта

Метод мог конвертировать:

var obj = {
  showThis: function(){
    console.log(this)
  }
}
//obj.showThis() 
obj.showThis.call(obj)
//output: obj

В настоящее время this = контекст, поэтому this - это obj.

Функция стрелки

Самый простой способ запомнить this в стрелочной функции - это то, что в стрелочной функции не создается новый this.

this в стрелочной функции равно this снаружи.

function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100)
}
var id = 21
foo.call({ id: 42 })
// id: 42

В global this = window, в функции foo this = {id:42}.

Функция стрелки находится внутри foo(), поэтому функция стрелки this = {id:42}.

Если вы измените функцию стрелки на обычную функцию, результатом foo.call({ id: 42 }) будет 21. Это потому, что var id = 21 на самом деле window.id, поскольку оно объявлено на верхнем уровне, а this будет относиться к window, поскольку контекст не передается во вложенный function .

Как заставить ценность этого

Мы можем использовать apply / call / bind, чтобы принудительно установить значение this.

var a = {
        name : "Cherry",
​
        func1: function () {
            console.log(this.name)
        },
​
        func2: function () {
            setTimeout(  function () {
                this.func1()
            }.apply(a),100);
        }
​
    };
​
    a.func2()            // Cherry
var a = {
        name : "Cherry",
​
        func1: function () {
            console.log(this.name)
        },
​
        func2: function () {
            setTimeout(  function () {
                this.func1()
            }.call(a),100);
        }
​
    };
​
    a.func2()            // Cherry
var a = {
        name : "Cherry",
​
        func1: function () {
            console.log(this.name)
        },
​
        func2: function () {
            setTimeout(  function () {
                this.func1()
            }.bind(a)(),100);
        }
​
    };
​
    a.func2()            // Cherry

Вот и все! Вы можете преобразовать вызов метода или функции в func.call(), чтобы убедиться в этом. Надеюсь это поможет!