Skip to content

第 6 题:请分别用深度优先思想和广度优先思想实现一个拷贝函数?

工具函数

js
let _toString = Object.prototype.toString;
let map = {
  array: "Array",
  object: "Object",
  function: "Function",
  string: "String",
  null: "Null",
  undefined: "Undefined",
  boolean: "Boolean",
  number: "Number",
};
let getType = (item) => {
  return _toString.call(item).slice(8, -1);
};
let isTypeOf = (item, type) => {
  return map[type] && map[type] === getType(item);
};

深度优先遍历

js
let DFSdeepClone = (obj, visitedArr = []) => {
  let _obj = {};
  if (isTypeOf(obj, "array") || isTypeOf(obj, "object")) {
    let index = visitedArr.indexOf(obj);
    _obj = isTypeOf(obj, "array") ? [] : {};
    if (~index) {
      // 判断环状数据
      _obj = visitedArr[index];
    } else {
      visitedArr.push(obj);
      for (let item in obj) {
        _obj[item] = DFSdeepClone(obj[item], visitedArr);
      }
    }
  } else if (isTypeOf(obj, "function")) {
    _obj = eval("(" + obj.toString() + ")");
  } else {
    _obj = obj;
  }
  return _obj;
};

广度优先遍历

js
let BFSdeepClone = (obj) => {
  let origin = [obj],
    copyObj = {},
    copy = [copyObj];
  // 去除环状数据
  let visitedQueue = [],
    visitedCopyQueue = [];
  while (origin.length > 0) {
    let items = origin.shift(),
      _obj = copy.shift();
    visitedQueue.push(items);
    if (isTypeOf(items, "object") || isTypeOf(items, "array")) {
      for (let item in items) {
        let val = items[item];
        if (isTypeOf(val, "object")) {
          let index = visitedQueue.indexOf(val);
          if (!~index) {
            _obj[item] = {};
            //下次while循环使用给空对象提供数据
            origin.push(val);
            // 推入引用对象
            copy.push(_obj[item]);
          } else {
            _obj[item] = visitedCopyQueue[index];
            visitedQueue.push(_obj);
          }
        } else if (isTypeOf(val, "array")) {
          // 数组类型在这里创建了一个空数组
          _obj[item] = [];
          origin.push(val);
          copy.push(_obj[item]);
        } else if (isTypeOf(val, "function")) {
          _obj[item] = eval("(" + val.toString() + ")");
        } else {
          _obj[item] = val;
        }
      }
      // 将已经处理过的对象数据推入数组 给环状数据使用
      visitedCopyQueue.push(_obj);
    } else if (isTypeOf(items, "function")) {
      copyObj = eval("(" + items.toString() + ")");
    } else {
      copyObj = obj;
    }
  }
  return copyObj;
};

测试

js
/**测试数据 */
// 输入 字符串String
// 预期输出String
let str = "String";
var strCopy = DFSdeepClone(str);
var strCopy1 = BFSdeepClone(str);
console.log(strCopy, strCopy1); // String String 测试通过
// 输入 数字 -1980
// 预期输出数字 -1980
let num = -1980;
var numCopy = DFSdeepClone(num);
var numCopy1 = BFSdeepClone(num);
console.log(numCopy, numCopy1); // -1980 -1980 测试通过
// 输入bool类型
// 预期输出bool类型
let bool = false;
var boolCopy = DFSdeepClone(bool);
var boolCopy1 = BFSdeepClone(bool);
console.log(boolCopy, boolCopy1); //false false 测试通过
// 输入 null
// 预期输出 null
let nul = null;
var nulCopy = DFSdeepClone(nul);
var nulCopy1 = BFSdeepClone(nul);
console.log(nulCopy, nulCopy1); //null null 测试通过

// 输入undefined
// 预期输出undefined
let und = undefined;
var undCopy = DFSdeepClone(und);
var undCopy1 = BFSdeepClone(und);
console.log(undCopy, undCopy1); //undefined undefined 测试通过
//输入引用类型obj
let obj = {
  a: 1,
  b: () => console.log(1),
  c: {
    d: 3,
    e: 4,
  },
  f: [1, 2],
  und: undefined,
  nul: null,
};
var objCopy = DFSdeepClone(obj);
var objCopy1 = BFSdeepClone(obj);
console.log(objCopy === objCopy1); // 对象类型判断 false 测试通过
console.log(obj.c === objCopy.c); // 对象类型判断 false 测试通过
console.log(obj.c === objCopy1.c); // 对象类型判断 false 测试通过
console.log(obj.b === objCopy1.b); // 函数类型判断 false 测试通过
console.log(obj.b === objCopy.b); // 函数类型判断 false 测试通过
console.log(obj.f === objCopy.f); // 数组类型判断 false 测试通过
console.log(obj.f === objCopy1.f); // 数组类型判断 false 测试通过
console.log(obj.nul, obj.und); // 输出null,undefined 测试通过

// 输入环状数据
// 预期不爆栈且深度复制
let circleObj = {
  foo: {
    name: function () {
      console.log(1);
    },
    bar: {
      name: "bar",
      baz: {
        name: "baz",
        aChild: null, //待会让它指向obj.foo
      },
    },
  },
};
circleObj.foo.bar.baz.aChild = circleObj.foo;
var circleObjCopy = DFSdeepClone(circleObj);
var circleObjCopy1 = BFSdeepClone(circleObj);
console.log(circleObjCopy, circleObjCopy1); // 测试通过?