Js 對象拷貝

Js 對象拷貝

對象的引用在js裏面實在的太常見了。若是不注意這個問題,則每每會犯一些小白同樣的錯誤。好比:html

var pa = {
  name: 'huasheng',
  age: '20',
  address: {
    province: 'zzz',
    city: 'aaa'
  }
};

function test(param){
  var addr = param.address;
  addr.city = "bbb";
}

test(obj);

console.log(obj.address.city); // bbb
// 這裏函數test裏面的 addr = param.address 其實就產生了一個引用
// 原本覺得的是把param的address從新賦給一個變量 addr,而後修改 addr 裏面的值,不去影響param
// 可是實驗結果發現,addr 和 param.address 兩個實際上是一個東西。

關於Js變量引用的問題,其實就是數據類型的問題。在Js裏面,有兩種數據類型:基礎類型和引用類型app

其中,Number, Boolean, String都是基礎類型,引用類型包括:Object, Array, Function函數

你們也能夠參考一下這篇文章:http://www.cnblogs.com/diva/post

既然發現了問題,那固然要來解決問題。(下面主要針對的是Object和Array兩種引用類型,在實際應用中,引用裏面須要變化Function的需求很少,最多要求調用一下。)url

其實,解決辦法說白了,就是從新拷貝一份新的數據,若是是基礎類型的,直接賦值就OK, 引用類型的須要拷貝一份出來。這裏的拷貝都要求可以深層拷貝對象。spa

方案1:遞歸法

function deepCopy(result, source) {
  for (var key in source) {
    var copy = source[key];
    if (source === copy) continue;//如window.window === window,會陷入死循環,須要處理一下
    if (is(copy, "Object")) {
      result[key] = arguments.callee(result[key] || {}, copy);
    } else if (is(copy, "Array")) {
      result[key] = arguments.callee(result[key] || [], copy);
    } else {
      result[key] = copy;
    }
  }
    
  return result;
  
  function is(obj, type) {
    var toString = Object.prototype.toString;
    return (type === "Null" && obj === null) ||
      (type === "Undefined" && obj === undefined ) ||
      toString.call(obj).slice(8, -1) === type;
  }

}
callee 的用法能夠參見:JS 中的call,apply,bind 和 caller, callee

方案2:JSON序列化法

先把對象轉成JSON格式的字符串,再將該字符串解析成新的對象。該方法能夠一次性解決深層拷貝問題。簡單易行。prototype

var pa = {
  name: 'huasheng',
  age: '20',
  address: {
    province: 'zzz',
    city: 'aaa'
  }
};

var b = JSON.parse(JSON.stringify(pa));
console.log(b);
b.address.city = 'bbb';
console.log(b.address.city);    // bbb
console.log(pa.address.city);   // aaa
相關文章
相關標籤/搜索