摘要:也就是說(shuō),深拷貝與淺拷貝最主要的區(qū)別在引用類型的拷貝上。方法二遞歸拷貝深拷貝與淺拷貝相比不就是多拷貝幾層的事嘛,這不就是遞歸常干的事嘛。
什么是淺拷貝和深拷貝 淺拷貝
淺拷貝:將一個(gè)對(duì)象自身的屬性拷貝給另一個(gè)對(duì)象,如果源對(duì)象的屬性是基本類型則直接進(jìn)行值賦值,如果是引用類型則進(jìn)行引用賦值,也就是說(shuō)只進(jìn)行一層賦值。
深拷貝深拷貝:將一個(gè)對(duì)象自身的屬性拷貝給另一個(gè)對(duì)象,如果源對(duì)象的屬性是基本類型則直接進(jìn)行值賦值,如果是引用類型則復(fù)制這個(gè)引用類型,使得目標(biāo)對(duì)象擁有一個(gè)引用類型且和這個(gè)源屬性一模一樣,而非是一個(gè)指針。
也就是說(shuō),深拷貝與淺拷貝最主要的區(qū)別在引用類型的拷貝上。
注意,引用賦值不是淺拷貝??! 引用賦值僅僅只是賦值個(gè)指針,兩個(gè)變量都指向同一內(nèi)存區(qū)域,而淺拷貝是使得兩個(gè)變量分別指向不同的內(nèi)存區(qū)域
如果不懂,可以參考這里 一個(gè)小姐姐的博客
以上不是重點(diǎn)...
淺拷貝的實(shí)現(xiàn) 方法一 使用 for in 遍歷function shallowCopy(source){ var target=source instanceof Array ? [] : {}; for(var i in source){ if(source.hasOwnProperty(i)){ target[i]=source[i]; } } return target; } // 測(cè)試 var obj={a:1,b:[1,2,3],c:function(){console.log("i am c")}} var tar=shallowCopy(obj) tar.c() // "i am c" obj.a=5 obj.a // 5 tar.a // 1 obj.b[0]=10 obj.b // [10, 2, 3] tar.b // [10, 2, 3] var arr=[1,2,[4,5,6]] var newArr=shallowCopy(arr) newArr // [1, 2, [4,5,6]] arr[0]=10 arr // [10, 2, [4,5,6]] newArr // [1, 2, [4,5,6]] arr[2][0]=10 arr // [1, 2, [10,5,6]] newArr // [1, 2, [10,5,6]]方法二 使用 Object.assign 或 slice、concat
Object.assign
var obj={a:1,b:[1,2,3],c:function(){console.log("i am c")}} var tar={}; Object.assign(tar,obj);
當(dāng)然這個(gè)方法只適合于對(duì)象類型,如果是數(shù)組可以使用slice和concat方法
Array.prototype.slice
var arr=[1,2,[3,4]]; var newArr=arr.slice(0);
Array.prototype.concat
var arr=[1,2,[3,4]]; var newArr=arr.concat();
測(cè)試同上(assign用對(duì)象測(cè)試、slice concat用數(shù)組測(cè)試),結(jié)合淺拷貝深拷貝的概念來(lái)理解效果更佳
深拷貝的實(shí)現(xiàn) 方法一 JSON黑科技var obj={a:1,b:[1,2,3],c:function(){console.log("i am c")}} var tar=JSON.parse(JSON.stringify(obj)); // 測(cè)試 obj.a=5 obj.a // 5 tar.a // 1 obj.b[0]=10 obj.b // [10, 2, 3] tar.b // [1, 2, 3] tar.c() // Uncaught TypeError: tar.c is not a function
可以看到,無(wú)論是基本類型還是引用類型,兩個(gè)對(duì)象的相同屬性(屬性名相同的屬性)之間并沒(méi)有關(guān)系了,但tar.c()報(bào)錯(cuò)了,我們打印看一下tar有什么console.log(tar) // {a: 1, b: Array(3)}可以看到c方法沒(méi)了,這是和JSON的語(yǔ)法有關(guān),JSON 并不支持函數(shù)類型的數(shù)據(jù)。這也就是這種方法的最大缺陷。
仔細(xì)一看,這并非黑科技,反而倒是有很大缺陷,不過(guò)很好用、效率高,只是在使用前需要稍加注意是否有函數(shù)類型的數(shù)據(jù)罷了。
方法二 遞歸拷貝深拷貝與淺拷貝相比不就是多拷貝幾層的事嘛,這不就是遞歸常干的事嘛。所以我們就想,在每次拷貝時(shí)都判斷下,該屬性是否是引用類型,如果是我們?cè)龠f歸調(diào)用拷貝方法,否則直接進(jìn)行值賦值。
function deepCopy(obj,tar){ var tar = tar || {}; for(var i in obj){ if(typeof obj[i] === "object"){ if(obj[i].constructor === Array){ tar[i] =[]; }else{ tar[i] = {}; } deepCopy(obj[i],tar[i]); } else{ tar[i] = obj[i]; } } return tar; } // 使用 var obj={a:1,b:[1,2,3],c:function(){console.log("i am c")}}; var tar={}; deepCopy(obj,tar); console.log(tar);
測(cè)試同上,你會(huì)驚喜的發(fā)現(xiàn)第一個(gè)方法中的函數(shù)bug沒(méi)了
你看出來(lái)函數(shù)是怎樣進(jìn)行拷貝的了嗎?很簡(jiǎn)單,typeof運(yùn)算符的操作對(duì)象是一個(gè)函數(shù)時(shí),得到的是 "function" 所以在循環(huán)里第一個(gè)if判斷那為false 所以走else分支,在tar[i] = obj[i]這里,函數(shù)是進(jìn)行引用賦值的,如果再造一個(gè)相同的函數(shù)不是不可以,只是不符合思想罷了,函數(shù)占用堆內(nèi)存,如果可以共用當(dāng)然是最好的選擇。
當(dāng)然這個(gè)方法還是有些許不足之處,不夠已經(jīng)很棒了
方法三 更嚴(yán)謹(jǐn)、更優(yōu)雅的實(shí)現(xiàn)這就需要去讀一些好的源碼了,比如Zepto、JQuery中extend方法的實(shí)現(xiàn)
現(xiàn)學(xué)現(xiàn)賣(mài),如有不足請(qǐng)指出...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/94062.html
摘要:淺拷貝與深拷貝一數(shù)據(jù)類型數(shù)據(jù)分為基本數(shù)據(jù)類型,和對(duì)象數(shù)據(jù)類型。淺拷貝是按位拷貝對(duì)象,它會(huì)創(chuàng)建一個(gè)新對(duì)象,這個(gè)對(duì)象有著原始對(duì)象屬性值的一份精確拷貝。對(duì)于字符串?dāng)?shù)字及布爾值來(lái)說(shuō)不是或者對(duì)象,會(huì)拷貝這些值到新的數(shù)組里。 淺拷貝與深拷貝 一、數(shù)據(jù)類型數(shù)據(jù)分為基本數(shù)據(jù)類型(String, Number, Boolean, Null, Undefined,Symbol)和對(duì)象數(shù)據(jù)類型。 基本數(shù)據(jù)類...
摘要:所以,深拷貝是對(duì)對(duì)象以及對(duì)象的所有子對(duì)象進(jìn)行拷貝實(shí)現(xiàn)方式就是遞歸調(diào)用淺拷貝對(duì)于深拷貝的對(duì)象,改變?cè)磳?duì)象不會(huì)對(duì)得到的對(duì)象有影響。 為什么會(huì)有淺拷貝與深拷貝什么是淺拷貝與深拷貝如何實(shí)現(xiàn)淺拷貝與深拷貝好了,問(wèn)題出來(lái)了,那么下面就讓我們帶著這幾個(gè)問(wèn)題去探究一下吧! 如果文章中有出現(xiàn)紕漏、錯(cuò)誤之處,還請(qǐng)看到的小伙伴多多指教,先行謝過(guò) 以下↓ 數(shù)據(jù)類型在開(kāi)始了解 淺拷貝 與 深拷貝 之前,讓我們先...
摘要:所以,深拷貝是對(duì)對(duì)象以及對(duì)象的所有子對(duì)象進(jìn)行拷貝實(shí)現(xiàn)方式就是遞歸調(diào)用淺拷貝對(duì)于深拷貝的對(duì)象,改變?cè)磳?duì)象不會(huì)對(duì)得到的對(duì)象有影響。 上一篇 JavaScript中的繼承 前言 文章開(kāi)始之前,讓我們先思考一下這幾個(gè)問(wèn)題: 為什么會(huì)有淺拷貝與深拷貝 什么是淺拷貝與深拷貝 如何實(shí)現(xiàn)淺拷貝與深拷貝 好了,問(wèn)題出來(lái)了,那么下面就讓我們帶著這幾個(gè)問(wèn)題去探究一下吧! 如果文章中有出現(xiàn)紕漏、錯(cuò)誤之處...
摘要:原文地址淺拷貝和深拷貝只針對(duì)像這樣的復(fù)雜對(duì)象的簡(jiǎn)單來(lái)說(shuō),淺拷貝只拷貝一層對(duì)象的屬性,而深拷貝則遞歸拷貝了所有層級(jí)。淺拷貝通過(guò)來(lái)實(shí)現(xiàn)淺拷貝。 原文地址:http://www.silenceboy.com/201... 淺拷貝和深拷貝只針對(duì)像Object, Array這樣的復(fù)雜對(duì)象的.簡(jiǎn)單來(lái)說(shuō),淺拷貝只拷貝一層對(duì)象的屬性,而深拷貝則遞歸拷貝了所有層級(jí)。 淺拷貝 通過(guò) Object.ass...
摘要:什么是深拷貝,什么是淺拷貝中的淺拷貝與深拷貝是針對(duì)復(fù)雜數(shù)據(jù)類型引用類型的復(fù)制問(wèn)題。 什么是深拷貝,什么是淺拷貝 JS中的淺拷貝與深拷貝是針對(duì)復(fù)雜數(shù)據(jù)類型(引用類型)的復(fù)制問(wèn)題。 淺拷貝:淺拷貝是拷貝引用(拷貝地址),拷貝后兩個(gè)變量指向的是同一塊內(nèi)存空間 深拷貝:會(huì)在內(nèi)存中開(kāi)辟一塊新的內(nèi)存空間,它不僅將原對(duì)象的各個(gè)屬性逐個(gè)復(fù)制過(guò)去,而且將原對(duì)象各個(gè)屬性所包含的內(nèi)容也依次采用深復(fù)制的方法...
閱讀 2688·2021-11-16 11:53
閱讀 2751·2021-07-26 23:38
閱讀 2082·2019-08-30 15:55
閱讀 1763·2019-08-30 13:21
閱讀 3687·2019-08-29 17:26
閱讀 3317·2019-08-29 13:20
閱讀 885·2019-08-29 12:20
閱讀 3205·2019-08-26 10:21