前言
轉(zhuǎn)載自:
Java 的深拷貝和淺拷貝_淺拷貝
一篇文章徹底說(shuō)清JS的深拷貝/淺拷貝
1. 深淺拷貝的來(lái)由和區(qū)分
除了基本數(shù)據(jù)類型(元類型)之外姆怪,還存在 類的實(shí)例實(shí)例對(duì)象 這個(gè)引用數(shù)據(jù)類型。而一般使用 『 = 』號(hào)做賦值操作的時(shí)候腻异。對(duì)于基本數(shù)據(jù)類型虫碉,實(shí)際上是拷貝的它的值谨垃,但是對(duì)于對(duì)象而言拯腮,其實(shí)賦值的只是這個(gè)對(duì)象的引用幌甘,將原對(duì)象的引用傳遞過(guò)去潮售,他們實(shí)際上還是指向的同一個(gè)對(duì)象。
而淺拷貝和深拷貝就是在這個(gè)基礎(chǔ)之上做的區(qū)分锅风,如果在拷貝這個(gè)對(duì)象的時(shí)候酥诽,只對(duì)基本數(shù)據(jù)類型進(jìn)行了拷貝,而對(duì)引用數(shù)據(jù)類型只是進(jìn)行了引用的傳遞皱埠,而沒(méi)有真實(shí)的創(chuàng)建一個(gè)新的對(duì)象肮帐,則認(rèn)為是淺拷貝。反之边器,在對(duì)引用數(shù)據(jù)類型進(jìn)行拷貝的時(shí)候训枢,創(chuàng)建了一個(gè)新的對(duì)象,并且復(fù)制其內(nèi)的成員變量忘巧,則認(rèn)為是深拷貝恒界。
2. 復(fù)合類型深拷貝的最快解
var copyObj = {
name: 'ziwei',
arr : [1,2,3]
}
var targetObj = JSON.parse(JSON.stringify(copyObj))
// 此時(shí) copyObj.arr !== targetObj.arr 已經(jīng)實(shí)現(xiàn)了深拷貝
別著急走,利用window.JSON的方法做深拷貝存在2個(gè)缺點(diǎn):
如果你的對(duì)象里有函數(shù),函數(shù)無(wú)法被拷貝下來(lái)
無(wú)法拷貝copyObj對(duì)象原型鏈上的屬性和方法
當(dāng)然,你明確知道他們的缺點(diǎn)后,如果他的缺點(diǎn)對(duì)你的業(yè)務(wù)需求沒(méi)有影響,就可以放心使用了,一行原生代碼就能搞定。
目前我在開(kāi)發(fā)業(yè)務(wù)場(chǎng)景中,大多還真可以忽略上面2個(gè)缺點(diǎn)砚嘴。往往需要深拷貝的對(duì)象里沒(méi)有函數(shù),也不需要拷貝它原型鏈的屬性十酣。
3.深拷貝和淺拷貝的實(shí)現(xiàn)方式
其實(shí)JQ里已經(jīng)有$.extend()函數(shù),實(shí)現(xiàn)就是深拷貝和淺拷貝的功能。有興趣的小伙伴也可以看看源碼际长。
淺拷貝
淺拷貝比較簡(jiǎn)單,就是用for in 循環(huán)賦值
function shallowCopy(source, target = {}) {
var key;
for (key in source) {
if (source.hasOwnProperty(key)) { // 意思就是__proto__上面的屬性,我不拷貝
target[key] = source[key];
}
}
return target;
}
深拷貝的實(shí)現(xiàn)
深拷貝,就是遍歷那個(gè)被拷貝的對(duì)象
判斷對(duì)象里每一項(xiàng)的數(shù)據(jù)類型
如果不是對(duì)象類型,就直接賦值,如果是對(duì)象類型,就再次調(diào)用deepCopy,遞歸的去賦值耸采。
function deepCopy(source, target = {}) {
var key;
for (key in source) {
if (source.hasOwnProperty(key)) { // 意思就是__proto__上面的屬性,我不拷貝
if (typeof(source[key]) === "object") { // 如果這一項(xiàng)是object類型,就遞歸調(diào)用deepCopy
target[key] = Array.isArray(source[key]) ? [] : {};
deepCopy(source[key], target[key]);
} else { // 如果不是object類型,就直接賦值拷貝
target[key] = source[key];
}
}
}
return target;
}
以上的無(wú)論深、淺拷貝,都用了source.hasOwnProperty(key),意思是判斷這一項(xiàng)是否是其自有屬性,是的話才拷貝,不是就不拷貝也颤。
也就是說(shuō)proto上面的屬性,我不拷貝洋幻。這個(gè)其實(shí)你可以根據(jù)業(yè)務(wù)需求,來(lái)決定加上和這個(gè)條件
(JQ的$.extend()是會(huì)連proto上的屬性也拷貝下來(lái)的,但是是直接拷貝到對(duì)象上,而不是放到之前的proto上)
4.總結(jié)與建議
雖然大家可能經(jīng)常用框架提供的api來(lái)實(shí)現(xiàn)深拷貝。
這篇文章分享的目的,更多還是希望用一篇文章整理清楚深淺拷貝的含義翅娶、遞歸實(shí)現(xiàn)思路,以及小伙伴們?nèi)绻褂昧薐SON.parse()這種黑科技,一定要清楚這樣寫的優(yōu)缺點(diǎn)文留。