Javascript 理解自定义迭代器的实现
我试图理解Ecmascript 6迭代器,并试图创建一个行为与本机数组非常相似的数据结构Javascript 理解自定义迭代器的实现,javascript,ecmascript-6,Javascript,Ecmascript 6,我试图理解Ecmascript 6迭代器,并试图创建一个行为与本机数组非常相似的数据结构 for (let i of [1,2,3]) console.log(i); //Iterate over data set itself 将输出1,2,3 for (let i of [1,2,3].keys()) console.log(i); //Iterate over a custom iterator from a method 将输出0,1,2,以及 var a = [1,2,3]; v
for (let i of [1,2,3]) console.log(i); //Iterate over data set itself
将输出1,2,3
for (let i of [1,2,3].keys()) console.log(i); //Iterate over a custom iterator from a method
将输出0,1,2
,以及
var a = [1,2,3];
var keys = [...a.keys()];
将按预期包含[0,1,2]
所以,
console.log([1,2,3].keys().next());
将输出对象{value:0,done:false}
现在,我创建了一种新类型的数据,并尝试使其以相同的方式运行
var myDogs = function(dogs) {
this.dogs = dogs;
this[Symbol.iterator] = () => {
let i = -1;
return {
next() {
i++;
var dog = Object.keys(dogs)[i];
if (!dog) return {done:true};
return {value:{ dog, hungry:dogs[dog] }, done:false};
}
};
};
this.dogsNames = () => {
return {
[Symbol.iterator]() {
let i = -1;
return {
next() {
i++;
var dog = Object.keys(dogs)[i];
if (!dog) return {done:true};
return {value: dog, done:false};
}
};
}
}
}
};
var dogs = new myDogs({ buddy: true, hasso: false });
这可以按预期工作(自定义迭代器-):
迭代器dogsNames()
的工作原理几乎与预期一致。这没关系:
var names = [...dogs.dogsNames()];
names == ["buddy", "hasso"]
但这并不是:
dogs.dogsNames().next()
VM19728:2 Uncaught TypeError: dogs.dogsNames(...).next is not a function(…)
为什么以及如何再现本机数组的行为?因为dogsNames()
返回一个以迭代器作为键的对象。因此,您可以在dogsNames上使用for…of
,但要直接访问next()
,您需要访问对象上声明的迭代器函数,如下所示:
dogsNames()[Symbol.iterator]().next()
为完整起见,共享next()函数的完整代码如下:
var myDogs = function(dogs) {
this.dogs = dogs;
let i = -1;
var iter = {
next() {
i++;
var dog = Object.keys(dogs)[i];
if (!dog) return {done:true};
return {value:{ dog, hungry:dogs[dog] }, done:false};
}
}
this[Symbol.iterator] = () => iter;
this.next = iter.next;
};
var dogList = new myDogs({
dog1: "no",
dog2: "yes"
});
for(const x of dogList) console.log(x);
console.log(dogList.next());
console.log(dogList.next());
dogNames
必须返回一个迭代器(实现next
方法的东西),该迭代器也是一个iterable(实现Symbol.iterator
方法的东西)(并返回自身)
快速测试可验证:
var it = [].keys();
it[Symbol.iterator]() === it // true
所以你可以把你的代码改成
this.dogsNames = () => {
let i = -1;
return {
[Symbol.iterator]() {
return this;
},
next() {
i++;
var dog = Object.keys(dogs)[i]; // should probably also be put in the outer function
if (!dog) return {done:true};
return {value: dog, done:false};
},
};
};
好的,我如何重现本机数组的行为?关于迭代器?这已经是你或多或少做过的事情了。换句话说:我怎样才能保持spread操作符工作,并使
dogsNames().next()
也工作?@BarthZalewski您需要以某种方式在类和迭代器之间共享next()
方法……仅供参考,本机数组的工作方式是相同的。没有Array.prototype.next()
方法,它只能通过arrayVar[Symbol.iterator]()使用。next()
也dogNames
必须返回一个迭代器,该迭代器也是一个iterable(并返回自身)。每个内置迭代器都会这样做:。快速测试:var it=[].keys();它[Symbol.iterator]()==它
会产生true
。基本上:返回{next(){…},[Symbol.iterator](){returnthis;}代码>@FelixKling这确实回答了我的问题。非常感谢。
this.dogsNames = () => {
let i = -1;
return {
[Symbol.iterator]() {
return this;
},
next() {
i++;
var dog = Object.keys(dogs)[i]; // should probably also be put in the outer function
if (!dog) return {done:true};
return {value: dog, done:false};
},
};
};