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