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