4

Я обнаружил, что это ключевое слово «this» всегда указывает на global на использование функции стрелки внутри вложенного объектного литерала.Почему не происходит «это» функции стрелки внутри вложенного объектного литерала?

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

var c = 100; 
var a = {c:5 , fn:() => {return this.c;} }; 
console.log(a.c); //100 

Однако, я не могу понять следующий код (вложенный объект буквального):

var c = 100; 

var a = { 
    c: 5, 
    b: { 
     c: 10, 
     fn:()=> {return this.c;} 
    } 
} 

console.log(a.b.fn());// still 100, why not 5? 

я имею в виду, если рассматривать с лексическим контекстом аспекта, следует не «это» в точке abfn к?

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

+2

Указывает на текущий объем. Объекты не изменяют область видимости, только функции меняют область. Таким образом, 'this' внутри функции стрелки будет ссылаться на ближайшую функцию внутри. В вашем случае это только верхний уровень. – mash

+1

@mash: 'this' и scope в значительной степени не связаны друг с другом, и' this' только редко 'относится к ... [a] функции. " Но суть комментария, конечно, правильная. –

+0

Только для записи: функции стрелок меняют область действия, как и любую функцию. Они просто связывают слова 'this',' arguments', 'super' и' new.target' лексически, а не определяют свои собственные переменные d, которые затеняют внешние. –

ответ

2

Единственное выражение в JavaScript, которое изменяет область видимости, представляет собой функцию и, как и ES6, блокирует (обратите внимание, что литерал объекта составляет не блок, несмотря на наличие фигурных скобок вокруг него). Это означает: все, что не находится внутри функции, находится в глобальном масштабе.

В глобальном масштабе this относится к глобальному объекту (window в случае браузеров). Единственная вещь, которая меняет область видимости, - это функция стрелки (да, они меняют область действия!), Но она связывает это лексически (это означает, что она использует this из внешней области), поэтому она по-прежнему является глобальным объектом.

Если вы хотите this обратиться к a объекта, используйте IIFE вместо литерала объекта:

var c = 100; 

var a = new function() { 
    this.c = 5; 
    this.b = { 
     c: 10, 
     fn:()=> {return this.c;} 
    } 
}() 

alert(a.b.fn()) // 5; 

Или, чтобы связать b с this:

var c = 100; 

var a = { 
    c : 5, 
    b : new function() { 
     this.c = 10; 
     this.fn =()=> {return this.c;} 
    }() 
} 

alert(a.b.fn()) // 10; 

В качестве альтернативы, для связывания this до b, вы также можете использовать обычную функцию вместо функции стрелки:

var c = 100; 

var a = { 
    c: 5, 
    b: { 
     c: 10, 
     fn: function() {return this.c;} 
    } 
} 

alert(a.b.fn()) // 10; 
+0

"* Единственное выражение в JavaScript, которое изменяет область видимости, - это функция *" - нет. Блоки тоже. – Bergi

+0

@ Bergi Я согласен с тобой, и поэтому я был в замешательстве в отношении этого слова во вложенных объектных литералах. –

+0

@ jt-wang: но объектные литералы не являются блоками :-) – Bergi

3

Это то же самое, что и this, где инициализатор объекта. Таким образом, в обоих ваших примерах это то же самое, что и this, где находится ваша линия var a = .... this никогда не изменяется в пределах заданного контекста выполнения, а инициализаторы объектов не создают новый контекст выполнения; только функции и eval делают это. В ваших примерах единственный раз, когда создается новый контекст выполнения, когда вы вызываете fn, а поскольку fn является функцией стрелки, он закрывается над this в контексте выполнения, где он был создан (что является глобальным контекстом выполнения в ваши примеры).

Причина вы видите 100 для this.c в вашем примере кода является то, что this в глобальном масштабе (в свободном режиме) относится к глобальному объекту, и var переменные в глобальном масштабе становятся свойствами глобального объекта, и поэтому this.c является c глобальная переменная.

Если вы положили все, что код в функции обзорного, например:

(function() { // Or `(() => {`, doesn't matter in this case 
    var c = 100; 

    var a = { 
     c: 5, 
     b: { 
      c: 10, 
      fn:()=> {return this.c;} 
     } 
    } 
    console.log(a.b.fn());// still 100, why not 5? 
})();  

... this.c будет undefined, потому что, хотя this будет по-прежнему относятся к глобальному объекту, c больше не будет глобальная переменная (и, следовательно, свойство глобального объекта).

Если вы хотите this внутри fn обратиться к b в выражении a.b.fn(), то вы не хотите функцию стрелки там, вы хотите нормальную функцию; вы получите 10 (значение a.b.c), а не 5 (значение a.c).

Конечно, так как это объект разовый и fn закрывает над a, вы можете просто сделать fn «s тело return a.c; или return a.b.c; в зависимости от c вы хотите.

+0

Как насчет второго фрагмента кода? 'B' инициализируется внутри' a', но почему 'a.b.c' указывает на глобальный c вместо' a.c'? –

+1

@ jt-wang: Я говорил о втором фрагменте. :-) 'this.c' ссылается на' c' global в этом примере по той же причине, что и первая: 'this' по-прежнему является тем, что было в строке' var a'. 'this' никогда не изменяется в контексте выполнения, а инициализатор объекта не создает новый контекст выполнения (только функции и' eval' do). –

1

Другой способ думать об этом заключается в том, что в литературе нет понятия о новом «этом» объеме.

Функция, с другой стороны, представит новую область.

 Смежные вопросы

  • Нет связанных вопросов^_^