由于我试图掌握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
)和两个属性(current
和from
)的对象。此对象中的属性等于对象range
中的属性。
由于current
等于this.from
且last
等于this.to
,我认为我可以直接在方法中使用this.from
和this.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);
}
然而,这样做阻止了迭代的开始。观察到这一点后,我有两个问题:
为什么可以属性current
和last
使用关键字this
并让它引用对象range
而方法next
不能? current
,last
和next()
都是相同对象的一部分,该对象由Symbol.iterator
返回。
另外,假设Symbol.iterator()
返回单独的对象,那么该对象中的this
关键字不应该引用该对象本身吗?换句话说,不应该使用关键字current
last
和range
而不是从属this
访问属性?不是range
一个单独的对象吗?
答案 0 :(得分:2)
关键字this
很复杂。当有更好的替代方案时,避免使用它是明智的,因为它有许多问题。
有了这个,这就是答案:this
指的是激活对象(有时称为上下文对象)它包含的功能被叫了。
什么是激活对象?它是调用函数时附加的对象。 console.log()
的激活对象为console
。
...然而
const x = {
log : console.log
};
x.log();
...此处x.log()
与console.log()
完全相同,但激活对象为x
而不是console
。
看起来很简单吧?是的,有点。但还有更多事情需要了解。
window
,在Node.js中称为global
。undefined
this
值根本不是通常的上下文对象 - 它是父函数的上下文对象,无论箭头函数定义在何处现在让我们采用上述内容并将其应用于您的代码。最重要的是,如果在上下文为next()
对象的情况下调用它,则range
方法将起作用。问题是,在引擎盖下,引擎基本上是这样做的......
const returnedObject = range[Symbol.iterator]();
returnedObject.next();
...因此next
以returnedObject
作为其上下文而不是range
进行调用。但返回对象的函数是用<{1}}作为其上下文调用的。因此,range
在每个地方都不同。
使用箭头功能而不是简写方法,您可以非常轻松地解决问题。
这将有效:
this
答案 1 :(得分:1)
这个被认为是一件棘手的事情。因此,凯尔辛普森几乎将整本书专门用于该主题(You Don't Know JS: this & Object Prototypes)。但是,在您的示例中答案很简单 - 在第二个函数中,此位于next()
函数内,因此,解析为此函数。
要检查此的范围,我正在使用Chrome的调试工具。如果您在右侧停留,它会告诉您此解析为的内容。