Динамическое поведение этого

Давайте посмотрим на пример:

У нас есть переменная a, которая является функцией. Внутри этой функции у нас есть еще одна переменная const b, которая также является функцией, которую мы запускаем в конце - b (); Внутри b у нас есть еще одна функция c, но на этот раз c - это объект со свойством hi, это функция. В конце мы вызываем c.hi ().

Давайте узнаем, что происходит, когда мы запускаем эту функцию.

Давайте разберемся, что здесь произошло.

В случае a this является оконным объектом. Это имеет смысл, потому что слева от точки или того, кто вызвал a, находится объект окна.

С помощью b мы видим, что он вложен в a, но все еще слева от точки, по-прежнему является объектом окна. Нет другого объекта, кроме оконного. Вот что происходит - window.a (b ());

Как насчет c?
У нас есть интересный случай с c. Здесь у нас есть объект, который, как мы знаем, должен что-то изменить. Итак, у нас есть c.hi (). В этом случае слева от точки стоит c. c позвонил привет. Итак, this это объект c.

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

На самом деле не имеет значения, где мы пишем это в фрагменте кода. Все, что имеет значение, - это то, как он вызывается - во время вызова, кто его вызывает. Все, что имеет значение, - это то, как функция вызывается.

Давайте посмотрим на другой пример:

Давай посмотрим что происходит

У нас есть a, а значением this является объект. Это имеет смысл.

Но b не имеет смысла. Это относится к оконному объекту! Но разве b не находится внутри объекта?

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

Произошло то, что выполняется obj.sing (), а внутри функции sing выполняется anotherFunction. Итак, obj на самом деле не вызывает anotherFunction. Функция Sing сделала. В Javascript ключевым словом this по умолчанию является объект окна.

В Javascript наша лексическая область видимости (доступные данные + переменные, в которых была определена функция) определяет наши доступные переменные. Не там, где функция вызывается (динамическая область видимости).

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

Так как же решить эту проблему?

Мы можем решить эту проблему, используя стрелочные функции Es6. Возможно, вы слышали, что стрелочные функции связаны лексически. Стрелочные функции имеют лексическое поведение в отличие от обычных функций.

Итак, если мы изменим нашу функцию, мы увидим, что она лексически связывает this.

Здесь объект, окружающий this, является основным объектом - obj. Проблема решена.

Но что делали люди до того, как появились стрелки? Они использовали привязку.

obj.sing () возвращает функцию, но если мы вызовем ее снова, мы получим ссылку на объект obj.

Есть и другой способ решения этого вопроса.

То, что мы будем делать, находится вне самой функции, мы создадим ссылку, чтобы var self = this.

И поскольку во время выполнения этой строки this все еще находится внутри объекта obj, мы собираемся сохранить ссылку на этот объект.

Здесь мы можем использовать self внутри anotherFunction, чтобы при запуске функции мы видели, что обе функции sing имеют ссылку на объект, используя переменную self.