给 Object 添加自定义的迭代器
有时候浏览器会给我报一个:Uncaught TypeError: obj is not iterable at ...... 的错误。
-
简言之就是说我们的变量 obj 类型错误,它不是可以迭代的。
-
比如我们一不小心使用迭代语句 for of 去取 obj 的 value,例如:
let obj = {
Shurima: 1,
Demacia: 2,
Freljord: 3
};
for(let v of obj){
console.log(v);
}
Object 与 Array 数据不同,Array 数据,可以随便去使用迭代语句的 for in 或是 for of
-
for in
- 对于 Array 数组,获取数组中的每一项的下标
- 对于 Object 对象,Object 中的 key
-
for of
- 对于 Array 数组,获取数组中的每一项
- 对于 Object 对象,会报“Uncaught TypeError: obj is not iterable at ...... ”的错误。
当然要获取 obj 的值,也可以 for in
for(let k in obj){
console.log(obj[k]);
}
“Uncaught TypeError: obj is not iterable at ...... ”的错误,是在说啥?
- 我们把 Array 数据与 Object 数据,分别在控制台打印对比一下,可以发现 Array 数据 原型中是有 Symbol(Symbol.iterator) 迭代器方法的,而 Object 数据是没有的。
let arr = ["Shurima","Demacia","Freljord","Ionia"];
let obj = {
Shurima: 1,
Demacia: 2,
Freljord: 3
};
console.dir(arr);
console.dir(obj);
但是就是想让 obj 也是可以迭代的,可以为它添加一个迭代器
- 比如:
obj[Symbol.iterator] = function(){
// 迭代协议
let keys = Object.keys(this); // 以 Object 的 key 进行
let index = 0; // 声明一个索引,方便后面迭代
let _this = this; // 保存一下当前的 this
return {
next(){
if(index<keys.length){
return {
done:false,
// 一次将 Object 的 key 与 value 都获取到
value:{
key:keys[index],
value:_this[keys[index++]]
}
}
}else{
return {
done:true,
}
}
}
};
};
- 这里有一些是固定的格式,如果不遵循浏览器是不知道你要搭理的
-
obj[Symbol.iterator] , obj 是你要为谁添加迭代器的那个“谁”,[Symbol.iterator] 迭代器属性,不能改变、写错
-
迭代器是一个函数,所以 obj[Symbol.iterator] 必须等于或是说必须用一个函数去为它赋值
-
迭代协议,也就是你要打算让这个迭代器,遵循什么条件进行迭代。
-
(迭代器这个)函数中必须返回一个对象,且对象中有 next() 方法,
-
next 函数里进行条件的判断,但都要再次返回一个对象,对象中固定返回 done与value 这两个键值对
-
done :就是字面意,是否做完全部的迭代
- 如果给 false ,表示还没有完成所有迭代,后面还有内容
- 如果给 true ,表示已经完成了所有迭代,这里可以省略了 value,迭代已经结束了。
-
注意,如果 next 函数里,没有返还过 done 为 true 的这个情况,那就糟了 --> 死循环......
-