WEBYK WEBYK Індивідуальні OnLine уроки з web технологій
+38 093 766 39 11
oleggpann@gmail.com

Что такое this ? Подсмотрим внутрь JavaScript объектов.

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

   Динамическое связывание

Динамическое связывание - это процесс определения метода для вызова во время выполнения, а не во время компиляции. JavaScript выполняет это с thisпомощью цепочки прототипов. В частности, значение thisвнутри метода определяется во время выполнения, и правила меняются в зависимости от того, как этот метод был определен.

Давай сыграем в игру. Я называю эту игру «Что есть this?»

const a = { 
  a: 'a' 
};const obj = { 
  getThis: () => this, 
  getThis2 () { 
    вернуть это; 
  } 
}; 
obj.getThis3 = obj.getThis.bind (obj); 
obj.getThis4 = obj.getThis2.bind (obj);const 
  answers = [ obj.getThis (), 
  obj.getThis.call (a), 
  obj.getThis2 (), 
  obj.getThis2.call (a), 
  obj.getThis3 (), 
  obj.getThis3.call (a), 
  obj .getThis4 (), 
  obj.getThis4.call (a) 
];

Прежде чем продолжить, запишите свои ответы. После того, как вы это сделали, console.log()ваши ответы, чтобы проверить их. Вы правильно догадались?

Давайте начнем с первого случая и продолжим наш путь. obj.getThis()возвращается undefined, но почему? Функции стрелок никогда не могут иметь своих собственных thisграниц. Вместо этого они всегда делегируют лексическую область видимости. В корневой области модуля ES6 лексическая область в этом случае будет неопределенной this. obj.getThis.call(a)также не определено по той же причине. Для функций со стрелками thisпереназначение невозможно, даже с помощью  .call()или  .bind(). Это всегда будет делегировать лексическому this.

obj.getThis2()получает его привязку через обычный процесс вызова метода. Если предыдущей thisпривязки нет, и функция может иметь привязку this(т. Е. Это не функция со стрелкой), она thisпривязывается к объекту, для которого вызывается метод с  синтаксисом доступа к свойству .or [squareBracket].

obj.getThis2.call(a)немного сложнее call()Метод вызывает функцию с заданным thisзначением и необязательными аргументами. Другими словами, он получает thisпривязку от  .call()параметра, поэтому obj.getThis2.call(a)возвращает aобъект.

С помощью obj.getThis3 = obj.getThis.bind(obj);мы пытаемся связать функцию стрелки, которая, как мы уже определили, не будет работать, поэтому мы вернулись к undefinedобоим obj.getThis3(), и obj.getThis3.call(a).

Вы можете связать обычные методы, поэтому obj.getThis4()return obj, как и ожидалось, и, поскольку он уже связан obj.getThis4 = obj.getThis2.bind(obj);, obj.getThis4.call(a)учитывает первое связывание и возвращает objвместо a.

Кривой мяч

Та же проблема, но на этот раз с classиспользованием синтаксиса открытых полей ( Этап 3 на момент написания этой статьи, доступный по умолчанию в Chrome и с @babel/plugin-proposal-class-properties):

class Obj { 
  getThis = () => this 
  getThis2 () { 
    return this; 
  } 
}const obj2 = новый Obj (); 
obj2.getThis3 = obj2.getThis.bind (obj2); 
obj2.getThis4 = obj2.getThis2.bind (obj2);const answers2 = [ 
  obj2.getThis (), 
  obj2.getThis.call (a), 
  obj2.getThis2 (), 
  obj2.getThis2.call (a), 
  obj2.getThis3 (), 
  obj2.getThis3.call (a), 
  obj2 .getThis4 (), 
  obj2.getThis4.call (a) 
];

Запишите свои ответы, прежде чем продолжить.

Готовы?

За исключением того obj2.getThis2.call(a), что все они возвращают экземпляр объекта. Исключение возвращает aобъект. Функция стрелки все еще делегирует лексическому this. Разница в том, что лексический thisотличается для свойств класса. Внутри этого присваивания свойства класса компилируется примерно так:

class Obj { 
  constructor () { 
    this.getThis = () => this; 
  } 
...

Другими словами, функция стрелки определяется в контексте функции конструктора. Так как это класс, единственный способ создать экземпляр - использовать newключевое слово (пропуск newопускает ошибку).

Одна из самых важных вещей, которые выполняет newключевое слово, - создание экземпляра нового объекта и привязка thisк нему в конструкторе. Это поведение в сочетании с другими поведениями, которые мы уже упоминали выше, должно объяснить остальное.

Заключение

Как ты это сделал? С тобой все в порядке? Хорошее понимание того, как thisведет себя в JavaScript, сэкономит вам много времени на отладку сложных проблем. Если вы ошиблись в ответах, это хорошо послужило бы вам для практики. Поиграйте с примерами, затем вернитесь и проверьте себя снова, пока вы не сможете выполнить тест и объяснить кому-то еще, почему методы возвращают то, что возвращают.

Если это было сложнее, чем вы ожидали, вы не одиноки. Я протестировал довольно много разработчиков на эту тему, и я думаю, что пока что только один разработчик справился с этой задачей.

То , что начиналось , как динамическая Lookups метод , который вы могли бы перенаправлять с  .call(),  .bind()или  .apply()становится значительно более сложным с добавлением classи поведением функции стрелка. Это может быть полезно немного разделить. Помните, что функции стрелок всегда делегируются thisлексической области, и это class thisфактически ограничено функциями конструктора под капотом. Если вы когда-либо сомневаетесь в том, что это thisтакое, не забудьте использовать отладчик, чтобы убедиться, что объект - это то, что вы думаете.

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

Тем не менее, thisиногда полезно. Например, для обмена методами между большим количеством объектов. Даже в функциональном программировании thisможет быть полезно получить доступ к другим методам объекта для реализации алгебраических производных, чтобы построить новые алгебры поверх существующих. Например, универсальный  .flatMap()может быть получен путем доступа к this.map()и this.constructor.of().

Эрик Эллиотт - эксперт по распределенным системам и автор книг «Создание программного обеспечения» и «Программирование приложений JavaScript» . Как соучредитель DevAnywhere.io , он обучает разработчиков навыкам, которые им необходимы для удаленной работы и обеспечения баланса между работой и личной жизнью. Он создает и консультирует команды разработчиков для криптографических проектов, а также вносит свой вклад в опыт разработки программного обеспечения для Adobe Systems, Zumba Fitness, The Wall Street Journal, ESPN, BBC и ведущих исполнителей звукозаписи, включая Usher, Frank Ocean, Metallica и многих других.

Он наслаждается отдаленным образом жизни с самой красивой женщиной в мире.

Источник: https://medium.com/javascript-scene/what-is-this-the-inner-workings-of-javascript-objects-d397bfa0708a

Якщо у вас виникли питання, вбо ви бажаєте записатися на індивідуальний урок, замовити статтю (інструкцію) або придбати відеоурок, пишіть нам на:
скайп: olegg.pann
telegram, viber - +380937663911
додавайтесь у телеграм-канал: t.me/webyk
email: oleggpann@gmail.com
ми у fb: www.facebook.com/webprograming24
Обов`язково оперативно відповімо на усі запитіння


Поділіться в соцмережах



Подобные статьи:


facebook
×
Підришіться на цікаві пости.
Підписатись