Что такое лексический 'this'?

Может кто-нибудь, пожалуйста, дайте мне краткое введение в лексику этого?

"Выражение функции стрелки (также известное как функция толстой стрелки) имеет более короткий синтаксис по сравнению с выражением функции и лексически связывает это значение (не связывает его собственные, аргументы, супер или new.target). Функции стрелок всегда анонимны".

Означает ли это, что когда я вызываю член функции с помощью 'this' ref из функции Fat Arrow, 'this' всегда ссылается на прилагаемый 'this'?

Ответ 1

Кажется, у вас есть правильное понимание того, что происходит с this в функции стрелки. Я предложу объяснение, которое, как я думаю, добавит к разговору и, надеюсь, упрочит ваше понимание.

Как вы, вероятно, знаете, когда вы определяете функцию и используете переменную внутри нее, она проверяет, была ли переменная определена в ее области. Если это так, он использует его! Если нет, он проверяет область охвата для определения этой переменной. Он продолжает проверять охватывающие области, пока не найдет переменную или не достигнет глобальной области. Теперь определения функций, которые являются функциями not arrow, определяют this для вас, неявно. Таким образом, они никогда не будут проверять охватывающую область при попытке использовать this в своей области действия (потому что они находят это в своей области!). Функции стрелки НЕ определяют свой собственный this, поэтому они переходят к охватывающей области и ищут ее так же, как и с любой переменной, которую вы пытаетесь использовать в своей области.

Ответ 2

Как способ описать поведение this в функциях стрелок, термин "лексическое this " находится где-то между запутанным и неправильным.

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

К сожалению, терминология "лексическое this ", возможно, была увековечена неправильным выбором формулировок в статье MDN о функциях стрелок (которая до недавнего времени также побуждала людей использовать устаревший термин "функция жирной стрелы"). Теперь это было убрано. Отметим также, что в спецификации никогда не используется термин "лексический" по отношению к this в функциях стрелок. Мне было бы интересно узнать, кто придумал это выражение.

Ответ 3

Допустим, у вас есть прослушиватель кликов. В этом слушателе вы выполняете некоторую операцию AJAX, например setTimeout. По истечении установленного времени будет выполнен код внутри обратного вызова. Внутри этого обратного вызова вы можете получить доступ к this, чтобы изменить цвет нажатой кнопки. Но управление будет вне контекста из-за работы AJAX. ES2015 представил функцию стрелки, чтобы исправить эту проблему. Функция стрелки захватывает значение this окружающего контекста.

Пример использования:

$('.btn').click(function () {
    setTimeout(function () {
        $(this).text('new'); 
        // This will cause an error since function() defines this as the global object.
    } ,100); 
}); 

Чтобы избежать этого случая:

$('.btn').click(function () { // <- Enclosing context
    setTimeout( () => {
        $(this).text('new')  } 
        // This works, because this will be set to a value captured from the enclosing context.
      ,100);
});

Ответ 4

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

Возможно, в течение многих лет вы были обеспокоены тем, что в конечном итоге будет означать "это", когда вам нужно было использовать его в какой-то вложенной функции или функции более высокого порядка. Но с помощью стрелок вы можете перестать беспокоиться об этом. Вы почти наверняка уже знаете, что означает "это" в контексте, в котором вы сейчас находитесь: НО... внутри функции стрелки оно не изменилось. Таким образом, вы можете рассматривать функции со стрелками как простой случай, а функцию() {} как более сложную.

Вы пишете какую-то функцию и запускаете блок if() {} и беспокоитесь о том, что "this" могло бы измениться внутри нее? Нет? То же самое с функциями стрелок. Вот что значит "лексическое". Это означает "Хакуна матата".

Ответ 5

Означает ли это, что когда я вызываю член функции с помощью 'this' ref из функции Fat Arrow, 'this' всегда ссылается на прилагаемый 'this'?

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

Например,

Функция жирной стрелки внутри объекта, использующая this, будет искать внешний контекст. В этом случае контекст window:

var foo = {
  bar: () => this.baz    // 'this' is window      
}

Однако, если вы используете синтаксис ES6, который является сильным синтаксисом открытого класса:

class MyClass {
  handleEvent = () => {
    this.letsCode();    // 'this' is instance of MyClass
  }
}

Есть много других экземпляров (например, использование в render функции React на элементе HTML для установки кликов щелчка), которые выходят за рамки этого вопроса, где используются функции стрелки жира, а this контекст, в котором он используется, что дает нам возможность контролировать его характер. Надеюсь, это поможет!

Ответ 6

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

function foo() {
setTimeout(() => {
    // `this` here is lexically adopted from `foo()`
    console.log( this.a );
},100);
}
var obj = {
  a:2
};
foo.call(obj); //2

Между тем, pre es6, был способ реализовать лексическое определение области видимости в javascript, назначив это ключевое слово переменной, которая до некоторой степени делает это локальным для области

function foo() {
var self = this; // lexical capture of `this`
setTimeout( function(){
    console.log( self.a );
}, 100 );
}
var obj = {
  a: 2;
};
foo.call(obj); //2