Руководство по этому в JavaScript

Ключевое слово this является одним из наиболее широко используемых, но неправильно понятых в JavaScript. Я постараюсь изменить это сегодня.

Давайте вернемся в старые добрые школьные времена, когда мы узнали о местоимениях.

Фелпс плывет быстро, потому что хочет выиграть гонку.

Обратите внимание на использование местоимения «он». Мы не обращаемся к Фелпсу напрямую, а используем местоимение он для обозначения Фелпса. Точно так же JavaScript использует ключевое слово this в качестве референта для ссылки на объект в контексте, то есть на тему.

Пример:

var car= {
make: "Lamborghini",
model: "Huracán",
fullName: function () {
console.log(this.make+" " +this.model);
console.log(car.make+ " " +car.model);
}
}
car.fullName();

В приведенном выше коде у нас есть объект car со свойствами make, model и fullName. Значение fullName — это функция, которая печатает полное название автомобиля, используя 2 разных синтаксиса.

Используя this => this.make+» « +this.model, this относится к объекту в контексте, который является автомобилем, поэтому this.make фактически является car.make, как и this.model.
Используя запись через точку, мы можем получить доступ к свойствам объектов car.make и car.model.
это оно!
Теперь, когда мы поняли, что это такое, и его основное использование, давайте установим несколько практических правил, чтобы всегда помнить.

Ключевое слово JS this относится к объекту, которому оно принадлежит.

var car={
make:'....'
func:()=>{console.log(this.make)}}

this в приведенном выше фрагменте принадлежит объекту car.

Принимает разные значения в зависимости от использования
Внутри метода.
Внутри функции.
Один.
В мероприятии.
call() и применить().
Внутри метода

Когда это используется внутри метода, оно ссылается на объект-владелец.

Функции, определенные внутри объекта, называются методами. Давайте снова возьмем наш пример с автомобилем.

var car= {
make: "Lamborghini",
model: "Huracán",
fullName: function () {
console.log(this.make+" " +this.model);
console.log(car.make+ " " +car.model);
}
}
car.fullName();

fullName() здесь метод. Метод this внутри этого метода принадлежит автомобилю.

Внутри функции

это внутри функции немного сложно. Первое, что нужно понять, это то, что, как и все объекты имеют свойства, функции также имеют свойства. Всякий раз, когда эта функция выполняется, она получает свойство this, которое представляет собой переменную со значением объекта, который ее вызывает.

на самом деле это просто краткая ссылка на «предшествующий объект» — вызывающий объект. — javascriptissexy.com
Если функция вызывается не объектом, то this внутри функции принадлежит глобальному объекту, который называется window. В этом случае это будет относиться к значениям, определенным в глобальной области видимости. Давайте посмотрим на пример для лучшего понимания:

var make= "Mclaren";
var model= "720s"
function fullName(){ 
console.log(this.make+ " " + this.model);
}
var car = {
    make:"Lamborghini",
    model:"Huracán",
    fullName:function () {
    console.log (this.make + " " + this.model);
    }
}
    car.fullName(); // Lmborghini Huracán
    window.fullName(); // Mclaren 720S
    fullName(); // Mclaren 720S

Здесь make, model и fullName определены глобально, а объект car также имеет реализацию fullName. При вызове объектом car это относится к свойствам, определенным внутри объекта. С другой стороны, вызовы двух других функций одинаковы и возвращают глобально определенные свойства.

Один

При использовании отдельно, а не внутри какой-либо функции или объекта, это относится к глобальному объекту.

Это здесь относится к свойству глобального имени.

В мероприятии

События могут быть любого типа, но для простоты и ясности возьмем событие клика.

Всякий раз, когда нажимается кнопка и возникает событие, оно может вызвать другую функцию для выполнения определенной задачи на основе щелчка. Если это используется внутри этой функции, оно будет ссылаться на элемент, вызвавший событие. В DOM все элементы хранятся как объекты. Вот почему, когда возникает событие, оно ссылается на этот элемент, потому что этот элемент веб-страницы на самом деле является объектом внутри DOM.

Пример:

<button onclick="this.style.display='none'">
  Remove Me!
</button>

вызов(), применить() и привязать()

bind: позволяет нам установить это значение для методов.
call & apply: позволяет нам заимствовать функции и устанавливать значение this при вызове функции.
Call, Bind и Apply сами по себе являются темой отдельного поста. Они очень важны, и объяснить их здесь невозможно, так как мы должны знать все об этом, чтобы знать, как использовать эти функции.

Самая сложная часть
При правильном понимании это в некотором роде облегчит нашу работу. Но бывают случаи, когда это понимают неправильно.

Пример 1.

var car = {
make:"Lamborghini",
model:"Huracán",
name:null,
fullName:function () {
this.name=this.make + " " + this.model;
console.log (this.name);
}
}
var anotherCar={
make:"Ferrari",
model:"Italia",
name:null}
    anotherCar.name= car.fullName();

Здесь мы получаем неожиданный результат. Мы позаимствовали метод, использующий this, у другого объекта, но проблема здесь в том, что этот метод назначается только функции AnotherCar, но на самом деле вызывается для объекта car. Вот почему мы получаем результат как Lamborghini, а не как Ferrari.

Чтобы решить эту проблему, мы используем метод call().

Здесь метод call() вызывает fullName() для другого объектаCar, который изначально не имеет функции fullName().

