给 Object 添加自定义的迭代器

169 阅读2分钟

给 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 的这个情况,那就糟了 --> 死循环......