摘要:基本數據類型的復制很簡單,就是賦值操作,所以深淺拷貝也是針對,這類引用類型數據。它會拋棄對象的。另外,查資料過程中還看到這么一個詞結構化克隆算法還有這一篇資料也有參考,也寫得比較詳細了的深淺拷貝
基本數據類型的復制很簡單,就是賦值操作,所以深淺拷貝也是針對Object,Array這類引用類型數據。
淺拷貝對于字符串來說,是值的復制,而對于對象來說則是對對象地址的復制;實現方式 原生JS實現:而深拷貝的話,它不僅將對象的各個屬性逐個復制出來,還將各個屬性所包含的對象也依次復制出來,相當于在堆區又新開了一塊地存放,主要采取遞歸來實現。
淺拷貝:
let originObj={ color:["red","green"], num:5 }; function shallowClone(obj){ let newObj=(obj instanceof Array) ? []:{}; for(let item in obj){ if(obj.hasOwnProperty(item)){ // 避免列舉出原型上的屬性 newObj[item]=obj[item]; } } return newObj; } let cloneObj=shallowClone(originObj);
深拷貝:
function deepClone(obj){ let newObj=(obj instanceof Array)? [] : {}; for(let item in obj){ if(obj.hasOwnProperty){ const val=obj[item]; debugger newObj[item]=typeof val==="object" ? deepClone(val) : val; } } return newObj; } let cloneObj2=deepClone(originObj);
其實,這種深拷貝的實現還是有些問題的,比如日期,正則對象無法復制,還有一個是循環引用,類似閉包會內存泄露一樣,這樣的對象深拷貝也會陷入一個閉環,直到棧溢出。
為了解決這個問題,就得先判斷這個對象是否等于原對象。
function deepClone(obj){ let tempArr=[]; let newObj=(obj instanceof Array) ? [] : {}; tempArr.push(obj); for(let item in obj){ if(typeof obj[item] === "object"){ const index=tempArr.indexOf(obj[item]); // 如果已存在,證明引用了相同對象,那么無論是循環引用還是重復引用,我們返回引用就可以了 if(index>-1){ newObj[item]=tempArr[index]; }else{ newObj[item]=obj[item]; } }else{ newObj[item]=obj[item]; } } return newObj; }ES6實現
let newObj1=Object.assgin({},originObj); let newObj2={...obj}; // 數組用[...obj]
注:Object.assgin和擴展運算符實現的都是淺拷貝。JSON實現:
這種方法簡單是簡單,不過這個方法有以下缺陷:
1.會忽略函數對象以及原型對象,正則會復制成空對象,而日期對象會變成字符串。 2.它會拋棄對象的constructor。也就是深拷貝之后,不管這個對象原來的構造函數是什么,在深拷貝之后都會變成Object; 3.如果對象中存在循環引用的情況無法正確處理。
按需取用吧。
let originObj={fn:function(){console.log(111)}, colors:["red","gree"],reg:/s/g}; let newObj=JSON.parse(JSON.stringify(originObj));第三方庫實現:
轉自鏈接:深入剖析 JavaScript 的深復制
Underscore —— _.clone()順便安利下underscore,真的挺好用的一個庫: Underscore中文文檔
這個方法實際上是一種淺復制 (shallow-copy),所有嵌套的對象和數組都是直接復制引用而并沒有進行深復制。
let originObj={ color:["red","green"], num:5 }; let newObj=_.clone(originObj); newObj.colors.push("grey"); originObj.colors; // ["red","green","grey"];
源碼邏輯很簡單:(當然調用的其他方法也是underscore的)
// Create a (shallow-cloned) duplicate of an object. _.clone = function(obj) { if (!_.isObject(obj)) return obj; return _.isArray(obj) ? obj.slice() : _.extend({}, obj); }jQuery —— $.extend()
這個用法很簡單:
let originObj={ color:["red","green"], num:5 }; let shallowClone=$.extend({},originObj); // 淺拷貝 let deepClone=$.extend(true,{},originObj); // 深拷貝,第一個參數表示是否深度合并對象lodash —— _.clone() / _.cloneDeep()
lodash深拷貝——這個算是這幾個里面最完善的方法了,日期,函數,正則對象通通都能復制。
在lodash中關于復制的方法有兩個,分別是_.clone()和_.cloneDeep()。其中_.clone(obj, true)等價于_.cloneDeep(obj)。
沒引入的可以點擊上面的文檔鏈接去直接改動代碼試試看。
另外,查資料過程中還看到這么一個詞:結構化克隆算法
還有這一篇資料也有參考,也寫得比較詳細了:JS的深淺拷貝
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/99349.html
摘要:為何寫最近在研究深淺拷貝,找了很多資料,感覺不是很滿意,所以自己就整理了一份。深拷貝如果給放到新的內存中,將的各個屬性都復制到新內存里,就是深拷貝。安全的值是指能夠呈現為有效格式的值。參考文檔冴羽的專題之深淺拷貝深拷貝與淺拷貝的實現 為何寫: 最近在研究深淺拷貝,找了很多資料,感覺不是很滿意,所以自己就整理了一份。廢話不多說,我們來一起復習一下吧,也希望留下您寶貴意見。 何為深淺拷貝?...
摘要:一數據類型基本類型引用類型類型判斷返回結果未定義布爾值字符串數值對象或者函數拓展堆棧兩種數據結構堆隊列優先,先進先出由操作系統自動分配釋放,存放函數的參數值,局部變量的值等。 一、數據類型 基本類型:`Null Boolean String Undefined Number(NB SUN)` 引用類型:`Array Function Object` 類型判斷:typeof 返回結果...
摘要:專題系列第六篇,講解深淺拷貝的技巧和以及實現深淺拷貝的思路前言拷貝也是面試經典吶數組的淺拷貝如果是數組,我們可以利用數組的一些方法比如返回一個新數組的特性來實現拷貝。所以我們可以看出使用和是一種淺拷貝。 JavaScript 專題系列第六篇,講解深淺拷貝的技巧和以及實現深淺拷貝的思路 前言 拷貝也是面試經典吶! 數組的淺拷貝 如果是數組,我們可以利用數組的一些方法比如:slice、co...
摘要:專題系列共計篇,主要研究日常開發中一些功能點的實現,比如防抖節流去重類型判斷拷貝最值扁平柯里遞歸亂序排序等,特點是研究專題之函數組合專題系列第十六篇,講解函數組合,并且使用柯里化和函數組合實現模式需求我們需要寫一個函數,輸入,返回。 JavaScript 專題之從零實現 jQuery 的 extend JavaScritp 專題系列第七篇,講解如何從零實現一個 jQuery 的 ext...
閱讀 1588·2019-08-30 13:18
閱讀 1578·2019-08-29 12:19
閱讀 2094·2019-08-26 13:57
閱讀 4137·2019-08-26 13:22
閱讀 1179·2019-08-26 10:35
閱讀 2991·2019-08-23 18:09
閱讀 2500·2019-08-23 17:19
閱讀 677·2019-08-23 17:18