js對象淺拷貝與深拷貝

在js中,若是一個對象,做爲變量賦值給另外一個對象,那麼兩個對象得值會是相同得引用地址,其中一個改變,另一個也會隨之改變。函數

`性能

var obj1 = {
    num: 123
}
var obj2 = obj1;
obj2.num = 456;
console.log(obj1.num);  // 輸出: 456
複製代碼

` 在咱們平常開發過程中,咱們去複製一個對象得目的是爲了去得到該對象的值,咱們對得到的值進行操做,不會影響原對象纔對。而咱們要解決這樣的問題,就涉及到了使用對象的淺拷貝和深拷貝來解決問題了。spa

淺拷貝

淺拷貝是咱們平常開發使用最多的,由於他能解決咱們平常開發中絕大部分的問題,首先最經常使用的方法就是:Object.assign(),是ES6:Object裏的新增方法,Object.assign()方法用於對象的合併,將源對象(source)的全部可枚舉屬性,複製到目標對象(target),那麼如何使用呢,請看案例:3d

`code

var obj1 = {
    num: 123
}
var obj2 = Object.assign({}, obj1);
obj2.num = 456;
console.log(obj1.num, obj2.num);  // 輸出: 123  456
複製代碼

`cdn

使用方法,仍是很是簡單的,咱們也可使用擴展運算符...的方法來實現淺拷貝: `對象

var obj1 = {
    num: 123
}
var obj2 = {...obj1};
obj2.num = 456;
console.log(obj1.num, obj2.num);  // 輸出: 123  456
複製代碼

` 所謂淺拷貝,實際上指的就是複製對象自己可枚舉的屬性,不會拷貝到繼承屬性和可自己可枚舉屬性的值也是對象裏的值。blog

深拷貝

上面那句話的後半段裏看上去有點繞,這裏在講什麼是深拷貝,你就立馬理解了。而 這個字我我的以爲就挺通俗易懂了,說白了就是更深層次的拷貝唄。那麼怎麼就是深拷貝呢?看案例: `繼承

var obj1 = {
    num: 123,
    child: {
        str: '子級對象'
    }
}
var obj2 = Object.assign({}, obj1);
obj2.child.str = '子對象的str值';
console.log(obj1.child.str);  // 輸出: 子對象的str值
複製代碼

`開發

經過上面的案例,咱們發現,咱們用了淺拷貝,可是obj1obj2裏面的child子對象仍是共用了一個引用地址,這就是我上面說的那句「自己可枚舉屬性裏的值也是對象」,因此咱們就須要更深層次的拷貝到這個對象裏來唄,這就須要使用深拷貝了,最多見的深拷貝方法就是:JSON.parse(JSON.stringify(obj1)),下面看案例:

`

var obj1 = {
    num: 123,
    child: {
        str: '子級對象'
    }
}
var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.child.str = '子對象的str值';
console.log(obj1.child.str);  // 輸出: 子級對象
複製代碼

`

經過使用JSON.parse(JSON.stringify(obj1))咱們實現了深拷貝,其實該方法的實現原理很是的簡單,JSON.stringify()是把咱們的對象轉換成了JSON字符串,字符串屬於基本類型了,已經不存在引用地址了,而後咱們在用JSON,pase()把它轉換回來,此時它已是一個新對象了,和原對象沒有任何關係了。經過這樣轉換的方式實現了深拷貝。可是呢,該方法也存在必定的侷限性,或者說是不足:

  • 1.會忽略 undefined,
  • 2.不能序列化函數,
  • 3.不能解決循環引用的對象

下面看案例:

`

let obj = {
    a: 1,
    b: {
        c: 2,
        d: 3,
    },
}

obj.c = obj.b
obj.e = obj.a
obj.b.c = obj.c
obj.b.d = obj.b
obj.b.e = obj.b.c
let newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj)
複製代碼

`

若是你的對象像這樣的相互引用賦值的話,那麼你會發現不能使用JSON.parse(JSON.stringify(obj1))來實現了,而且還報錯:

不只如此,在遇到 undefined和函數時,也不能正常實現深拷貝:

`

let obj1 = {
    id: undefined,
    fn: function() {},
    tel: 13880089009
}
let obj2 = JSON.parse(JSON.stringify(obj1))
console.log(obj2) // {tel: 13880089009}
複製代碼

`

這樣只拷貝到了tel一個屬性值:那麼這個時候就會用到經常使用得另外一種深拷貝方式了:for in

`

let obj1 = {
	    id: undefined,
		fn: function() {},
		tel: 13880089009
	}
let obj2 = {}
    for (let key in obj1) {
		obj2[key] = obj1[key]
	}
    console.log(obj2)   // {id: undefined, fn: ƒ, tel: 13880089009}
複製代碼

`

for in自己是一個比較耗性能得循環方法,它實現得方式也簡單粗暴,就是一個屬性一個屬性得賦值,for in還能夠遍歷到對象繼承得全部屬性和方法,正是由於這一點,因此for in是個耗性能得主。

總結

本篇章主要講解得是淺拷貝和深拷貝這樣得一個概念,並給出了我的用得一些淺拷貝和深拷貝得方法,用於對咱們平常開發當中注意得一些細節操做。喜歡得朋友給個贊吧,謝謝。

相關文章
相關標籤/搜索