怎么"这"关键字在JavaScript中使用对象?

时间:2017-08-22 02:00:36

标签: javascript oop iteration symbols

由于我试图掌握JavaScript中迭代的概念,我使用以下代码构建了一个:

let range = {
  from: 0,
  to: 5
};

range[Symbol.iterator] = function() {
  return {
    current: this.from,
    last: this.to,

    next() {
      if (this.current <= this.last) {
        return { done: false, value: this.current++ };
      } else {
        return { done: true };
      }
    }
  };
};

for (let num of range) {
  console.log(num);
}

Symbol.iterator方法返回一个包含一个方法(next)和两个属性(currentfrom)的对象。此对象中的属性等于对象range中的属性。

由于current等于this.fromlast等于this.to,我认为我可以直接在方法中使用this.fromthis.to next如此:

let range = {
  from: 0,
  to: 5
};

range[Symbol.iterator] = function() {
  return {
    next() {
      if (this.from <= this.to) {
        return { done: false, value: this.from++ };
      } else {
        return { done: true };
      }
    }
  };
};

for (let num of range) {
  console.log(num);
}

然而,这样做阻止了迭代的开始。观察到这一点后,我有两个问题:

  1. 为什么可以属性currentlast使用关键字this并让它引用对象range而方法next不能? currentlastnext()都是相同对象的一部分,该对象由Symbol.iterator返回。

  2. 另外,假设Symbol.iterator()返回单独的对象,那么该对象中的this关键字不应该引用该对象本身吗?换句话说,不应该使用关键字current lastrange 而不是从属this访问属性?不是range一个单独的对象吗?

2 个答案:

答案 0 :(得分:2)

关键字this很复杂。当有更好的替代方案时,避免使用它是明智的,因为它有许多问题。

有了这个,这就是答案:this指的是激活对象(有时称为上下文对象)它包含的功能被叫了。

什么是激活对象?它是调用函数时附加的对象。 console.log()的激活对象为console

...然而

const x = {
    log : console.log
};
x.log();

...此处x.log()console.log()完全相同,但激活对象为x而不是console

看起来很简单吧?是的,有点。但还有更多事情需要了解。

  • 有一个默认的上下文对象,在调用函数而不附加到对象时使用。它是全局对象,在浏览器中称为window,在Node.js中称为global
  • 如果脚本在strict mode中运行,则没有默认的上下文对象,如果没有使用上下文显式调用,它将是undefined
  • Arrow functions使用词法作用域,它们的this值根本不是通常的上下文对象 - 它是父函数的上下文对象,无论箭头函数定义在何处

现在让我们采用上述内容并将其应用于您的代码。最重要的是,如果在上下文为next()对象的情况下调用它,则range方法将起作用。问题是,在引擎盖下,引擎基本上是这样做的......

const returnedObject = range[Symbol.iterator]();
returnedObject.next();

...因此nextreturnedObject作为其上下文而不是range进行调用。但返回对象的函数是用<{1}}作为其上下文调用的。因此,range在每个地方都不同。

使用箭头功能而不是简写方法,您可以非常轻松地解决问题。

这将有效:

this

答案 1 :(得分:1)

这个被认为是一件棘手的事情。因此,凯尔辛普森几乎将整本书专门用于该主题(You Don't Know JS: this & Object Prototypes)。但是,在您的示例中答案很简单 - 在第二个函数中,位于next()函数内,因此,解析为此函数。

要检查的范围,我正在使用Chrome的调试工具。如果您在右侧停留,它会告诉您解析为的内容。