Мы также можем видеть, что, когда мы регистрируем car.name и AnotherCar.name, мы получаем результат для последнего, а не для первого, что означает, что функция действительно была вызвана для AnotherCar, а не для автомобиля.

Пример 2.

var cars=[
{ make: "Mclaren", model: "720s"},{make: "Ferrari",model: "Italia"}]
var car = {cars:[{make:"Lamborghini", model:"Huracán"}],
fullName:function () {console.log(this.cars[0].make + " " + this.cars[0].model);}}
var vehicle=car.fullName;
vehicle()

В приведенном выше фрагменте у нас есть глобальный объект с именем cars, и у нас есть объект с таким же именем внутри объекта car. Затем метод fullName() присваивается переменной транспортного средства, которая затем вызывается. Переменная принадлежит глобальному объекту, поэтому из-за контекста вызывается глобальный объект cars вместо объекта cars.

Чтобы решить эту проблему, мы используем функцию .bind().

Привязка помогает нам конкретно установить значение this, и, следовательно, переменная транспортного средства явно указывает на объект автомобиля, а не на глобальный объект, поэтому это находится в контексте объекта автомобиля.

Пример 3.

var car = {
cars:[{make:"Lamborghini",model:"Huracán"},
{ make: "Mclaren", model: "720s"},
{make: "Ferrari",model: "Italia"}],
fullName:function(){this.cars.forEach(()=>{console.log (this.make + " " + this.model);
})}}
car.fullName();

В приведенном выше фрагменте fullName() вызывает функцию, которая перебирает массив cars с помощью forEach. Внутри forEach есть анонимная функция, где this теряет контекст. Функция внутри функции в JavaScript называется замыканием. Замыкания очень важны и широко используются в JavaScript.

Еще одно важное понятие, играющее здесь роль, — масштаб. Переменная внутри функции не может получить доступ к переменным и свойствам вне ее области. this внутри функции anon не может получить доступ к этому снаружи. Так что этому некуда идти, кроме как указывать на глобальный объект. Но там для этого не определено свойство, поэтому печатается undefined.

Обходной путь для вышеизложенного заключается в том, что мы можем присвоить переменной значение this вне анонимной функции, а затем использовать его внутри нее.

Здесь переменная self содержит значение this, которое используется с внутренней функцией, что дает нам результат.

Пример 4.

var car= {
make: "Lamborghini",
model: "Huracán",
fullName: function (cars) {
cars.forEach(function(vehicle){
console.log(vehicle +" "+ this.model);
})}}
car.fullName(['lambo','ferrari','porsche']);

Это пересмотренный пример, в котором это не было доступно, поэтому мы сохранили его значение, используя переменную с именем self. Давайте используем функцию стрелки, чтобы решить то же самое:

Как видите, использование функции стрелки в forEach() автоматически решает проблему, и нам не нужно выполнять привязку или присваивать значение this какой-либо другой переменной. Это связано с тем, что стрелочные функции связывают свой контекст, поэтому это фактически относится к исходному контексту или исходному объекту.

Пример 5.

var car= {
make: "Lamborghini",
model: "Huracán",
fullName: function () {
console.log(this.make +" "+ this.model);
}}
var truck= {
make: "Tesla",
model: "Truck",
fullName: function (callback) {
console.log(this.make +" "+ this.model);
callback();
}}
truck.fullName(car.fullName);

Приведенный выше код состоит из двух идентичных объектов, один из которых содержит функцию обратного вызова. Функция обратного вызова — это функция, передаваемая в другую функцию в качестве аргумента, которая затем вызывается внутри внешней функции для завершения какой-либо процедуры.

Здесь метод fullName объекта грузовика состоит из обратного вызова, который также вызывается внутри него. Наш автомобильный объект такой же, как и раньше. Когда мы вызываем метод fullName грузовика с обратным вызовом (аргументом) в качестве метода fullName объекта car, мы получаем вывод как Tesla Truck и undefined undefined.

Прочитав об этом, у некоторых из вас могло возникнуть подозрение, что car.fullName напечатает модель и марку объекта грузовика, но, к вашему разочарованию, это снова сыграло с нами злую шутку. Здесь car.fullName передается в качестве аргумента и фактически не вызывается объектом грузовика. Обратный вызов вызывает метод объекта автомобиля, но обратите внимание, что фактическое место вызова функции — это обратный вызов, который привязывает this к глобальному объекту. Это немного запутанно, так что прочитайте еще раз!

Здесь, чтобы получить ясность, мы печатаем это само. Мы видим, что this обратного вызова имеет глобальную область видимости. Итак, чтобы получить результат, мы создаем глобальные свойства марки и модели.

Опять же, запуская тот же код с глобальными свойствами make и model, мы, наконец, получаем ответ на глобальное this. Это доказывает, что this ссылается на глобальный объект.

Чтобы получить желаемые результаты, результат car.fullName, мы снова будем использовать bind() для жесткой привязки объекта автомобиля к обратному вызову, что снова сделает все правильно.

Решено!
Без сомнения, это очень полезно, но есть и свои подводные камни. Надеюсь, я сделал это довольно легко для вас понять. Если вы хотите больше контента, упрощенного таким образом, следуйте за мной на Medium. Пожалуйста, оставьте свои ответы и поделитесь этим, если вам понравилось.

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *