详解for..of遍历可迭代对象
1. 迭代字面量定义的对象试试
首先看一案例
const obj1 = { a: 1, b: 2, c: 3 }; // const num = [a, b , c] for(let item of obj1) { console.log(item); }
结果是报错的。
Uncaught TypeError: obj1 is not iterable
这个iterable 是什么。是不是有了就可以遍历了呢,答案是当然了(后边给方案)。
在看一个正面的例子
const num = [a, b , c] for (let i of num) { console.log(i); } // 结果是 a ,b ,c
那就是说数组可以遍历。直接定义字面量对象不可以,问题在哪里呢
都打印一下看下区别
const obj1 = { a: 1, b: 2, c: 3 }; const num = [a, b , c] console.log(obj1); console.log(num)
问题就出在这里,谁有这个属性谁就能被for...of和 for ..in 迭代遍历
这些可以被遍历的统统成为可迭代对象
可迭代对象(包括Array, Map, Set, String, TypedArray, arguments对象等等)
语法:
for (variable of iterable) { //statements }
举例:
2.迭代Array
let iterable = [10, 20, 30]; for (let value of iterable) { value += 1; console.log(value); } // 11 // 21 // 31
3. 迭代String
let iterable = "boo"; for (let value of iterable) { console.log(value); } // "b" // "o" // "o"
4. 迭代TypedArray
let iterable = new Uint8Array([0x00, 0xff]); for (let value of iterable) { console.log(value); } // 0 // 255
5.迭代Map
let iterable = new Map([["a", 1], ["b", 2], ["c", 3]]); for (let entry of iterable) { console.log(entry); } // ["a", 1] // ["b", 2] // ["c", 3] for (let [key, value] of iterable) { console.log(value); } // 1 // 2 // 3
6.迭代Set
let iterable = new Set([1, 1, 2, 2, 3, 3]); for (let value of iterable) { console.log(value); } // 1 // 2 // 3
迭代arguments 对象
(function() { for (let argument of arguments) { console.log(argument); } })(1, 2, 3); // 1 // 2 // 3
7.迭代 DOM 集合
迭代 DOM 元素集合,比如一个Nodelist对象:下面的例子演示给每一个 article 标签内的 p 标签添加一个 "read" 类。
//注意:这只能在实现了NodeList.prototype[Symbol.iterator]的平台上运行 let articleParagraphs = document.querySelectorAll("article > p"); for (let paragraph of articleParagraphs) { paragraph.classList.add("read"); }
8.关闭迭代或者终止
对于for...of的循环,可以由break, throw continue 或return终止。在这些情况下,迭代器关闭。
const num = [a, b , c] // console.log(obj1); // console.log(num) for (let i of num) { if(i === b) { break } console.log(i); } // 只会打印出来一个 a 就结束了
9. 迭代字面量对象
回到问题开始,我想要用for of 迭代 对象字面量生成的对象。怎么办呢
迭代其他可迭代对象,显式实现可迭代协议的对象。
看例子就会明白(迭代规则必须按照固定的写法。):
const obj1 = { a: 1, b: 2, c: 3 }; obj1[Symbol.iterator] = function() { let keys = Object.keys(obj1); //[a,b,c] let len = keys.length; let n = 0; return { next: function() { if (n < len) { return { value: { k: keys[n], v: obj1[keys[n++]] }, done: false }; } else { return { done: true }; } } }; }; for (let { k, v } of obj1) { // 这里用的是es6中的对象解构赋值 console.log(k, v); } for (let item of obj1) { console.log(item); }
打印结果:
10.迭代最优解
当然这里只是为了理解,es6中有 Object.keys() 、 Object.values() 、 Object.entries() 和for of 配合迭代那是极好的
const obj1 = { a: 1, b: 2, c: 3 }; for(let key of Object.keys(obj1)) { console.log(key); } // 结果 : a b c for(let value of Object.values(obj1)) { console.log(value); } // 结果 : 1 2 3 for(let [index , item] of Object.entries(obj1)) { // 这里为啥要用方括号呢。得看你要解构的是什么格式了。 console.log(index,item); } // 结果 a 1 b 2 c 3