簡析js中的深淺拷貝問題

問題描述:

由於在JavaScript中對象在賦值中存儲的是對象的地址(指針),因此會形成對象類型在複製過程當中只複製對象的地址,從而致使如下問題javascript

var people = {
      name: "小明"
    }
var peoplea = people;
peoplea.name = "小白";
console.log(peoplea.name)//小白
console.log(people.name)//小白
複製代碼

咱們原本指望只改變peoplea的name,如今連people的name都改變了。根據狀況的不一樣,可以使用深拷貝或淺拷貝來解決。java

解決方法:

咱們在實現深淺拷貝以前,咱們先看一看深、淺拷貝、賦值這三種的區別:模塊化

一、賦值

改變新對象時無論第幾層,老對象都會隨着變化。函數

var people = {
      name: "小明",
      act: ["吃飯","睡覺"]
}
var people1 = people;//賦值
people1.name = "小紅";
 people1.act[1] = "打遊戲";
console.log(people.name);//小紅
console.log(people.act);//["吃飯", "打遊戲"]
複製代碼
二、淺拷貝

改變新對象第一層基本數據類型時,老對象不變。有子對象時,改變子對象,老對象會隨着變化。工具

var people = {
      name: "小明",
      act: ["吃飯", "睡覺"]
}
var people1 = Object.assign({}, people);//淺拷貝
people1.name = "小紅";
people1.act[1] = "打遊戲";
console.log(people.name);//小明
console.log(people.act);// ["吃飯", "打遊戲"]
複製代碼
三、深拷貝

無論改變新對象第幾層,老對象都不會隨之改變。性能

var people = {
      name: "小明",
      act: ["吃飯", "睡覺"]
}
var people1 = JSON.parse(JSON.stringify(people));//深拷貝
people1.name = "小紅";
people1.act[1] = "打遊戲";
console.log(people.name);//小明
console.log(people.act);// ["吃飯", "睡覺"]
複製代碼

總結一下就是:ui

第一層爲基本數據類型 多於一層含有子對象
賦值 新老一塊兒改變 新老一塊兒改變
淺拷貝 新對象改變,老對象不變 新老一塊兒改變
深拷貝 新對象改變,老對象不變 新對象改變,老對象不變

瞭解完了區別,下面介紹實現深淺拷貝的幾個方法。spa

1、淺拷貝

一、Object.assign()

官方對這個函數的介紹是:Object.assign() 方法用於將全部可枚舉屬性的值從一個或多個源對象複製到目標對象。實際上就是會把屬性中的簡單數據類型直接複製,而對於對象屬性,只會拷貝地址(指針),上邊介紹區別時用的就是這個;指針

var people1 = Object.assign({}, people);
複製代碼

須要注意的是,若是對象沒有子對象,Object.assign()實現的就是深拷貝。code

二、展開運算符(ES6新增)
var people = {
      name: "小明",
      act: ["吃飯", "睡覺"]
}
var people1 = {...people};
people1.name = "小紅";
people1.act[1] = "打遊戲";
console.log(people.name);//小明
console.log(people.act);// ["吃飯", "打遊戲"]
複製代碼
三、本身寫
var people = {
      name: "小明",
      act: ["吃飯", "睡覺"]
    }
    var people1 = shallowCopy(people);
    people1.name = "小紅";
    people1.act[1] = "打遊戲";
    console.log(people.name);//小明
    console.log(people.act);// ["吃飯", "打遊戲"]
    function shallowCopy(obj) {
      var res = {};
      for (var index in obj) {
        if (obj.hasOwnProperty(index)) {//不復制原型鏈上的屬性
          res[index] = obj[index];
        }
      }
      return res;
    }
複製代碼

2、深拷貝

一、JSON.parse(JSON.stringify(obj))

上邊介紹區別時用的就是這個:

var people1 = JSON.parse(JSON.stringify(people));//深拷貝
複製代碼

這個方法比較簡便但也存在問題 一、不能複製對象中的函數。 二、會忽略對象中的undefind。

二、lodash函數

官方介紹是:lodash是一個一致性、模塊化、高性能的 JavaScript 實用工具庫。官網是 www.lodashjs.com/ ,我推薦用其中的_.cloneDeep(value)方法。

ar objects = [{ "a": 1 }, { "b": 2 }];
 
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false
複製代碼

還有本身去寫一個遞歸,可是須要考慮的東西較多,再也不贅述,也有用jq的$.extend()方法實現的,可是性能很差,這裏提一下。

相關文章
相關標籤/搜索