摘要:接下來就讓我們更細致的探究中的深淺拷貝。總結以上對深拷貝和淺拷貝做了簡單的介紹,在深拷貝的實現上也只介紹了最簡單的實現形式,并未考慮復雜情況以及相應優化,想要對深拷貝有更深入的了解,需要大家花時間去深入研究,或者可以關注我后續文章的動態。
對象和數組的拷貝對我來說一直都是一個比較模糊的概念,一直有點一知半解,但是在實際工作中又偶爾會涉及到,有時候還會一不小心掉坑里,不知道大家有沒有同樣的感受,因此,準備對js對象和數組拷貝一探究竟。提到js的對象和數組拷貝,大家一定會想深拷貝和淺拷貝,但是為什么會有深拷貝和淺拷貝呢?下面就讓我簡單介紹一下為什么拷貝會有深淺之分以及有什么區別?
原因及區別我們都知道js中有兩種數據類型,一種是基本數據類型,一種是引用數據類型,基本數據類型是按值訪問的,即在操作基本類型的變量時,是直接修改變量的值,而引用數據類型的值是按引用訪問的,什么叫按引用訪問的呢?js的引用類型,也叫對象類型,是保存在內存中的,而在js中又無法直接操作內存中的對象,實際上操作的是對象的引用,因此在引用類型變量在進行復制操作時,并不是對對象值的直接復制,而是將對象的引用復制給了另一個變量,實際上變量指向的是同一個內存地址中對象的值,因此只要改變其中一個對象變量的值另外一個就會一起改變,這就是我們常說的淺拷貝。而在深拷貝中,會開辟一個新的內存地址用來存放新對象的值,兩個對象對應兩個不同的內存地址 ,修改一個對象并不會對另外一個對象產生影響。接下來就讓我們更細致的探究js中的深淺拷貝。
淺拷貝實現淺拷貝的方法有多種,讓我們先來看看js中提供的幾個自帶方法實現淺拷貝的的例子:
Object.assign()方法用于將所有可枚舉屬性的值從一個或多個源對象復制到目標對象。它將返回目標對象。注意:Object.assign()拷貝的是屬性值,假如源對象的屬性值是一個指向對象的引用,它也只拷貝那個引用值,來看個例子:
var a = {a : "old", b : { c : "old"}} var b = Object.assign({}, a) b.a = "new" b.b.c = "new" console.log(a) // { a: "old", b: { c: "new" } } console.log(b) // { a: "new", b: { c: "new" } }
如上面例子,當拷貝的源對象的屬性值是一個對象時,拷貝的只是對象的引用值,因此當修改屬性值的時候兩個對象的屬性值都會發生更新
Array.prototype.slice()方法提取并返回一個新的數組,如果源數組中的元素是個對象的引用,slice會拷貝這個對象的引用到新的數組,來看個例子:
var arr = ["a", "b", {d: "old"}] var arr1 = arr.slice(1) arr1[1].d = "new" console.log(arr[2].d) // new
如上例所示,但源數組中的元素是對象引用時,slice拷貝的是這個對象的引用,因此當修改其中一個的值時,兩個數組中的值都會發生改變
Array.prototype.concat()用于合并多個數組,并返回一個新的數組,和slice方法類似,當源數組中的元素是個對象的引用,concat在合并時拷貝的就是這個對象的引用,來看個例子:
var arr1 = [{a: "old"}, "b", "c"] var arr2 = [{b: "old"}, "d", "e"] var arr3 = arr1.concat(arr2) arr3[0].a = "new" arr3[3].b = "new" console.log(arr1[0].a) // new console.log(arr2[0].b) // new
除了上述js中自帶方法實現的淺拷貝外,我們自己如何簡單實現一個淺拷貝呢?來看個例子:
function copy(obj) { if (!obj || typeof obj !== "object") { return } var newObj = obj.constructor === Array ? [] : {} for (var key in obj) { newObj[key] = obj[key] } return newObj } var a = {b: "bb", c: "cc", d: {e: "ee"}} var b = copy(a) console.log(b) // { b: "bb", c: "cc", d: { e: "ee" } }
實現一個淺拷貝,就是遍歷源對象,然后在將對象的屬性的屬性值都放到一個新對象里就ok了,是不是很簡單呢?
深拷貝先來介紹一個做深拷貝最簡單粗暴的方法JSON.stringify()和JSON.parse()的混合配對使用,相信大家對這兩個方法都是非常熟悉的,來看個例子:
var obj = {a: {b: "old"}} var newObj = JSON.parse(JSON.stringify(obj)) newObj.a.b = "new" console.log(obj) // { a: { b: "old" } } console.log(newObj) // { a: { b: "new" } }
上述例子可以看出,使用JSON.stringify()和JSON.parse()確實可以實現深拷貝,在新對象中修改對象的引用時,并不會影響老對象里面的值,那么,這么個方法是否就沒有缺陷了呢?在JSON.stringify()做序列時,undefined、任意的函數以及symbol值,在序列化過程中會被忽略,這會在對象復制的時候導致什么后果呢?來看一個例子:
var obj = {a: {b: "old"}, c:undefined, d: function () {}, e: Symbol("")} var newObj = JSON.parse(JSON.stringify(obj)) newObj.a.b = "new" console.log(obj) // { a: { b: "old" }, c: undefined, d: [Function: d], e: Symbol() } console.log(newObj) // { a: { b: "new" } }
從例子中可以看到,當源對象中有undefine、function、symbol時,在序列化操作的時候會被忽略,導致拷貝生成的對象中沒有對應屬性及屬性值。那么怎么自己去實現一個深拷貝呢?比較常見的方法就是通過遞歸,來看個例子:
function copy(obj) { if (!obj || typeof obj !== "object") { return } var newObj = obj.constructor === Array ? [] : {} for (var key in obj) { if (obj.hasOwnProperty(key)) { if (typeof obj[key] === "object" && obj[key]) { newObj[key] = copy(obj[key]) } else { newObj[key] = obj[key] } } } return newObj } var old = {a: "old", b: {c: "old"}} var newObj = copy(old) newObj.b.c = "new" console.log(old) // { a: "old", b: { c: "old" } } console.log(newObj) // { a: "old", b: { c: "new" } }
通過對需要拷貝的對象的屬性進行遞歸遍歷,如果對象的屬性不是基本類型時,就繼續遞歸,知道遍歷到對象屬性為基本類型,然后將屬性和屬性值賦給新對象。
總結以上對js深拷貝和淺拷貝做了簡單的介紹,在深拷貝的實現上也只介紹了最簡單的實現形式,并未考慮復雜情況以及相應優化,想要對深拷貝有更深入的了解,需要大家花時間去深入研究,或者可以關注我后續文章的動態。
這篇文章如果有錯誤或不嚴謹的地方,歡迎批評指正,如果喜歡,歡迎點贊收藏
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/99160.html
摘要:本文解釋中深拷貝和淺拷貝的區別。深拷貝深拷貝指遞歸的復制對象的屬性給新對象。有些時候一層的深拷貝被認為是淺拷貝,比如的值是一個對象,淺拷貝出來的新對象直接引用了原對象的對象,所以也會相互影響的。 本文解釋javascript中深拷貝和淺拷貝的區別。 淺拷貝/Shallow Copy 淺拷貝指拷貝了引用值。 var original = {prop1 : Prop1, prop2 : p...
摘要:深拷貝和淺拷貝的區別背景最近在用框架寫頁面,賦值給中的對象時會出現一個問題,賦值和被賦值對象之中任何一個有變化,另一個也會隨之變化。 深拷貝和淺拷貝的區別 背景:最近在用vue框架寫頁面,賦值給Vue.$data中的對象時會出現一個問題,賦值和被賦值對象之中任何一個有變化,另一個也會隨之變化。例如: var b = { foo: 123 }; var vm = new Vue(...
摘要:參考鏈接淺拷貝最簡單的淺拷貝就賦值。所謂的淺拷貝就是,后面的對象和前面的對象在第一層數據結構中指向同一個堆地址。但是如果前面的數據不止有一層,如此時,使用和方式實現的都是淺拷貝。深拷貝管你怎么變,互不影響。 參考鏈接:http://www.cnblogs.com/st-les...https://blog.csdn.net/hj7jay/... 淺拷貝: 1.最簡單的淺拷貝就賦值。由于...
閱讀 1118·2021-10-09 09:43
閱讀 18475·2021-09-22 15:52
閱讀 1059·2019-08-30 15:44
閱讀 3050·2019-08-30 15:44
閱讀 3244·2019-08-26 14:07
閱讀 904·2019-08-26 13:55
閱讀 2566·2019-08-26 13:41
閱讀 3087·2019-08-26 13:29