js深拷貝和淺拷貝

antzone發表於2017-04-12

本章節介紹一下淺拷貝和深拷貝。

之所以出現深拷貝,也是由於要規避淺拷貝的缺陷,先來看一個淺拷貝的程式碼:

[JavaScript] 純文字檢視 複製程式碼
var original = {
  age: 3,
  webName: "螞蟻部落", 
  antzoneObj: {
    address: "青島市南區",
    target:"分享互助"
  }
};
var extend = function (result, source) {
  for (var key in source) {
    result[key] = source[key];
  }
  return result;
}
var newObj = extend({}, original);
newObj.antzoneObj.address = "青島市北區";
console.log(newObj.antzoneObj.address);
console.log(original.antzoneObj.address);

從上面的程式碼可以看出,雖然我只想修改新物件的屬性,但是原來物件的屬性也被改變了。

因為result[key] = source[key]傳遞的知識物件的儲存地址,{address: "青島市南區",target:"分享互助"}沒有真正被拷貝。

下面就來看一下深度拷貝:

[JavaScript] 純文字檢視 複製程式碼
var original = {
  age: 3,
  webName: "螞蟻部落", 
  antzoneObj: {
    address: "青島市南區",
    target:"分享互助"
  }
};
 
dom = {};
dom.is = function (obj, type) {
  var toString = Object.prototype.toString, undefined;
  return (type === "Null" && obj === null) ||
         (type === "Undefined" && obj === undefined) ||
         toString.call(obj).slice(8, -1) === type;
};
 
dom.deepCopy = function (result, source) {
  for (var key in source) {
    var copy = source[key];
    if (result === copy) continue;
    if (dom.is(copy, "Object")) {
      result[key] = arguments.callee(result[key] || {}, copy);
    }
    else if (dom.is(copy, "Array")) {
      result[key] = arguments.callee(result[key] || [], copy);
    } else {
      result[key] = copy;
    }
  }
  return result;
};
var newObj = dom.deepCopy({}, original);
newObj.antzoneObj.address = "青島市北區";
console.log(newObj.antzoneObj.address);
console.log(original.antzoneObj.address);

上面的程式碼實現深度拷貝效果,下面介紹一下它的實現過程。

一.程式碼註釋:

(1).var original = {  

  age: 3,

  webName: "螞蟻部落", 

  antzoneObj: {

    address: "青島市南區",

    target:"分享互助"

  }

},建立一個待拷貝的物件,內部巢狀有一個物件。

(2).dom = {},宣告一個空物件,其實用作一個名稱空間功能。

(3).dom.is = function (obj, type) {

  var toString = Object.prototype.toString, undefined;

  return (type === "Null" && obj === null) ||

         (type === "Undefined" && obj === undefined) ||

         toString.call(obj).slice(8, -1) === type;

},此方法的功能是準確判斷資料的型別,第一個引數要判斷的資料,第二個引數是型別,返回值是一個布林值。

dom.deepCopy = function (result, source) {},實現深度拷貝功能,第一個引數目標物件,第二個引數是要被拷貝的物件。

(4).for (var key in source) {},遍歷物件中的每一個屬性。

(5).var copy = source[key],獲取對應的屬性值。

(6).if (result === copy) continue,防止是同一個物件產生死迴圈。

(7).if (dom.is(copy, "Object")) {

  result[key] = arguments.callee(result[key] || {}, copy);

},判斷是否是一個物件。然後用遞迴的方式進行拷貝操作。

result[key] || {}的作用是,如果目標物件中沒有同名屬性,那麼就使用一個空物件。

二.相關閱讀:

(1).prototype可以參閱javascript prototype原型一章節。

(2).call()可以參閱js call()一章節。

(3).slice()可以參閱javascript slice()一章節。

相關文章