Каков механизм привязки лексической области внутри методов объекта (Javascript)? - PullRequest
1 голос
/ 23 октября 2019

Я испытываю сильное замораживание мозга, понимая функции стрелок и лексическую область видимости: некоторое время назад я прочитал все «Ты не знаешь JS» Кайла Симпсона, и мне показалось, что я достаточно хорошо понял область видимости и контекст. Но я просто не понимаю, как лексическая область действия функции стрелки применяется к объектам - я работал с классами в React, и там всегда ясно, что this, с которым связана функция стрелки, является классом.

Например, в этом примере (из https://medium.com/tfogo/advantages-and-pitfalls-of-arrow-functions-a16f0835799e)

 let obj = {
      myVar: 'foo',

      myFunc: function() { 
        console.log(this.myVar)  

        setTimeout(() => {
          console.log(this.myVar)
        }, 1000)
      }
    }

Функция стрелки должна правильно связывать this, избегая выполнения bind. Но это из лексической области видимости? В каком смысле? Поскольку следующая область действия - это функция myFunc, а лексическая родительская область видимости этой функции - obj?

Но тогда они приводят этот пример

let obj = {
  myVar: 'foo',

  myFunc: () => { 
    console.log(this.myVar)  
  }
}
obj.myFunc() // undefined

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

Подводя итог: верно ли, что здесь «лексическая область видимости»это просто та же самая лексическая область, определяемая функциями, и что this с функциями стрелок просто ищет родителя следующей содержащей функции?

I promто есть вы поняли это (или думали, что поняли) некоторое время назад, но «используйте это или потеряйте», я думаю -

Ответы [ 3 ]

1 голос
/ 23 октября 2019

Прежде всего имейте в виду определение функции стрелки

Функция стрелки не имеет своего собственного this;используется значение this окружающего контекста выполнения ( mozilla )


let obj = {
  myVar: 'foo',
  myFunc: function() { 
    console.log(this.myVar)  
    setTimeout(() => {
      console.log(this.myVar)
    }, 1000)
  }
}
obj.myFunc();

Функция стрелки должна связывать это правильно, избегая выполнения привязки. Но это из лексической сферы? В каком смысле? Поскольку следующая область действия - это функция myFunc, а лексическая родительская область видимости этой функции - obj?

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


let obj = {
  myVar: 'foo',
  myFunc: () => { 
    console.log(this.myVar)  
  }
}
obj.myFunc() // undefined

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

во втором сценарии метод, объявленный в экземпляре, использует функцию стрелки, поэтому this будет унаследовано от включающей функции, но, так как без функции-обертки ваш объект будет Window

1 голос
/ 23 октября 2019

Функция стрелки имеет те же правила лексического обзора, что и все другие функции, кроме случаев, когда речь идет о this. Когда вы определяете функцию стрелки, она захватывает то, что this прямо сейчас, во время определения, и использует это навсегда. Какое бы значение ни было доступно как this in the lexical context of the arrow function's definition is the permanent value of this` в функции стрелки.

Один способ думать об этом: если я закончил определение этой функции стрелки, и сразу же использованный this вне определениякакое значение this это будет?

Во втором случае рассмотрим одно дополнительное свойство:

let obj = {
  myVar: 'foo',

  myFunc: () => { 
    console.log(this.myVar)  
  },

  myOtherVar: this.myVar
}

Мы определенно за исключением myOtherVar будем undefined,потому что, когда вы строите этот объект, this равен window, у которого нет свойства myVar. Это то же самое для функции стрелки: она постоянно принимает this из window, поэтому this.myVar не определено.

1 голос
/ 23 октября 2019

Но это из лексической области? В каком смысле?

В том смысле, что оно имеет то же значение, которое this имеет внутри функции, в которой определена функция стрелки.

Оба console.log(this.myVar) используют одно и то жеthis

Поскольку следующая область действия - это функция myFunc, а лексическая родительская область этой функции - obj?

myFunc Родительская область не имеет значения. Это не функция стрелки. Он получает значение this из того места, где он вызывается.


, где правильное связывание этого не происходит.

this совпадает сродительская функция. Объектный литерал не влияет на него.

Если мы добавим еще один файл console.log, то они (снова) ссылаются на одно и то же значение.

console.log(this.myVar)
let obj = {
  myVar: 'foo',

  myFunc: () => { 
    console.log(this.myVar)  
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...