Why doesn't the 'this' arrow function change inside a nested object literal?

I found that the 'this' keyword always points to global when using the arrow function inside a nested object literal.

According to other questions, the following snippet can be explained as the function of the arrow 'this' is defined in the lexical context.

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

However, I cannot understand the following code (literal of nested objects):

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

I mean, if you look from the aspect of the lexical context, shouldn't 'this' in abfn point to?

Why, no matter how many levels an object is nested, all instances of 'this' point to a window or global?

+5
source share
3 answers

The only expression in JavaScript that changes the scope is a function and, like in ES6, it blocks (note that the object literal is not a block, despite the presence of curly braces around it). This means: everything that is not inside the function is in the global scope.

In the global scope, this refers to the global object ( window in the case of browsers). The only thing that changes the scope is the arrow function (yes, they change the scope!) - but it connects it lexically (meaning that it uses this from the outer scope), so it is still a global object.

If you want this refer to the object a , use the IIFE object instead of the symbol object:

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

Or, to bind b to this :

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

Alternatively, to bind this to b you can also use a regular function instead of the arrow function:

 var c = 100; var a = { c: 5, b: { c: 10, fn: function () {return this.c;} } } alert(abfn()) // 10; 
+2
source

Same as this , where is the object initializer. So in both of your examples, this is the same as this , where is your line var a = ... this never changes within the specified execution context, and object initializers do not create a new execution context; only functions and eval do this. In your examples, the only time a new execution context is created, you call fn , and since fn is an arrow function, it closes above this in the execution context where it was created (which happens to be the global execution context in your examples).

The reason you see 100 for this.c in your code example is because this in the global scope (in free mode) refers to the global object, and var variables in the global scope become properties of the global object, and therefore this.c is a global variable c .

If you put all this code in a scope function, for example:

 (function() { // Or `(() => {`, doesn't matter in this case var c = 100; var a = { c: 5, b: { c: 10, fn: ()=> {return this.c;} } } console.log(abfn());// still 100, why not 5? })(); 

... this.c will be undefined , because although this will still refer to the global object, c will no longer be a global variable (and therefore is a property of the global object).

If you want this inside fn to refer to b in the expression abfn() , then you do not need an arrow function, you need a normal function; you will get 10 ( abc value), not 5 ( ac value).

Of course, since this is a one-time object and fn closes over a , you can also just do fn body return ac; or return abc; depending on which c you want.

+4
source

Another way to think about this is that there is no concept of a new "this" area in the literature.

On the other hand, the function will suggest a new area.

+1
source

All Articles