for in的坑

61 阅读1分钟

for..in可以遍历出在原型上修改的属性

比如Array上有这么一个方法:

  // 数组增加删除元素方法
  Array.prototype.remove = function(filter) {
    if (typeof filter === 'number') {
      this.splice(~~filter, 1);
      return;
    }
    if (typeof filter === 'function') {
      for (let i = 0; i < this.length; i++) {
        if (filter(this[i], i)) {
          this.splice(i, 1);
        }
      }
    }
  };

这时候我们去打印:

  for (let key in []) {
    // 这里for in循环会把remove也循环出来,在remove上加属性data:[]
    key.data = []
    console.log(key)
  }
  // 打印出来是 remove

这时候如果有一个深拷贝的方法:

function isObj(obj) {
  return (typeof obj === 'object' || typeof obj === 'function') && obj !== null;
}

export function deepCopy(obj) {
  let tempObj = Array.isArray(obj) ? [] : {};
  for (let key in obj) {
    tempObj[key] = isObj(obj[key]) ? deepCopy(obj[key]) : obj[key];
  }
  return tempObj;
}

// 调用深拷贝,此时会陷入死循环
let data = []
deepCopy(data)

解决方案

使用forEach去循环:

  [].forEach(item=>{
    console.log(key)
  })
  // 什么都打印不出来,forEach不会遍历原型上的方法