【问题标题】:Scope of `this` within object declaration对象声明中“this”的范围
【发布时间】:2018-04-07 02:12:45
【问题描述】:

在 JavaScript 中创建对象时,this 似乎没有指向我正在创建的对象。

在下面的示例中,anArrayValue 应该是 "a",但它被记录为 undefined

const anArray = ['a', 'b', 'c'];

const anObject = {
  arrayIndex: 0,

  // I want to use anObject.arrayIndex here, but it's undefined
  anArrayValue: anArray[this.arrayIndex],

  log() {
    console.log(this.anArrayValue);
  }
};

//logs undefined
anObject.log();     

//logs 'a'
console.log(anArray[anObject.arrayIndex]);  

【问题讨论】:

  • this 总是指向执行上下文的调用。这是一个在窗口上下文中执行声明的文字对象。因此 this.arrayIndex 正在调用 window.arrayIndex。你需要一个真实的对象来作为这种参考。

标签: javascript arrays object scope


【解决方案1】:

“this”在函数调用的开头定义。在这里,您不在 anObjet 的方法中。您必须在声明对象之前存储该值。

const anArray = ['a', 'b', 'c'];

const DEFAULT_ARRAY_INDEX = 0;

const anObject = {
    arrayIndex: DEFAULT_ARRAY_INDEX,

    anArrayValue: anArray[DEFAULT_ARRAY_INDEX],

    log: function() {
        console.log(anObject.anArrayValue);
    }
};

anObject.log();     

console.log(anArray[anObject.arrayIndex]);

您还可以使用“初始化”方法。或者使用构造函数创建一个类。

【讨论】:

    【解决方案2】:

    'this.arrayIndex'实际上被解释为'window.arrayIndex'(这里指的是浏览器中的全局“window”对象)。

    您可能想在 JavaScript 控制台中尝试以下代码,而不是将整个全局对象转储到 StackOverflow sn-p 中。

    const anArray = ['a', 'b', 'c'];
    const anObject = {
          arrayIndex: 0,
          anArrayValue: anArray[(function(arg){console.log('this :', this); return arg.arrayIndex})(this)],
          log() {
            console.log(this.anArrayValue);
          }
        };

    而且这个全局对象显然没有任何arrayIndex 属性,除非显式创建:

    const anArray = ['a', 'b', 'c'];
    arrayIndex = 0; // here we create the arrayIndex for the global object
    const anObject = {
          arrayIndex: 0,
          anArrayValue: anArray[this.arrayIndex],
          log() {
            console.log(this.anArrayValue);
          }
        };
    
    console.log("anObject.anArrayValue :", anObject.anArrayValue);

    另一方面,log() 是一个对象方法,因此,this 指的是它所属的对象:

    当一个函数作为对象的方法被调用时,它的 this 被设置为调用该方法的对象。

    参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

    希望这会有所帮助!

    【讨论】:

      【解决方案3】:

      这里的问题是this.arrayIndex 没有按照你的想法做。

      考虑这个例子:

      let parent = {
          a: ['parent a'],
          method() {
              let child = { a: ['child a'], b: this.a[0] };
              console.log(child.b);
          }
      }
      
      parent.method(); // Outputs 'parent a', not 'child a'
      //^^^^           // <-- This decides that `this` is.

      当像这样声明一个对象时,this 唯一会引用您正在创建的对象是当它位于分配给该对象的函数内时。

      需要明确的是,this 始终引用包含您正在调用的函数的对象。这意味着如果您将 method 分配给不同的对象然后调用它,它将引用新对象。

      例子:

      let newObject = { a: ['newObject a'], method: parent.method };
      newObject.method(); // This outputs 'newObject a'
      

      例外情况是当您使用胖箭头 (() =&gt;) 函数声明时,在这种情况下,this 是从声明函数的作用域继承的,无论从何处调用函数。

      【讨论】:

        【解决方案4】:

        this 上下文不能在声明时使用。但是,您可以使用getter 返回值,该值将在调用时执行(因此可以访问this)。

            const anArray = ['a', 'b', 'c'];
        
            const anObject = {
              arrayIndex: 0,
              // Use a getter to execute the expression upon call
              get anArrayValue() { return anArray[this.arrayIndex] },
              log() {
                console.log(this.anArrayValue);
              }
            };
            anObject.log();
            //logs 'a'
            console.log(anArray[anObject.arrayIndex]);
            //logs 'a'

        【讨论】:

          【解决方案5】:

          不,在对象构造过程中this not 是否引用了您所在的对象。如果这样,对象将不稳定且无法优化。但是,您可以简单地将 arrayIndex 移出它:

          const anArray = ['a', 'b', 'c'], arrayIndex = 0;
          
          const anObject = {
            arrayIndex,     
            anArrayValue: anArray[arrayIndex],
          
            log() {
              console.log(this.anArrayValue);
            }
          };
          

          【讨论】:

            猜你喜欢
            • 2021-02-01
            • 2016-03-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多