摘要:在之前的文章專題之數據類型和類型檢測中我有講過,中的數據類型分為兩種,基本數據類型和引用數據類型,基本數據類型是保存在棧的數據結構中的是按值訪問,所以不存在深淺拷貝問題。
前言
在開發過程中,偶爾會遇到這種場景,拿到一個數據后,你打算對它進行處理,但是你又希望拷貝一份副本出來,方便數據對比和以后恢復數據。
那么這就涉及到了 JS 中對數據的深淺拷貝問題,所謂深淺拷貝,淺拷貝的意思就是,你只是復制了對象數據的引用,并沒有把內存里的值另外復制一份,那么深拷貝就是把值完整地復制一份新的值。
在之前的文章《JS專題之數據類型和類型檢測》中我有講過,JS 中的數據類型分為兩種,基本數據類型和引用數據類型,基本數據類型是保存在棧的數據結構中的,是按值訪問,所以不存在深淺拷貝問題。
而比如對象,數組,函數,正則,時間對象這些都是引用數據類型,是保存在堆中的。所以,引用數據類型的復制,是內存地址的傳遞,并沒有拷貝出一份新的數據。
那么深拷貝,淺拷貝的區別是什么呢?先給結論:
操作拷貝之后的數據不會影響到原數據的值拷貝,就是深拷貝,反正,有影響則為淺拷貝。一、應用場景
日常開發中,JS 拷貝大多會在 數據保存,數據比對,數據同步 時出現,所以,當你在這些場景的時候,要記得里面隱藏有一個數據深淺拷貝的問題。
二、淺拷貝我們來看一下淺拷貝:
function clone(origin) { var result = {}; for (var prop in origin) { if (origin.hasOwnProperty(prop)) { result[prop] = origin[prop]; } } return result; } var jay = { name: "jayChou", age: 40, family: { wife: "Quinlivan" } } var otherJay = clone(jay); otherJay.age = 18; otherJay.family.wife = "otherGirl"; console.log(jay); // // { // name: "jayChou", // age: 40, // 沒被改變 // family: { // wife: "otherGirl" // 同時被改變,說明是同一個引用 // } // } console.log(otherJay); // // { // name: "jayChou", // age: 18, // family: { // wife: "otherGirl" // 被改變了 // } // }
我們發現,首先,淺拷貝不是直接賦值,淺拷貝新建了一個對象,然后將源對象的屬性都一一復制過來,復制的是值,而不是引用。
我們知道,對象都是按地址引用進行訪問的,淺拷貝的復制只復制了第一層的屬性,并沒有遞歸將所有的值復制過來,所以,操作拷貝數據,對原數據產生了影響,故而為淺拷貝。
進而,那些可以直接返回原數組的方法就可以簡單實現數組和對象淺拷貝。
// 1、 數組淺拷貝 - slice function shallowCopy1(origin) { return origin.slice(); } // 2、 數組淺拷貝 - concat function shallowCopy2(origin){ return origin.concat(); } // 3、 數組淺拷貝 - 遍歷 function shallowCopy3(origin){ var result = []; for(var i = 0; i < origin.length; i++) { result.push(origin[i]); } return result; } // 4、 對象淺拷貝 - Object.assign function shallowCopy4(origin) { return Object.assign({},origin) } // 5、 對象淺拷貝 - 擴展運算符 // 擴展運算符(...)用于取出參數對象的所有可遍歷屬性,拷貝到當前對象之中 function shallowCopy5(origin) { return { ...origin } }
Object.assign 的拷貝,假如源對象的屬性值是一個指向對象的引用,它也只拷貝那個引用值。MDN 有相應的實例和解釋。
二、深拷貝深拷貝就完整復制數據的值(而非引用),目的在于避免拷貝后數據對原數據產生影響。
目前深拷貝的實現方法主要有遞歸復制,JSON 正反序列化:
// 1. 深拷貝 - JSON 正反序列化 // 缺點就是無法拷貝 undefined、function、symbol 這類特殊的屬性值。 function deepClone1(origin) { return JSON.parse(JSON.stringify(arr)); } // 2. 深拷貝 - 遞歸; function deepClone2(origin) { const result = origin.constructor === Array ? [] : {}; for (let keys in origin) { // 不遍歷原型鏈上的屬性 if (origin.hasOwnProperty(keys)) { if (origin[keys] && typeof origin[keys] === "object") { // 如果值是對象,就遞歸一下, 區分是一般對象還是數組對象 result[keys] = origin[keys].constructor === Array ? [] : {}; // 如果是引用數據類型,會遞歸調用 result[keys] = deepClone(origin[keys]); } else { // 如果不是,就直接賦值 result[keys] = origin[keys]; } } } return result; }
JS 的深拷貝的應用,需要根據你的使用場景進行使用,首先是有無必要深拷貝,其次是數據類型,是否直接使用 JSON 的 API 其實就可以。
JS 深淺拷貝在日常開發中使用頻率還是較高的,其中考察的知識點,主要在于:
1、是否遇到過深淺拷貝的問題,里面有什么坑
2、是否了解 JS 的數據類型,數據在計算機中的存儲機制
3、是否了解數組、對象的一些常用的 API
4、jquery、lodash、underscore 的相關工具函數使用
深淺拷貝主要考察了開發者對 JS 數據類型的了解,數組,對象常用方法的特點和應用,遞歸函數的封裝。
春節快樂!
寫于大年三十,不寫文章渾身不舒服~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/101529.html
摘要:專題系列第六篇,講解深淺拷貝的技巧和以及實現深淺拷貝的思路前言拷貝也是面試經典吶數組的淺拷貝如果是數組,我們可以利用數組的一些方法比如返回一個新數組的特性來實現拷貝。所以我們可以看出使用和是一種淺拷貝。 JavaScript 專題系列第六篇,講解深淺拷貝的技巧和以及實現深淺拷貝的思路 前言 拷貝也是面試經典吶! 數組的淺拷貝 如果是數組,我們可以利用數組的一些方法比如:slice、co...
摘要:專題系列共計篇,主要研究日常開發中一些功能點的實現,比如防抖節流去重類型判斷拷貝最值扁平柯里遞歸亂序排序等,特點是研究專題之函數組合專題系列第十六篇,講解函數組合,并且使用柯里化和函數組合實現模式需求我們需要寫一個函數,輸入,返回。 JavaScript 專題之從零實現 jQuery 的 extend JavaScritp 專題系列第七篇,講解如何從零實現一個 jQuery 的 ext...
摘要:基本數據類型的復制很簡單,就是賦值操作,所以深淺拷貝也是針對,這類引用類型數據。它會拋棄對象的。另外,查資料過程中還看到這么一個詞結構化克隆算法還有這一篇資料也有參考,也寫得比較詳細了的深淺拷貝 基本數據類型的復制很簡單,就是賦值操作,所以深淺拷貝也是針對Object,Array這類引用類型數據。 淺拷貝對于字符串來說,是值的復制,而對于對象來說則是對對象地址的復制;而深拷貝的話,它不...
摘要:寫在前面專題系列是我寫的第二個系列,第一個系列是深入系列。專題系列自月日發布第一篇文章,到月日發布最后一篇,感謝各位朋友的收藏點贊,鼓勵指正。 寫在前面 JavaScript 專題系列是我寫的第二個系列,第一個系列是 JavaScript 深入系列。 JavaScript 專題系列共計 20 篇,主要研究日常開發中一些功能點的實現,比如防抖、節流、去重、類型判斷、拷貝、最值、扁平、柯里...
摘要:為何寫最近在研究深淺拷貝,找了很多資料,感覺不是很滿意,所以自己就整理了一份。深拷貝如果給放到新的內存中,將的各個屬性都復制到新內存里,就是深拷貝。安全的值是指能夠呈現為有效格式的值。參考文檔冴羽的專題之深淺拷貝深拷貝與淺拷貝的實現 為何寫: 最近在研究深淺拷貝,找了很多資料,感覺不是很滿意,所以自己就整理了一份。廢話不多說,我們來一起復習一下吧,也希望留下您寶貴意見。 何為深淺拷貝?...
閱讀 3674·2021-11-23 09:51
閱讀 1035·2021-11-19 11:30
閱讀 3360·2019-08-29 14:16
閱讀 3369·2019-08-29 12:12
閱讀 2363·2019-08-26 13:40
閱讀 3471·2019-08-26 12:21
閱讀 3073·2019-08-26 11:55
閱讀 2221·2019-08-26 11:35