Reputation: 4505
I am currently reading about Symbols and Iterators (ES6 features) and after running into an example there, I am trying to make an object iterable so that I can use for...of
feature. From few examples/answers here/articles I checked, it looks like this in plain case:
let obj = {
prop1: 5,
prop2: 'test',
prop3: new Date(),
[Symbol.iterator]: () => ({
items: obj.items,
next: function next() {
return {
done: this.items.length === 0,
value: this.items.shift()
}
}
})
};
Object.defineProperty(obj, "items", {
enumerable: false,
get: function() {
let props = [];
for(let prop in this) if(this.hasOwnProperty(prop)) props.push(this[prop]);
return props;
}
});
for(let prop of obj) console.log(prop);
But I find it annoying to list manually all the values of an object's properties in items
array of iterator. Also it feels dirty and messy with Object.defineProperty
. I am kind of trying tom expand the example from the link. Is there a smarter/simpler way to get all the object's properties inside iterator (instead of items: obj.items
and related bloat or manually listing items like items: [5, 'test', new Date()]
)?
Upvotes: 0
Views: 3291
Reputation: 11177
function objectEntries(obj) {
let index = 0;
// In ES6, you can use strings or symbols as property keys,
// Reflect.ownKeys() retrieves both
let propKeys = Reflect.ownKeys(obj);
return {
[Symbol.iterator]() {
return this;
},
next() {
if (index < propKeys.length) {
let key = propKeys[index];
index++;
return { value: [key, obj[key]] };
} else {
return { done: true };
}
}
};
}
let obj = { first: 'Jane', last: 'Doe' };
for (let [key,value] of objectEntries(obj)) {
console.log(`${key}: ${value}`);
}
http://2ality.com/2015/02/es6-iteration.html
Upvotes: 1
Reputation: 664494
You should not use an items
getter but instead just create the array inside the iterator method. Also you can use generator syntax to create the iterator, which is much easier.
But the simplest way to achieve what you want is
let obj = {
prop1: 5,
prop2: 'test',
prop3: new Date(),
[Symbol.iterator]() { return Object.keys(this).map(k => this[k])[Symbol.iterator](); }
};
Upvotes: 1
Reputation: 138267
You could return a generator in the symbol iterator maybe:
[Symbol.iterator]:function*(){
for(value of Object.values(this)){
yield value;//may extend this to your needs
}
}
Or in your case:
[Symbol.iterator]:function*(){
var i=1;
while(this["prop"+i]){
yield this["prop"+i];//may extend this to your needs
i++;
}
}
http://jsbin.com/zekunalusi/edit?console
Upvotes: 3