“怎么说?”;这";关键字在JavaScript中使用对象?

“怎么说?”;这";关键字在JavaScript中使用对象?,javascript,oop,iteration,symbols,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:

因为我试图在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);
}
然而,这样做阻止了迭代的开始。看到这一点,我有两个问题:

  • 为什么属性
    current
    last
    可以使用关键字
    this
    ,并让它引用对象
    范围
    ,而方法
    next
    不能
    current
    last
    next()
    都是同一对象的一部分,该对象由
    Symbol.iterator
    返回

  • 另外,假设
    Symbol.iterator()
    返回一个单独的对象,那么该对象中的
    this
    关键字不应该引用该对象本身吗?换句话说,属性
    当前的
    最后的
    是否不能使用关键字
    this
    范围
    访问属性?
    range
    不是一个单独的对象吗

  • 众所周知,这是一件棘手的事情。以至于凯尔·辛普森(Kyle Simpson)几乎用了一整本书来讨论这个话题()。但是,在您的示例中,答案很简单-在第二个函数中,这在
    next()
    函数中,因此解析为该函数


    为了检查这个范围,我使用了Chrome的调试工具。如果您在右行暂停,它会告诉您这是什么原因。

    关键字
    this
    很复杂。当有更好的替代品时,避免使用它是明智的,因为它有很多缺陷,通常都有

    这样,答案是:
    this
    指的是调用其包含函数的激活对象(有时称为上下文对象)

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

    然而

    const x = {
        log : console.log
    };
    x.log();
    
    。。。这里的
    x.log()
    console.log()
    完全相同,只是激活对象是
    x
    ,而不是
    console

    看起来很简单,对吧?有点像。但是还有更多的事情要知道

    • 有一个默认的上下文对象,当调用函数而不附加到对象时使用。它是全局对象,在浏览器中称为
      window
      ,在Node.js中称为
      global
    • 如果脚本正在中运行,则没有默认的上下文对象,如果未使用上下文显式调用,则该对象将是未定义的
    • 使用词法范围和它们的
      这个
      值根本不是通常的上下文对象-它是定义箭头函数的父函数的上下文对象
    现在,让我们将上述内容应用到您的代码中。最重要的是,如果在上下文为
    范围
    对象的情况下调用
    next()
    方法,则该方法将起作用。问题是,在引擎盖下,引擎基本上是这样做的

    const returnedObject = range[Symbol.iterator]();
    returnedObject.next();
    
    。。。因此,调用
    next
    时使用
    returnedObject
    作为上下文,而不是
    range
    。但是返回该对象的函数是以
    range
    作为上下文调用的。因此,
    这个
    在每个地方都是不同的

    实际上,通过使用箭头函数而不是速记方法,您可以非常轻松地解决问题

    这将有助于:

    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);
    }
    
    let范围={
    起:0,,
    致:5
    };
    范围[Symbol.iterator]=函数(){
    返回{
    下一个:()=>{
    
    如果(this.from)有意义。但是,为什么属性
    current
    last
    (它们的值都涉及
    this
    )解析为
    范围
    对象而不是它们自己的对象?闭包和原型继承
    current:this.from
    发生在
    范围
    对象内,因此,
    this
    指的是
    范围
    。在第二个代码段中,
    this
    next()
    函数的范围内使用。
    this
    的一个用法在
    符号迭代器内
    方法,另一个在
    .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);
    }