Простая визуальная диаграмма, которая поможет вам понять «это» в Javascript

Простая визуальная диаграмма, которая поможет вам понять «это» в Javascript

10 февраля 2023 г.

Этот пост поможет вам понять, как легко узнать значение «this» в JavaScript. Если вы спешите, в конце есть шпаргалка по этому ключевому слову JavaScript.

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

Во-первых, вам нужно знать одну важную вещь при работе с ключевым словом «this»

.

<цитата>

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

Когда я говорю об «этих привязках», я просто имею в виду, как ключевому слову «это» присваивается значение. В JavaScript существует 4 разных типа привязок «this», и у них есть собственный порядок старшинства. Итак, вот 4 разных привязки «этого» в порядке возрастания приоритета. Как ключевое слово this работает в JavaScript — привязка по умолчанию.

Как ключевое слово this работает в JavaScript — привязка по умолчанию

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

<цитата>

Примечание. Если функция находится в строгом режиме, то по умолчанию «это» относится к неопределенному. При работе в модуле JavaScript строгий режим включается автоматически.

function foo() {
  this.a = 4;
  /**
   *   creates a global variable a
   *    this is the same as doing these things
   *    var a = 4;
   *    or window.a = 4;
   **/
}

foo();
console.log(a); // 4

function bar() {
  "use strict";
  /**
   * since this is undefined in strict mode
   * the a variable cannot be set and it
   * results in an error
   */

  this.a = 6;
  console.log(a);
}
bar(); // TypeError: Cannot set property 'a' of undefined

Что такое ключевое слово this в классе JavaScript — привязка класса

Этот тип привязки происходит, когда вы вызываете функцию как метод объекта. Значением this является сам объект.

obj = {
  a: 4,
  foo: function() {
    console.log(this.a);
  }
};
obj.foo(); // 4

Неважно, где вы объявляете функцию, если вы вызываете ее как метод объекта.

function foo() {
  console.log(this.a);
}

obj = {
  a: 7,
  foo: foo
};

obj.foo(); // 7

Имеет значение только верхний/последний уровень цепочки ссылок свойств объекта.

function foo() {
  console.log(this.a);
}
const obj1 = {
  a: 4,
  foo: foo
};
const obj2 = {
  a: 7,
  obj1: obj1
};
obj2.obj1.foo(); // 4

/*
Here, obj2 is accessing it's obj1 property 
and then since, the obj1 property is an object itself, 
it calls it's own foo method,
which accesses the a variable set in the obj1 object so it logs the value 4.
*/

Самое важное, что нужно помнить, это то, что речь идет не о самой функции. Дело в том, как это называется. Например, здесь мы вызываем функцию foo, но поскольку она вызывается не как метод объекта, мы возвращаемся к привязке по умолчанию «this».

function foo() {
  console.log(this.a);
}

const obj = {
  a: 7,
  foo: foo
};

/**
 *  only a reference to the actual function is assigned
 * it does not care about the implicit binding
 */
const bar = obj.foo;

var a = 11;

/**
 * here this refers to the window object because of
 * default binding
 **/
bar(); // 11

Как связать это в JavaScript — явное связывание с вызовом и применением

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

function foo() {
  console.log(this.a);
}

const obj = {
  a: 4
};

/**
 * calls the foo function
 * where this is bound to the obj object
 */
foo.call(obj); // 4

<цитата>

Примечание: оба метода apply и call работают одинаково для явной привязки this к заданному значению, но способ передачи в других аргументах немного отличается. Возможно, вы также использовали метод .bind() es6 до этого, который использует явную привязку под капотом, вы можете прочитать больше об этом здесь.

Как это работает в JavaScript с новым ключевым словом — новая привязка

Чтобы понять этот тип привязки, необходимо понять, как работают конструкторы в JavaScript. В JavaScript конструкторы — это просто функции, которые вызываются с оператором «new» перед ними. Они не привязаны к классам и не создают экземпляр класса. Это обычные функции, захваченные с помощью ключевого слова «новое».

Любая определяемая пользователем или встроенная функция может быть вызвана с «новым» перед ней, и это делает ее вызовом построения. Нет такой вещи, как функции-конструкторы, а есть вызовы функций.

Вот что происходит, когда вы звоните на стройку:

  1. Создается совершенно новый объект.
  2. Новый объект связан с прототипом.
  3. Объект устанавливается как привязка this для вызова функции
  4. Если функция не вернет собственный альтернативный объект, вызов новой вызванной функции вернет вновь созданный объект.

function foo() {
this.a = 4;
}
const bar = new foo(); // bar is set to the newly created object;
console.log(bar.a); // 4

Как это работает в стрелочной функции — привязка стрелочной функции

Я знаю, что обещал, что будет только 4 разных типа привязки this, и в прошлом это было правдой, пока в es6 не появились стрелочные функции.

/**
 *  arrow functions use the fat arrow =>
 * instead of the function keyword.
 */

a => {
  console.log(a);
};

Стрелочные функции — это не только более быстрый способ написания функций, но и немного отличающаяся привязка «этого». Они используют лексический объем для «это». Чтобы узнать больше о лексической области видимости, ознакомьтесь с моим руководством по лексической области действия и замыканию.

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

function foo() {
  var = 3;
  return () => {
    /**
     * here this actually refers to the
     * this of the foo function
     */

    console.log(this.a); // 3
  };
}

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

function foo() {
  return () => {
    /**
     * here this actually refers to the
     * this of the foo function
     */

    console.log(this.a);
  };
}
const obj1 = {
  a: 4
};
const obj2 = {
  a: 7
};

/**
 * sets "this" binding to obj1 and
 * gets the arrow function as the return value
 * Now bar is a reference to the arrow function returned by the foo function
* */
const bar = foo.call(obj1);


/**
 * tries to set the this binding
 * of the arrow function to obj2 but
 * the arrow function's this is set
 * to the this of foo which was bound to obj1
 **/
bar.call(obj2); // 4

Таким образом, привязка «этой» функции стрелки на самом деле выполняется во время разработки, а не во время выполнения, как и другие типы привязки «этой».

"this" в Резюме JavaScript и Шпаргалке

Вот что мы теперь знаем о том, как это работает в JavaScript:

* Ключевое слово this в JavaScript относится не к привязке времени автора, а к привязке времени выполнения, то есть речь идет не о том, где объявлена ​​функция, а о том, как она вызывается. * В JavaScript существует 4 различных типа привязок this, каждый из которых имеет свой порядок приоритета: * Привязка по умолчанию: значение this привязано к глобальному объекту (объект окна при работе с JavaScript в браузере). Если функция находится в строгом режиме, то "this" относится к undefined. * Class Binding: значением this является сам объект при вызове функции как метода объекта. * Явное связывание с вызовом и применением: позволяет явно привязать значение this, передав желаемое значение в качестве первого аргумента в метод вызова или применения. * Неявное связывание: значением this является объект, свойством которого является функция. * Самое главное помнить, что дело не в самой функции, а в том, как она вызывается. * Стрелочные функции в JavaScript не имеют собственной привязки this, они наследуют значение this окружающей области видимости. Это означает, что значение this внутри стрелочной функции будет таким же, как значение this в коде, окружающем стрелочную функцию.

Вы можете использовать эту памятку, чтобы найти значение this в JavaScript. Итак, в следующий раз, когда будет сложно отладить значение «this», просто сохраняйте спокойствие и задавайте себе эти вопросы.

Cheat sheet to figure out the value of this in JavaScript

:::информация Также опубликовано здесь.

:::


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE