js 中的物件拷貝
阿新 • • 發佈:2019-01-29
js 中物件的拷貝很常見,特別是在面試中很常見
一: 物件淺拷貝與深拷貝和物件引用的區別
var a= {name:'anikin'}
var b = jsons
a == b // true
b.name == 'jack'
a.name // 'jack'
上述程式碼中,使用了=
進行賦值,於是b
指向了a
所指向的棧的物件,也就是a
與b
指向了同一個棧物件,所以在對b.name
賦值時,a.name
也發生了變化。
為了避免上面的情況,可以對物件進行拷貝,程式碼如下:
var a = {name:'wanger'}
var b = Object.assign({}, a)
a===b // false
b.name = 'zhangsan'
a.name //'wanger'
上面程式碼將原始物件拷貝到一個空物件,就得到了原始物件的克隆,這時候a與b指向的是不同的棧物件,所以對b.name重新複製也不會影響到a.name。
但是如果a.name
是一個物件的引用,而不是一個字串,那麼上面的程式碼也會遇到一些問題,參考如下程式碼:
var a = {name:{firstName:'wang',lastName:'er'}}
var b = Object.assign({}, a)
a===b // false
b.name.firstName = 'zhang'
a.name.firstName //'zhang'
b.name.firstName
又影響到了a.name.firstName
,這是因為Object.assign()
方法只是淺層拷貝,a.name
是一個棧物件的引用,賦值給b時,b.name
也同樣是這個棧物件的引用,很多時候,我們不想讓這種事情發生,所以我們就需要用到物件的深拷貝。
二、使用JSON.parse()與JSON.stringify()對物件進行拷貝
var b = JSON.parse(JSON.stringify(a))
這種方法只適用於純資料json物件的深度克隆,因為有些時候,這種方法也有缺陷,參考如下程式碼:
var clone = function (obj) {
return JSON.parse(JSON.stringify(obj));
}
var a = {
a:function(){console.log('hello world')},
b:{c:1},
c:[1,2,3],
d:"wanger",
e:new Date(),
f:null,
g:undefined
}
var b = clone(a)
我們發現,上述的方法會忽略值為function
以及undefied
的欄位,而且對date
型別的支援也不太友好。
更要緊的是,上述方法只能克隆原始物件自身的值,不能克隆它繼承的值。 因此在用這個方法的時候小心使用。
三, 一般寫法
function myextends(t,c){ //用後面的覆蓋前面的
var t = t||{};
for( var attr in c ){
if( c.hasOwnProperty(attr) ){
if( typeof c[attr] == 'object'){
//console.log(c[attr],c[attr].Contructor )
t[attr] = (c[attr].constructor === Array)?[]:{}
arguments.callee(t[attr],c[attr])
}else{
t[attr] = c[attr]
}
}
}
return t
}