深入JavaScript

深入JavaScript Day33 - 序列化实现深拷贝的缺点

2022-02-18  本文已影响0人  望穿秋水小作坊

一、序列化实现深拷贝的缺点、手写深拷贝

1、借助序列化实现深拷贝,有哪些缺点?

const _ = require("lodash");
const { cloneDeep } = require("./copy");

let s1 = Symbol("aaa");
let s2 = Symbol("bbb");

const obj = {
  name: "why",
  age: 18,
  friend: {
    name: "kobe",
    friend: {
      name: "james",
    },
  },
  hobbies: ["run", "swing"],
  food: null,
  country: undefined,
  [s1]: "aaa",
  [s2]: s2,
  run: function () {
    console.log(this.name, "在跑步");
  },
};
// obj.obj = obj;

const copyObj = JSON.parse(JSON.stringify(obj));
// const copyObj = _.cloneDeep(obj);
// const copyObj = cloneDeep(obj);

// 测试代码
copyObj.name = "copy" + obj.name;
copyObj.friend.name = "copy" + copyObj.friend.name;
copyObj.hobbies.push("eat");
console.log("====================obj======================");
console.log(obj);
console.log("====================copyObj======================");
console.log(copyObj);

// obj.run();
// copyObj.run();
// console.log(obj[s2] === copyObj[s2]);

====================obj======================
{
  name: 'why',
  age: 18,
  friend: { name: 'kobe', friend: { name: 'james' } },
  hobbies: [ 'run', 'swing' ],
  food: null,
  country: undefined,
  run: [Function: run],
  [Symbol(aaa)]: 'aaa',
  [Symbol(bbb)]: Symbol(bbb)
}
====================copyObj======================
{
  name: 'copywhy',
  age: 18,
  friend: { name: 'copykobe', friend: { name: 'james' } },
  hobbies: [ 'run', 'swing', 'eat' ],
  food: null
}

2、实现对象的深拷贝要注意哪些问题?

// copy.js
function cloneDeep(obj) {
  let map = new WeakMap();
  return _cloneDeep(obj, map);
}

function _cloneDeep(obj, map) {
  if (
    typeof obj !== "object" ||
    obj === null ||
    typeof obj === "function" ||
    typeof obj === "symbol"
  ) {
    return obj;
  }

  if (map.has(obj)) return map.get(obj);

  let copyObj = null;
  if (Array.isArray(obj)) {
    copyObj = [];
  } else {
    copyObj = {};
  }
  map.set(obj, copyObj);

  for (const key in obj) {
    copyObj[key] = _cloneDeep(obj[key], map);
  }

  for (const key of Object.getOwnPropertySymbols(obj)) {
    copyObj[key] = _cloneDeep(obj[key], map);
  }

  return copyObj;
}

module.exports = {
  cloneDeep,
};

3、手写事件总线,实现 emmit、on、off 三个方法

class EventBus {
  constructor() {
    this.evnentStore = {};
  }

  on(eventName, callback) {
    let list = this.evnentStore[eventName];
    if (!list) {
      list = [];
      this.evnentStore[eventName] = list;
    }
    if (list.indexOf(callback) < 0) list.push(callback);
  }
  off(eventName, callback) {
    let list = this.evnentStore[eventName];
    if (!list) return;
    let index = list.indexOf(callback);
    if (index >= 0) list.splice(index, 1);
  }
  emmit(eventName) {
    let list = this.evnentStore[eventName];
    if (!list) return;
    for (const item of list) {
      item();
    }
  }
}

const eventBus = new EventBus();

// 监听一
const func1 = function () {
  console.log("function1 listen to aaa");
};
eventBus.on("aaa", func1);

// 监听二
const func2 = function () {
  console.log("function2 listen to aaa");
};
eventBus.on("aaa", func2);

// 监听三
const func3 = function () {
  console.log("function3 listen to bbb");
};
eventBus.on("bbb", func3);

// 触发事件
eventBus.emmit("aaa");

// 移除事件
eventBus.off("aaa", func2);

// 触发事件
eventBus.emmit("aaa");

上一篇 下一篇

猜你喜欢

热点阅读