JS中的深拷貝與淺拷貝是什么?針對這個問題,這篇文章詳細(xì)介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
創(chuàng)新互聯(lián)建站專注于邳州企業(yè)網(wǎng)站建設(shè),自適應(yīng)網(wǎng)站建設(shè),商城網(wǎng)站制作。邳州網(wǎng)站建設(shè)公司,為邳州等地區(qū)提供建站服務(wù)。全流程按需求定制開發(fā),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)建站專業(yè)和態(tài)度為您提供的服務(wù)
淺拷貝
淺拷貝是對象的逐位復(fù)制。創(chuàng)建一個新對象,該對象具有原始對象中值的精確副本。如果對象的任何字段是對其他對象的引用,則只復(fù)制引用地址,即,復(fù)制內(nèi)存地址。
大白話講就是,淺拷貝是對對象地址的復(fù)制,并沒有開辟新的棧,也就是復(fù)制的結(jié)果是兩個對象指向同一個地址,修改其中一個對象的屬性,則另一個對象的屬性也會改變。
深拷貝
深拷貝復(fù)制所有字段,并復(fù)制字段所指向的動態(tài)分配內(nèi)存。深拷貝發(fā)生在對象及其引用的對象被復(fù)制時。
大白話講就是,深拷貝則是開辟新的棧,兩個對象對應(yīng)兩個不同的地址,修改一個對象的屬性,不會改變另一個對象的屬性。
Look See See 例子
淺拷貝:它將X
的引用復(fù)制到Y
中。因此,X
和Y
的地址是相同的,也就是說它們指向相同的內(nèi)存位置。
深拷貝:復(fù)制X
的所有成員,為Y
分配不同的內(nèi)存位置,然后將復(fù)制的成員分配給Y
,實(shí)現(xiàn)深拷貝。這樣,如果X
消失了,Y
在內(nèi)存中仍然有效。
考慮下面的代碼:
var employeeDetailsOriginal = { name: '前端小智', age: 18, Profession: '前端開發(fā)' };
假設(shè)你想創(chuàng)建一個這個對象的副本,這樣即使原始值被改變了,仍然可以通過副本得到原始對象的值。
我會這樣做:
var employeeDetailsDuplicate = employeeDetailsOriginal; // 淺拷貝
如果咱們改變一個值:
employeeDetailsDuplicate.name = '王大治';
這樣操作,咱們的原始對象 employeeDetailsOriginal
的屬性 name
也會跟著改變,因?yàn)檫@里是一個淺拷貝。這樣咱們就獲取不到原始對象的值了。所以這種拷貝做法是不對的。
但是,通過使用原始employeeDetailsOriginal
變量的屬性創(chuàng)建一個全新的變量,就可以創(chuàng)建一個深拷貝副本。
var employeeDetailsDuplicate = { name: employeeDetailsOriginal.name, age: employeeDetailsOriginal.age, Profession: employeeDetailsOriginal.Profession }; // 深拷貝
現(xiàn)在,如果更改employeeDetailsDuplicate.name
,它只會影響employeeDetailsDuplicate
,而不會影響employeeDetailsOriginal
。
談?wù)?Object.assign()
Object.assign()
是咱們經(jīng)常用到的方法,其實(shí)這個方法就是淺拷貝。但是它又有一點(diǎn)特殊的地方,就是可以處理第一層的深拷貝。
var employeeDetailsOriginal = { name: '前端小智', family: { name: '前端大家庭' } }; var employeeDetailsDuplicate = Object.assign({}, employeeDetailsOriginal ); employeeDetailsDuplicate.name = '王大治' employeeDetailsDuplicate.family.name = '后端大家庭' console.log(employeeDetailsOriginal ); // { name: "前端小智", family: {name: "后端大家庭"} } console.log(employeeDetailsDuplicate); // { name: "王大冶智", family: {name: "后端大家庭"} }
看上面的例子,屬性name
的值并沒有跟著變,但是屬性中family
的name
的值跟著變了。
如何實(shí)現(xiàn)深拷貝
唯一的作法就是克隆這個對象。
對于簡單的JSON對象,最簡單的方法是 var objectIsNew = JSON.parse(JSON.stringify(objectIsOld)); //如果使用jQuery,可以使用: // 淺拷貝 var objectIsNew = jQuery.extend({}, objectIsOld); // 深拷貝 var objectIsNew = jQuery.extend(true, {}, objectIsOld);
純JS方法來深拷貝對象(并非最佳方法)
function keepCloning(objectpassed) { if (objectpassed=== null || typeof objectpassed!== 'object') { return objectpassed; } // 臨時存儲原始的obj的構(gòu)造 var temporary_storage = objectpassed.constructor(); for (var key in objectpassed) { temporary_storage[key] = keepCloning(objectpassed[key]); } return temporary_storage; } var employeeDetailsOriginal = { name: '前端小智', age: 18, Profession: '前端開發(fā)' }; var employeeDetailsDuplicate = (keepCloning(employeeDetailsOriginal)); employeeDetailsOriginal.name = "前端大治"; console.log(employeeDetailsOriginal); console.log(employeeDetailsDuplicate);
總結(jié)
了解深拷貝也不僅僅是為了應(yīng)付面試題,在實(shí)際開發(fā)中也是非常有用的。例如后臺返回了一堆數(shù)據(jù),你需要對這堆數(shù)據(jù)做操作,但多人開發(fā)情況下,你是沒辦法明確這堆數(shù)據(jù)是否有其它功能也需要使用,直接修改可能會造成隱性問題,深拷貝能幫你更安全安心的去操作數(shù)據(jù),根據(jù)實(shí)際情況來使用深拷貝,大概就是這個意思。
關(guān)于JS中的深拷貝與淺拷貝是什么問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識。