Javascript生成器函数中的Set键
大家好,我正在尝试找出如何在符号迭代器中设置键,这是我到目前为止的代码:Javascript生成器函数中的Set键,javascript,ecmascript-6,functional-programming,iterator,generator,Javascript,Ecmascript 6,Functional Programming,Iterator,Generator,大家好,我正在尝试找出如何在符号迭代器中设置键,这是我到目前为止的代码: let james = { name: 'James', height: `5'10"`, weight: 185 }; james[Symbol.iterator] = function* () { for (let key in this) { yield this[key]; } } let iterator = james[Symbol.iterator]
let james = {
name: 'James',
height: `5'10"`,
weight: 185
};
james[Symbol.iterator] = function* () {
for (let key in this) {
yield this[key];
}
}
let iterator = james[Symbol.iterator]();
console.log(iterator.next().value); // 'James'
console.log(iterator.next().value); // `5'10`
console.log(iterator.next().value); // 185
例如,我遇到的问题是:
应该打印迭代器.next()的调用
{"value": "James", "key": "name", "done": false}
但是我越来越
{"value": "James", "done": false}
我想以某种方式设置“键”,就像设置“值”一样
我查过了,但是我没有看到任何与此相关的文档
有什么想法吗
编辑
这个问题的用例基本上是将James对象转换为iterable对象,这与“如何”无关,因此我第一次尝试使用生成器,然后我意识到我需要以这种格式打印对象:
{ value: 'James', key: 'name', done: false }
{ value: '5\'10"', key: 'height', done: false }
{ value: 185, key: 'weight', done: true }
这不是一种标准方法,因此我必须创建一个自定义方法来“实现”该行为:
感谢@loganfsmyth为我指明了正确的方向,我想出了这个简单的解决方案:
let james = {
name: 'James',
height: `5'10"`,
weight: 185
};
james[Symbol.iterator] = function (){
const keys = [];
for (let key in this) {
keys.push({'key':key, 'value':this[key]});
}
return {
next(){
let {key,value} = keys.shift();
return {value,key,done:keys.length===0};
}
}
}
let iterator = james[Symbol.iterator]();
console.log(iterator.next().value); // 'James'
console.log(iterator.next().value); // `5'10`
console.log(iterator.next().value); // 185
如果要同时生成键和值,则需要生成一个包含两项的数组,例如
yield [key, this[key]];
那么对象上的.value
将是一个键/值对
还请注意,此行为与您从ES2017中添加的新函数Object.entries(james)
中获得的类似,只是它返回一个数组
如果你想
.next()
要返回同时具有键
、值
和完成
的对象,答案是不能使用生成器执行此操作。这不是生成器提供的API,也不是ES6中定义的迭代器协议,所以您不应该使用迭代器来尝试这样做
你当然可以
james.makeCustomThing = function(){
const pairs = [];
for (const key in this) pairs.push([key, this[key]]);
return {
next(){
if (pairs.length === 0) return {done: true};
let [key, value} = pairs.shift();
return {key, value, done: false};
},
};
};
但它不再是迭代器,它只是您自己定义的自定义对象。您不能这样做。ES6中迭代器的接口是不可更改的:
interface IteratorResult {
done: boolean;
value: any;
}
interface Iterator {
next(): IteratorResult;
}
interface Iterable {
[Symbol.iterator](): Iterator
}
发电机只能用它工作。无论你产生什么,它都将在值中
我修改了@jack.the.ripper代码来使用Object.keys和接下来的arrow函数,所以我们可以利用它
const james = {
name: 'James',
height: `5'10"`,
weight: 185
};
james[Symbol.iterator] = function (){
const keys = Object.keys(this)
return {
next: () => {
let key = keys.shift();
return {value: this[key], key, done:keys.length===0};
}
}
}
let iterator = james[Symbol.iterator]();
console.log(iterator.next().value); // 'James'
console.log(iterator.next().value); // `5'10`
console.log(iterator.next().value); // 185
对iterator.next()的调用应该打印…
为什么?迭代器显式地产生value/done
对象,您不能在那里有其他字段。感谢您的回复,但我需要有这个对象,当在next=>{“value”:“James”,“key”:“name”,“done”:false}上进行打印时,而不是嵌入键值pairb,但迭代器不是这样工作的,所以您宁愿遵循标准,或者你想要那个输出,因为你不能两者兼得。你也没有给出任何关于用例的信息,因此很难提供更多的指导。基本上,用例是将james
对象变成一个可移植的对象,这与“如何”无关,但我的第一次尝试就像使用生成器一样,然后我意识到,我需要打印我之前提到的对象,我将尝试另一种方法让迭代器返回项对是迭代对象的标准方法。这就是为什么所有的ES*API都在实现该功能的.entries()
函数上进行了标准化<代码>存在数组
、对象
、映射
和集合
的条目。您尚未说明为什么需要使用.key
而不是数组。如果是因为您希望有时能够只迭代值,那么对于这两种情况,您可以使用两种不同类型的迭代器函数。@jack.the.ripper:如果您不遵循标准,那么像for…of
或Array.from
这样的事情将无法像您所期望的那样工作。