一步一步實現Javascript深克隆

步驟一:實現簡單的遞歸克隆

function deepCopy(source) {
  return (function _copy(parent) {
    var child;
    for (var i in parent) {
        if (parent.hasOwnProperty(i)) {
            child[i] = _copy(parent[i]);
        } else {
            child = parent;
        }
    }
    return child;
  })(source)
}
複製代碼

存在的問題

  • 未處理Array,Date,Function等特殊對象
  • 複製的對象的constructor都是指向Object構造函數
  • 存在循環引用問題

步驟二:處理特殊對象及constructor指向問題

function getType(obj) {
  var typeString = Object.prototype.toString.call(obj);
  return typeString.substring(8, typeString.length - 1);
}

function deepCopy(source) {

  return (function _copy(parent) {

    var child;

    switch (getType(parent)) {
      case 'Object':
          // 處理對象原型,指向父類的constructor
          child = Object.create(Object.getPrototypeOf(parent));
          for (var i in parent) {
            if (parent.hasOwnProperty(i)) {
              child[i] = _copy(parent[i]);
            }
          }
        break;
      default:
        child = parent;
    }

    return child;

  })(source)
}
複製代碼

存在的問題

  • 存在循環引用問題

步驟三:處理循環引用問題

function getType(obj) {
  var typeString = Object.prototype.toString.call(obj);
  return typeString.substring(8, typeString.length - 1);
}

function deepCopy(source) {

  var copyedList = [];

  return (function _copy(parent) {

    var child;

    switch (getType(parent)) {
      case 'Object':
        // 是否已經克隆過了
        var isCopyIndex = copyedList.indexOf(parent);
        if (isCopyIndex >= 0) {
          child = copyedList[isCopyIndex]
        } else {
          copyedList.push(parent);
          // 處理對象原型,指向父類的constructor
          child = Object.create(Object.getPrototypeOf(parent));
          for (var i in parent) {
            if (parent.hasOwnProperty(i)) {
              child[i] = _copy(parent[i]);
            }
          }
        }
        break;
      default:
        child = parent;
    }

    return child;

  })(source)
}
複製代碼

結束語

其實仍是有一些問題javascript

  • 存在爆棧的問題
  • 邊界問題未處理
相關文章
相關標籤/搜索