# 1. 手写深拷贝方法

const deepclone = (obj, hash = new WeakMap()) => {
  if (obj instanceof RegExp) return new RegExp(obj);
  if (obj instanceof Date) return new Date(obj);
  if (typeof obj !== 'object' || !obj) return obj;
  if (hash.has(obj)) return hash.get(obj);
  const newObj = Array.isArray(obj) ? [] : {};
  hash.set(obj, newObj);
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = deepclone(obj[key], hash);
    }
  }
  return newObj;
};

const obj = {name: {age: 10}};
obj.name = obj;
const newobj = deepclone(obj);
console.log(obj, newobj);

# 2. 闭包的理解

  • 使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当容易造成内存泄露。在 js 中,函数即闭包,只有函数才会产生作用域的概念。
  • 闭包有三个特性:
    1. 函数嵌套函数。
    2. 函数内部可以引用外部的参数和变量。
    3. 参数和变量不会被垃圾回收机制回收。
  • 使用场景
    1. setTimeout:原生的 setTimeout 传递的第一个函数不能带参数,通过闭包可以实现传参效果。
    2. 回调:定义行为,然后把它关联到某个用户事件上(点击或者按键)。代码通常会作为一个回调(事件触发时调用的函数)绑定到事件。
    3. 函数防抖:在事件被触发 n 秒后再执行回调,如果在这 n 秒内又被触发,则重新计时。
      实现的关键在于 setTimeOut 这个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现。
    4. 封装私有变量

注意

所有 js 数据类型都拥有 valueOf 和 toString 这两个方法,null 除外

  • valueOf()方法:返回指定对象的原始值。
  • toString()方法:返回对象的字符串表示。 在数值运算中,优先调用了 valueOf,字符串运算中,优先调用 toString

# 3. new 操作符

  1. 创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
  2. 属性和方法被加入到 this 引用的对象中。
  3. 新创建的对象由 this 所引用,并且最后隐式的返回 this。