The answer is No. It's not possible to use For..Of with Object literals.
I agree with Overv that For..Of is only for iterables.
I had exactly the same question because I use Objects to iterate over keys and values with for..in. But I just realized that that's what ES6 MAPS and SETS are for.
let test = new Map();
test.set('first', "one");
test.set('second', "two");
for(var item of test) {
console.log(item); // "one" "two"
}
Hence it achieves the goal of not having to use for..In (validating with hasOwnProperty) and not having to use Object.keys().
Additionally, your keys aren't limited to strings. You can use numbers, objects, or other literals.
const myObject = {
first: "one",
second: "two",
};
for (const [key, value] of Object.entries(myObject)) {
console.log(key, value); // first one, second two
}
Object literals don't have built-in iterators, which are required to work with for...of loops. However, if you don't want to go thru the trouble of adding your own [Symbol.iterator] to your object, you can simply use the Object.keys() method. This method returns an Array object, which already has a built-in iterator, so you can use it with a for...of loop like this:
const myObject = {
country: "Canada",
province: "Quebec",
city: "Montreal"
}
for (let i of Object.keys(myObject)) {
console.log("Key:", i, "| Value:", myObject[i]);
}
//Key: country | Value: Canada
//Key: province | Value: Quebec
//Key: city | Value: Montreal
var obj = {1: 'a', 2: 'b'};
function* entries(obj) {
for (let key of Object.keys(obj)) {
yield [key, obj[key]];
}
}
let generator = entries(obj);
let step1 = generator.next();
let step2 = generator.next();
let step3 = generator.next();
console.log(JSON.stringify(step1)); // {"value":["1","a"],"done":false}
console.log(JSON.stringify(step2)); // {"value":["2","b"],"done":false}
console.log(JSON.stringify(step3)); // {"done":true}
Here is the jsfiddle.
In the output you will get an object with the "value" and "done" keys. "Value" contains everything you want it to have and "done" is current state of the iteration in bool.
Iterator, Iterable and for..of loop in ECMAScript 2015/ ES6
let tempArray = [1,2,3,4,5];
for(element of tempArray) {
console.log(element);
}
// 1
// 2
// 3
// 4
// 5
But if we do
let tempObj = {a:1, b:2, c:3};
for(element of tempObj) {
console.log(element);
}
// error
We get error because for..of loop works only on Iterables, that is, the object which has an @@iterator that adheres to Iterator protocol, meaning it must have an object with a next method. The next method takes no arguments and it should return an object with these two properties.
done: signals that the sequence has ended when true, and false means there may be more values
value: this is the current item in the sequence
So, to make an object Iterable that is to make it work with for..of we can:
1 .Make an object an Iterable by assigning to it’s mystical @@iterator property through the Symbol.iterator property.Here is how:
let tempObj = {a:1, b:2, c:3};
tempObj[Symbol.iterator]= () => ({
next: function next () {
return {
done: Object.keys(this).length === 0,
value: Object.keys(this).shift()
}
}
})
for(key in tempObj){
console.log(key)
}
// a
// b
// c
2.Use Object.entries, which returns an Iterable:
let tempObj = {a:1, b:2, c:3};
for(let [key, value] of Object.entries(tempObj)) {
console.log(key, value);
}
// a 1
// b 2
// c 3
3.Use Object.keys, here is how:
let tempObj = {a:1, b:2, c:3};
for (let key of Object.keys(tempObj)) {
console.log(key);
}
// a
// b
// c
const person = {
name: "SeyyedKhandon",
age: 31,
*[Symbol.iterator]() { yield* Object.values(this) }
}
// for of
for (let value of person) {
console.log(value);
}
// spread it
console.log([...person])
example 2 - getting key-values:
const person = {
name: "SeyyedKhandon",
age: 31,
*[Symbol.iterator]() { yield* Object.entries(this) }
}
// for of
for (let item of person) {
console.log("key:",item[0]," -> ", "value:",item[1]);
}
// spread it
console.log([...person])