JS对象之遍历

167 阅读3分钟

for…in

for…in可以遍历对象属性列表,那么它是如何遍历属性值呢?

      const array = [1, 2, 3, 4];
      for (let i in array) {
        console.log(i, array[i]);
      }
      //0 1
      //1 2
      //2 3
      //3 4

从上面看出来,我们还是通过属性列表+对象的方式来获取属性值。实际上,这并不是在遍历属性值,而是间接的获取。

辅助迭代器

ES5中增加了一些数组的辅助迭代器。这里简单说一些怎么去迭代数组,不做深入研究。

forEach

  const array = [1, 2, 3, 4];
      array.forEach((item) => {
        console.log(item); //1,2,3,4
      });

some

      //some
      array.some((item) => {
        console.log(item); //1,2,3,4
        return false;
      });

every

      array.every((item) => {
        console.log(item); //1,2,3,4
        return true;
      });

区别于some和very,forEach并没有返回值,而some和every去区别在于,some是当一个返回值为true的时候,就停止迭代,而every是当一个返回值为false的时候停止迭代。

使用for…in是无法直接获取对象属性值的。

那么如何直接遍历对象的属性值呢?偷偷的告诉你,ES6增加了一种用来遍历数组得for…of循环语法(如果对象本身也定义了迭代器的话也能遍历对象)
image.png

      const array = [1, 2, 3, 4];
      for (const i of array) {
        console.log(i); //1,2,3,4
      }

手动遍历

      const array = [1, 2, 3, 4];
      const it = array[Symbol.iterator]();
      console.log(it.next());// {value: 1, done: false}
      console.log(it.next());// {value: 2, done: false}
      console.log(it.next());// {value: 3, done: false}
      console.log(it.next());// {value: 4, done: false}
      console.log(it.next());// {value: undefined, done: true}

我们使用ES6种的符号,Symblo.iterator来获取对象的内部属性@@iterator,返回的是一个函数。如你所见it.next()返回的是{value,done}的形式,done是一个布尔值,表示是否还有可在遍历的值,这里最后还返回一个{done:true}这有点奇怪,这个超出了今天所讲的范围,以后博主学到了再分享!

对象迭代

前几天博主在写代码的时候,突然就报错了,代码大概如下:

      const obj = {
        name: "陈志元",
        age: 21,
        height: 172,
        weight: 118,
      };

      for (const i of obj) {
        console.log(i); //obj is not iterable  obj不可迭代!
      }

欸?我当时就奇怪了,在我的映像中好像对象是可以迭代的欸?哈哈,应该是记混淆了!或者是其他对象内部实现了迭代器的!!

和数组不同的是,普通的对象没有内置@@iterator,所以无法自动完成for…of,但我们前面也说过,如果对象本身定义了迭代器也是可以遍历对对象的。

实现对象迭代器

      const obj = {
        name: "丁时一",
        age: 21,
        height: 170,
        weight: 106,
      };
     Object.defineProperty(obj, Symbol.iterator, {
        enumerable: true,
        writable: false,
        configurable: true,
        value: function () {
          const _this = this;
          //获取所有键
          const keys = Object.keys(_this);
          let idx = 0;
          return {
            next: function () {
              return {
                value: _this[keys[idx++]],
                done: idx > keys.length,
              };
            },
          };
        },
      });
      for (const i of obj) {
        console.log(i);//丁时一 21 170 106
      }

      const it = obj[Symbol.iterator]();
      console.log(it.next());//{value: "丁时一", done: false}
      console.log(it.next());//{value: 21, done: false}
      console.log(it.next());//{value: 170, done: false}
      console.log(it.next());//{value: 106, done: false}
      console.log(it.next());//{value: undefined, done: true}

这里呢我们使用Object.defineProperty定义了一个迭代器,并使用了闭包返回了一个函数next,当调用函数的时候,会返回当前的value和done。