Lexical context of 'this' in Nested Object Literals

巧了我就是萌 提交于 2020-02-24 12:08:51

问题


I'm asking because I've read similar (but not equal) questions about this issue.

As far as I understand, I get why this code would NOT work:

let myObj = {
  name: 'inner text',
  myFunction: () => {
    console.log("before text " + this.name + " after text");
  }
}
myObj.myFunction();

Reason: the context where the arrow function is created (myObj) belongs to the global scope (which is window or undefined depending on strict mode and so on).

I get that. But in the case of nested object literals, shouldn't be the outer object literal the inherited context for the arrow function like following example?

let outer = {
  name: 'outer',
  obj: {
    name: 'inner',
    myFunction: () => {
      console.log("before text " + this.name + " after text");
    }
  }
}
outer.obj.myFunction();

I would expect that this refers to the context of outer, which is the object literal where obj is nested.
This is not the case and the reason I don't understand properly this inherited lexical scope.

Could someone throw some light about why is that happening?


回答1:


But in the case of nested object literals, shouldn't be the outer object literal the inherited context for the arrow function like following example?

No.

An arrow function copies the current value of this;

var object = {
     a: this,
     b: { 
         a: this,
         b: {
             a: this
         }
     } 
}

It doesn't matter how many levels you nest it, the value of this doesn't change.

Since every level of the object literal appears in the same function, they all get the same this value.




回答2:


There are many ways to accomplish what you want. The most compact could be to use a getter like follows:

let outer = {
  name: 'outer',
  obj: {
    name: 'inner',
    get myFunction() {
      console.log("before text " + this.name + " after text");
      return (this.name);
    }
  }
}
outer.obj.myFunction;

Inside a getter/setter your context is guaranteed to be the object instance (the most nested) (remember that each inner object is an 'independent' instance of Object, and getters/setters will belong to the nearest instance).

The problem with your code is that your arrow function is preserving the execution context at the time of creating the object.

Another way to achieve the intended behaviour would be to save a manually bound method as follows:

let outer = {
  name: 'outer',
  obj: {
    name: 'inner'
  }
}
outer.obj.myFunction = (function () {console.log("before text " + this.name + " after text");}).bind(outer.obj);
outer.obj.myFunction();


来源:https://stackoverflow.com/questions/57769860/lexical-context-of-this-in-nested-object-literals

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!