摘要:對象是的基本塊。和明紅明可以看到改變并沒有改變原始對象,實現了基本的深拷貝。和能正確處理的對象只有等能夠被表示的數據結構,因此函數這種不能被表示的類型將不能被正確處理。
對象介紹
js中包含兩種不同數據類型的值: 基本類型值和引用類型值。 基本類型值指的是簡單的數據段,而引用類型值指的是那些由可能由多個值構成的對象。
js對象都是引用類型,對象是某個特定引用類型的實例。對象是js的基本塊。對象是屬性的集合,屬性是鍵值對。js中看到的大多數引用類型都是Object類型的實例,Object也是js中使用最多的一個類型。
按引用賦值let obj1 = { name : "jack", number: 10 } let obj2 = obj1 // 將obj1的引用賦值給obj2 此時obj1、obj2指向同一塊內存空間 obj2.name = "tom" console.log(obj1.name) // tom
但從一個變量像另一個變量復制引用類型的值時,同樣也會將存儲在變量對象中的值復制一份放到位新的變量分配的空間中。不同的是,這個值的副本實際是一個指針,而這個指針指向存儲在堆中的一個對象。復制操作結束后,兩個變量實際上將引用同一個對象。因此改變其中一個變量就會改變另一個變量。
對象的拷貝方式 1. 復制對象的原始方法是循環遍歷原始對象,然后一個接一個地復制每個屬性。let objCopy = {}; // objCopy 將存儲 mainObj 的副本 function copy(mainObj) { let key; for (key in mainObj) { objCopy[key] = mainObj[key]; // 將每個屬性復制到objCopy對象 } return objCopy; } const mainObj = { a: 2, b: 5, c: { x: 7, y: 4, }, } console.log(copy(mainObj)); objCopy.c.x = 10086 console.log("mainObj.c.x", mainObj.c.x) // 10086
上面的代碼只復制了 mainObj 的可枚舉屬性。
如果原始對象中的一個屬性本身就是一個對象,那么副本和原始對象之間將共享這個對象,從而使其各自的屬性指向同一個對象。
2.淺拷貝淺拷貝是對象共用一個內存地址,對象的變化相互影響。比如常見的賦值引用就是淺拷貝:
let obj1 = { name : "jack", number: 10 } let obj2 = obj1 // 將obj1的引用賦值給obj2 此時obj1、obj2指向同一塊內存空間 obj2.name = "tom" console.log(obj1.name) // tom
let obj = { a: 1, b: { c: 2, }, } let newObj = Object.assign({}, obj); console.log(newObj); // { a: 1, b: { c: 2} } obj.a = 10; console.log(obj); // { a: 10, b: { c: 2} } console.log(newObj); // { a: 1, b: { c: 2} } newObj.a = 20; console.log(obj); // { a: 10, b: { c: 2} } console.log(newObj); // { a: 20, b: { c: 2} } newObj.b.c = 30; console.log(obj); // { a: 10, b: { c: 30} } console.log(newObj); // { a: 20, b: { c: 30} } // 注意: newObj.b.c = 30; 為什么呢..
bject.assign 只是淺拷貝。 newObj.b 和 obj.b 都引用同一個對象,沒有多帶帶拷貝,而是復制了對該對象的引用。任何對對象屬性的更改都適用于使用該對象的所有引用。
注意:原型鏈上的屬性和不可枚舉的屬性不能復制。
let someObj = { a: 2, } let obj = Object.create(someObj, { b: { value: 2, }, c: { value: 3, enumerable: true, }, }); let objCopy = Object.assign({}, obj); console.log(objCopy); // { c: 3 }
someObj 是在 obj 的原型鏈,所以它不會被復制。
屬性 b 是不可枚舉屬性。
屬性 c 具有 可枚舉(enumerable) 屬性描述符,所以它可以枚舉。 這就是為什么它會被復制。
ES6已經有了用于數組解構賦值的 rest 元素,和實現的數組字面展開的操作符。
const array = [ "a", "c", "d", { four: 4 }, ]; const newArray = [...array]; console.log(newArray); // 結果 // ["a", "c", "d", { four: 4 }]
只對淺拷貝有效
3.深拷貝簡單理解深拷貝是將對象放到一個新的內存中,兩個對象的改變不會相互影響。
srcObj = {"name": "明", grade: {"chi": "50", "eng": "50"} }; // copyObj2 = Object.assign({}, srcObj); copyObj2 = JSON.parse(JSON.stringify(srcObj)); copyObj2.name = "紅"; copyObj2.grade.chi = "60"; console.log("JSON srcObj", srcObj); // { name: "明", grade: { chi: "50", eng: "50" } }
可以看到改變copyObj2并沒有改變原始對象,實現了基本的深拷貝。
但是用JSON.parse()和JSON.stringify()會有一個問題。
JSON.parse()和JSON.stringify()能正確處理的對象只有Number、String、Array等能夠被json表示的數據結構,因此函數這種不能被json表示的類型將不能被正確處理。比如
srcObj = {"name": "明", grade: {"chi": "50", "eng": "50"}, "hello": function() {console.log("hello")}}; // copyObj2 = Object.assign({}, srcObj); copyObj2 = JSON.parse(JSON.stringify(srcObj)); copyObj2.name = "紅"; copyObj2.grade.chi = "60"; console.log("JSON srcObj", copyObj2); //{ name: "紅", grade: { chi: "60", eng: "50" } }
可以看出,經過轉換之后,function丟失了,因此JSON.parse()和JSON.stringify()還是需要謹慎使用。
數組的深拷貝和淺拷貝最后在補充一點數組的深拷貝和淺拷貝,同對象一樣數組的淺拷貝也是改變其中一個會相互影響,比如:
let srcArr = [1, 2, 3]; let copyArr = srcArr; copyArr[0] = "0"; console.log("srcArr", srcArr); // ["0", 2, 3]
但是數組的深拷貝方法要相對簡單一些可以理解為數組方法中那些會改變原數組的方法,比如
concat
slice
es6 的Array.from
博客參考
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/106404.html
摘要:接下來就讓我們更細致的探究中的深淺拷貝。總結以上對深拷貝和淺拷貝做了簡單的介紹,在深拷貝的實現上也只介紹了最簡單的實現形式,并未考慮復雜情況以及相應優化,想要對深拷貝有更深入的了解,需要大家花時間去深入研究,或者可以關注我后續文章的動態。 對象和數組的拷貝對我來說一直都是一個比較模糊的概念,一直有點一知半解,但是在實際工作中又偶爾會涉及到,有時候還會一不小心掉坑里,不知道大家有沒有同樣...
摘要:一篇文章徹底說清的深拷貝淺拷貝這篇文章的受眾第一類業務需要急需知道如何深拷貝對象的開發者。這篇文章分享的目的更多還是希望用一篇文章整理清楚深淺拷貝的含義遞歸實現思路以及小伙伴們如果使用了這種黑科技一定要清楚這樣寫的優缺點。 一篇文章徹底說清JS的深拷貝and淺拷貝 這篇文章的受眾 第一類,業務需要,急需知道如何深拷貝JS對象的開發者。 第二類,希望扎實JS基礎,將來好去面試官前秀操作...
摘要:一篇文章徹底說清的深拷貝淺拷貝這篇文章的受眾第一類業務需要急需知道如何深拷貝對象的開發者。這篇文章分享的目的更多還是希望用一篇文章整理清楚深淺拷貝的含義遞歸實現思路以及小伙伴們如果使用了這種黑科技一定要清楚這樣寫的優缺點。 一篇文章徹底說清JS的深拷貝and淺拷貝 這篇文章的受眾 第一類,業務需要,急需知道如何深拷貝JS對象的開發者。 第二類,希望扎實JS基礎,將來好去面試官前秀操作...
摘要:一篇文章徹底說清的深拷貝淺拷貝這篇文章的受眾第一類業務需要急需知道如何深拷貝對象的開發者。這篇文章分享的目的更多還是希望用一篇文章整理清楚深淺拷貝的含義遞歸實現思路以及小伙伴們如果使用了這種黑科技一定要清楚這樣寫的優缺點。 一篇文章徹底說清JS的深拷貝and淺拷貝 這篇文章的受眾 第一類,業務需要,急需知道如何深拷貝JS對象的開發者。 第二類,希望扎實JS基礎,將來好去面試官前秀操作...
摘要:它將返回目標對象。有些文章說是深拷貝,其實這是不正確的。深拷貝相比于淺拷貝速度較慢并且花銷較大。拷貝前后兩個對象互不影響。使用深拷貝的場景完全改變變量之后對沒有任何影響,這就是深拷貝的魔力。 一、賦值(Copy) 賦值是將某一數值或對象賦給某個變量的過程,分為: 1、基本數據類型:賦值,賦值之后兩個變量互不影響 2、引用數據類型:賦址,兩個變量具有相同的引用,指向同一個對象,相互之間有...
閱讀 2801·2023-04-25 22:51
閱讀 2025·2021-10-11 10:58
閱讀 3308·2019-08-30 10:49
閱讀 1870·2019-08-29 17:09
閱讀 3135·2019-08-29 10:55
閱讀 839·2019-08-26 10:34
閱讀 3465·2019-08-23 17:54
閱讀 980·2019-08-23 16:06