this в стрелочной функции при работе с DOM

198
10 марта 2018, 21:13

Не могу понять, почему стрелочная функция иначе работает с this. Простой пример:

function btnClick() {
  console.log(this);
};
window.onload = function() {
  var buttons = document.querySelectorAll('.actions input');
  [...buttons].map((el) => el.onclick = btnClick);
}
//<input type="button" name="save" value="Сохранить">
//<input type="button" name="delete" value="Удалить">

При использовании стрелочной функции:

const btnClick = () => {
  console.log(this);
};
window.onload = function() {
  var buttons = document.querySelectorAll('.actions input');
  [...buttons].map((el) => el.onclick = btnClick);
}
//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}

Со всеми вытекающими последствиями.... Как быть в данной ситуации? Отказываться от стрелок в пользу Function Declaration? Или все-таки есть решение?

Answer 1

Внутри стрелочной функции используется this контекста (контекст функции или глобальный контекст), в котором она описана. Это и есть их киллерфича, а не более короткий синтаксис. Если тяжело набирать function funName() { ... }, то используйте снипетты в вашем текстовом редакторе. Да вот же, первая ссылка по запросу "стрелочные функции" с примерами и разъяснениями.

 function myFunction () {
     let self = this;
     let functionDeclaration = function () {
         console.log(self === this);
     }
     let arrowFun = () => console.log(self === this);
     functionDeclaration();
     arrowFun();
 }
 myFunction.call("some");
// output:
// false
// true
Answer 2

[[ThisBindingStatus]] - "lexical" | "initialized" | "uninitialized" - If the value is "lexical", this is an ArrowFunction and does not have a local this value.

Цитата из спецификации.

Если функция является стрелочной, то значение this скопится [scopes] статически (то есть лексически). Это значит, что значение this внутри стрелочной функции будет таким же, как и в том Лексическом Окружении, в рамках которого определена эта стрелочная функция.

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

console.log(this); 
let this1 = this; 
 
let foo = () => { 
    console.log(this); 
    let this2 = this; 
     
    let bar = () => { 
        console.log(this); 
        let this3 = this; 
         
        let baz = () => { 
            let this4 = this; 
            console.log(this); 
            console.log(this1 === this4); // === this2 === this3 
             
        } 
        baz(); 
    } 
    bar(); 
}; 
 
foo();

READ ALSO
jQuery: добавление стилей на страницу

jQuery: добавление стилей на страницу

ЗдравствуйтеЯ подключаю стили к своему веб-приложению с помощью js

305
Почему данные из формы не попадают сразу в компонент?

Почему данные из формы не попадают сразу в компонент?

Помогите пожалуйста понять скользкий моментЯ создал реактивную форму, добавил кастомный валидатор, который возвращает промис

212