摘要:如何深度克隆一個對象在我們?nèi)粘9ぷ髦薪?jīng)常會遇到需要去克隆一個對象比如多個地方用到的公共的圖表基本參數(shù)的配置相信很多人會想到用和方法去克隆一個對象,這個可以明確告訴大家這些都是些不靠譜的淺度克隆。
如何深度克隆一個對象
在我們?nèi)粘9ぷ髦薪?jīng)常會遇到需要去克隆一個對象比如多個地方用到的公共的圖表基本參數(shù)的配置
相信很多人會想到用 Object.assign, JSON.stringify 和 JSON.parse 方法去克隆一個對象,這個可以明確告訴大家這些都是些不靠譜的淺度克隆。
我們先來試一下 Object.assign 在控制臺執(zhí)行下列操作大家有沒有發(fā)現(xiàn)聯(lián)動了。關(guān)于此方法具體請參考文檔
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
大家有沒有發(fā)現(xiàn)什么異常?雖然 JSON.stringify(value[, replacer[, space]]) 可以處理但是太麻煩了,這個方法我就不多說了具體還是參考文檔
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
function isArray (arr) { return Object.prototype.toString.call(arr) === "[object Array]"; } // 深度克隆 function deepClone (obj) { if(typeof obj !== "object" && typeof obj !== "function") { return obj; //原始類型直接返回 } var o = isArray(obj) ? [] : {}; for(i in obj) { if(obj.hasOwnProperty(i)){ o[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i]; } } return o; }
看是靠譜是真是假我們來驗證一把 還是在控制臺輸入
大家發(fā)現(xiàn)什么異常的了嗎?
這個沒有區(qū)分具體的對象,在此問下大家js的對象有哪些呢?相信一般人答不出來4個
[object Object], [object Array], [object Null], [object RegExp], [object Date], [object HTMLXXElement], [object Map],[object Set],... 等等一系列
檢測類型使用 Object.prototype.toString.call(xxx) 和 typeof
我們分析下上面對象中哪些是引用類型需要特殊處理呢?相信大家都不陌生了。[object Object] 和 [object Array]
好!詳細大家思路有了,咋們用遞歸來實現(xiàn)一把吧!
const deepClone = function(obj) { // 先檢測是不是數(shù)組和Object // let isMap = Object.prototype.toString.call(obj) === "[object Map]; // let isSet = Object.prototype.toString.call(obj) === "[object Set]; // let isArr = Object.prototype.toString.call(obj) === "[object Array]"; let isArr = Array.isArray(obj); let isJson = Object.prototype.toString.call(obj) === "[object Object]"; if (isArr) { // 克隆數(shù)組 let newObj = []; for (let i = 0; i < obj.length; i++) { newObj[i] = deepClone(obj[i]); } return newObj; } else if (isJson) { // 克隆Object let newObj = {}; for (let i in obj) { newObj[i] = deepClone(obj[i]); } return newObj; } // 不是引用類型直接返回 return obj; }; Object.prototype.deepClone = function() { return deepClone(this); };
咋們先不考慮Map Set Arguments [object XXArrayBuffer] 對象了原理都是一樣
各種情況分析完了才說算是真克隆
我們在控制臺看下
注意先要把方法在控制臺輸進去,在調(diào)試
是不是解決了? 在此并沒有結(jié)束。 專注的伙伴們相信發(fā)現(xiàn)了對象中包含了個 deepClone 方法,具體細節(jié)我們在此就不多說了,我們給 Object 添加了個 Object.prototype.deepClone方法導(dǎo)致了每個對象都有了此方法。
原則上我們不允許在原型鏈上添加方法的,因為在循環(huán)中 for in, Object.entries, Object.values, Object.keys 等方法會出現(xiàn)自定義的方法。
相信熟悉 Object 文檔的伙伴人已經(jīng)知道解決方案了,
Object.defineProperty 這個方法給大家?guī)砹烁R?具體參考 Object 文檔。我們使用一個enumerable (不可枚舉)屬性就可以解決了。
在原來基礎(chǔ)上添加以下代碼即可。
Object.defineProperty(Object.prototype, "deepClone", {enumerable: false});
在看控制臺
同樣上面方法中也是無法克隆一個不可枚舉的屬性。
完整代碼如下
const deepClone = function(obj) { // 先檢測是不是數(shù)組和Object // let isArr = Object.prototype.toString.call(obj) === "[object Array]"; let isArr = Array.isArray(obj); let isJson = Object.prototype.toString.call(obj) === "[object Object]"; if (isArr) { // 克隆數(shù)組 let newObj = []; for (let i = 0; i < obj.length; i++) { newObj[i] = deepClone(obj[i]); } return newObj; } else if (isJson) { // 克隆Object let newObj = {}; for (let i in obj) { newObj[i] = deepClone(obj[i]); } return newObj; } // 不是引用類型直接返回 return obj; }; Object.prototype.deepClone = function() { return deepClone(this); }; Object.defineProperty(Object.prototype, "deepClone", {enumerable: false});
為了兼容低版本瀏覽器需要借助 babel-polyfill;
好了,深度克隆介紹到此。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/94181.html
摘要:在聊以下簡稱深度克隆之前,我們先來了解一下中對象的組成??寺』蛘呖截惙譃榉N淺度克隆深度克隆。淺度克隆基本類型為值傳遞,對象仍為引用傳遞。 該文轉(zhuǎn)載自http://www.cnblogs.com/zichi/p/4568150.html,有部分修改。 在聊JavaScript(以下簡稱js)深度克隆之前,我們先來了解一下js中對象的組成。在 js 中一切實例皆是對象,具體分為 原始類型 ...
摘要:原型模式是創(chuàng)建模式的一種,其作用是提高創(chuàng)建效率,減少計算機資源開銷,與工廠模式類似的是,都屏蔽了對象實例化的過程概述原型模式是模式的一種,其特點就是通過克隆拷貝的方式來,節(jié)約創(chuàng)建成本和資源,被拷貝的對象模型就稱之為原型。 原型模式(Prototype Pattern)是創(chuàng)建模式的一種,其作用是提高創(chuàng)建效率,減少計算機資源開銷,與工廠模式類似的是,都屏蔽了對象實例化的過程... 概述 ...
摘要:對象詳解對象深度剖析,深度理解對象這算是醞釀很久的一篇文章了。用空構(gòu)造函數(shù)設(shè)置類名每個對象都共享相同屬性每個對象共享一個方法版本,省內(nèi)存。 js對象詳解(JavaScript對象深度剖析,深度理解js對象) 這算是醞釀很久的一篇文章了。 JavaScript作為一個基于對象(沒有類的概念)的語言,從入門到精通到放棄一直會被對象這個問題圍繞。 平時發(fā)的文章基本都是開發(fā)中遇到的問題和對...
摘要:深度克隆方法,返回一個新的克隆對象這里得說明深拷貝與錢拷貝的區(qū)別,淺拷貝是復(fù)制一個對象的引用,深拷貝是一個新的對象,與原對象有著不同的內(nèi)存地址方法一通過遞歸遍歷一個對象,返回一個新的對象深拷貝要深拷貝的值判斷某個對象是否含有指定的屬性該方法 深度克隆方法,返回一個新的克隆對象這里得說明深拷貝與錢拷貝的區(qū)別,淺拷貝是復(fù)制一個對象的引用,深拷貝是chone一個新的對象,與原對象有著不同的內(nèi)...
摘要:定義是一個計算屬性類似于過濾器對綁定到的數(shù)據(jù)進行處理用法不可在里面定義如果定義會報如下圖片的錯誤因為對應(yīng)的作為計算屬性定義并返回對應(yīng)的結(jié)果給這個變量變量不可被重復(fù)定義和賦值和用法回調(diào)函數(shù)當需要讀取當前屬性值是執(zhí)行,根據(jù)相關(guān)數(shù)據(jù)計算并返回當前 1.computed 1.1 定義 是一個計算屬性,類似于過濾器,對綁定到view的數(shù)據(jù)進行處理 1.2 get用法 data: { ...
閱讀 2047·2023-04-25 15:24
閱讀 1586·2019-08-30 12:55
閱讀 1624·2019-08-29 15:27
閱讀 477·2019-08-26 17:04
閱讀 2415·2019-08-26 10:59
閱讀 1811·2019-08-26 10:44
閱讀 2207·2019-08-22 16:15
閱讀 2596·2019-08-22 15:36