Как мы все, наверное, знаем, ES6 (или ECMAScript 2015) вводит множество функций. Одной из них является Функция стрелки, и сегодня мы поэкспериментируем с ней.
Ключевое слово this
известно как объект, на который будет ссылаться вызов функции. Например:
function sayHello() { console.log(this.name); } sayHello();
Вставьте фрагмент кода в консоль браузера Chrome, чтобы увидеть, что будет напечатано:
undefined
: при первой проверке после открытия и вставки кода в консоль объектwindow
, на который ссылается вызов функции, не имеет свойства name.- Введите в консоли:
window.name = 'Mike';
, затем снова вызовите функцию. Результатом будет Майк. Это связано с тем, что объектwindow
теперь имеет свойствоnamed
и его значение равно'Mike'
. - Это то же самое, что и при вызове функции с помощью оператора
window.sayHello()
.
Однако ключевое слово this
работает по-другому при использовании с функцией стрелки. Для стрелочной функции контекст ключевого слова this
— это объект, в котором создается стрелочная функция.
Давайте рассмотрим несколько примеров, чтобы понять больше об этом.
const arrowF1 = () => console.log(this.name);
Что произойдет после вставки этого фрагмента кода и вызова функции arrowF1
в текущую консоль выше:
- Наверняка он выведет Mike на консоль.
- Это связано с тем, что
arrowF1
создается под объектомwindow
. А выше у объекта уже было свойствоname
со значением Mike.
Как насчет этого:
const obj = { name: 'Obj', arrowF2: () => console.log(this.name) };
Будет ли это распечатывать Obj?
- Ответ НЕТ:
- Хотя
arrowF2
является свойством объектаobj
, функция стрелки по-прежнему создается в объектеwindow
, прежде чем она будет установлена как свойство объектаobj
. - И он по-прежнему будет печатать Mike на консоли при вызове
obj.arrowF2()
.
И это?
const parentObj = { name: 'ParentObj', child: { name: 'Child', arrowF3: () => console.log(this.name) } }
- Ответ по-прежнему НЕТ:
- Даже когда мы создаем здесь вложенный объект, но это все равно то же самое, когда мы говорим, что функция стрелки все еще создается под объектом
window
. - Мы можем понять это таким образом. Функция стрелки сначала создается, а затем устанавливается как свойство объекта. После этого объект устанавливается как свойство
child
объектаparentObj
.
Итак, вопрос в том, как мы можем связать правильный контекст со стрелочной функцией.
Давай попробуем:
const newObj = { name: 'NewObj', generateFunc: () => { return () => console.log(this.name); } }
Напечатанный результат: Майк. Да, ты не ошибся. Давайте углубимся:
- Во-первых, функция стрелки еще не создана. Вы абсолютно правы в этом. Но как он создается. Он будет создан путем вызова функции
generateFunc
, которая является свойством объектаnewObj
. Вот такconst newArrowF = newObj.generateFunc();
И прямо в момент вызова функцииgenerateFunc
будет создана стрелочная функция и ссылка наthis
контекст функцииgenerateFunc
. - И, как вы видите, функция
generateFunc
— это еще одна стрелочная функция, созданная под объектомwindow
(описано выше).
Наконец, мы можем закончить цикл вопросов и ответов здесь:
const item = { name: 'Item', generateFunc() { return () => console.log(this.name); } }; const arrowFunction = item.generateFunc(); arrowFunction(); // -> Object
Здесь он печатает Item вместо Mike. Вот как это работает:
- Как видите, здесь есть небольшая разница, когда
generateFunc
определяется как обычная функция (что означает не как стрелочная функция). - Это означает, что контекст
this
будет привязан к функции только при вызове функции (а не при ее создании). - Как только
generateFunc
вызывается с объектомitem
, этот объект становится контекстомthis
, на который ссылается функция. По совпадению, этот контекстthis
является тем, на который ссылается функция стрелки, поскольку именно здесь она создается.
Тада, с тебя достаточно, чтобы ясно понять ключевое слово this
со стрелочными функциями.
Время вызова:
- Как мы можем изменить контекст
this
функции стрелки, но при этом сохранитьgenerateFunc
как обычную функцию? ИЛИ, - Что будет с:
const windowArrowFunction = item.generateFunc.call(window); windowArrowFunction();
Я хотел бы поблагодарить вас за то, что вы провели здесь со мной время, чтобы узнать больше о JS. Если у вас есть какие-либо отзывы об этом, пожалуйста, сделайте мне одолжение, оставив свои комментарии, чтобы мы могли обсудить это вместе.
До скорой встречи.
С наилучшими пожеланиями,