摘要:淺拷貝和深拷貝本質(zhì)上的原因是對(duì)象引用的是地址,直接賦值會(huì)吧引用地址也復(fù)制給新值。深拷貝是會(huì)遞歸源數(shù)據(jù),吧新值得引用地址給換掉。對(duì)遞歸對(duì)遞歸調(diào)用是否是類型數(shù)組這里主要是會(huì)有個(gè)的特殊數(shù)組返回的特殊數(shù)組其他方法庫(kù)或等
淺拷貝和深拷貝
本質(zhì)上的原因是對(duì)象引用的是地址,直接賦值會(huì)吧引用地址也復(fù)制給新值。
淺復(fù)制只會(huì)將對(duì)象的各個(gè)屬性進(jìn)行依次復(fù)制,會(huì)把引用地址也復(fù)制。
深拷貝是會(huì)遞歸源數(shù)據(jù),吧新值得引用地址給換掉。
入口
const CLONE_DEEP_FLAG = 1 const CLONE_SYMBOLS_FLAG = 4 function cloneDeep(value) { return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG) }
核心邏輯
function baseClone(value, bitmask, customizer, key, object, stack) { let result const isDeep = bitmask & CLONE_DEEP_FLAG const isFlat = bitmask & CLONE_FLAT_FLAG const isFull = bitmask & CLONE_SYMBOLS_FLAG if (customizer) { result = object ? customizer(value, key, object, stack) : customizer(value) } if (result !== undefined) { return result } if (!isObject(value)) { return value } // 判斷是否數(shù)組 const isArr = Array.isArray(value) // 獲取constructor const tag = getTag(value) if (isArr) { // 初始化一個(gè)長(zhǎng)度和源相等的數(shù)組 result = initCloneArray(value) // 不是deep就直接復(fù)制了事 if (!isDeep) { return copyArray(value, result) } } else { const isFunc = typeof value == "function" // Buffer.isBuffer, 對(duì)于buffer對(duì)象就直接復(fù)制了事 if (isBuffer(value)) { return cloneBuffer(value, isDeep) } if (tag == objectTag || tag == argsTag || (isFunc && !object)) { // 是否需要繼承proto result = (isFlat || isFunc) ? {} : initCloneObject(value) if (!isDeep) { // 這里deepclone的isFlat是0,走copySymbols,這個(gè)方法主要是復(fù)制源上的Symbols return isFlat ? copySymbolsIn(value, copyObject(value, keysIn(value), result)) : copySymbols(value, Object.assign(result, value)) } } else { // 如果是func或error, WeakMap就直接返回了 if (isFunc || !cloneableTags[tag]) { return object ? value : {} } // 對(duì)tag位true的類型進(jìn)行clone result = initCloneByTag(value, tag, isDeep) } } // Check for circular references and return its corresponding clone. // 檢查循環(huán)引用并返回其相應(yīng)的克隆。 stack || (stack = new Stack) const stacked = stack.get(value) if (stacked) { return stacked } stack.set(value, result) // 對(duì)map遞歸clone if (tag == mapTag) { value.forEach((subValue, key) => { result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack)) }) return result } // 對(duì)set遞歸調(diào)用 if (tag == setTag) { value.forEach((subValue) => { result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack)) }) return result } // 是否是TypedArray類型 if (isTypedArray(value)) { return result } const keysFunc = isFull ? (isFlat ? getAllKeysIn : getAllKeys) : (isFlat ? keysIn : keys) const props = isArr ? undefined : keysFunc(value) arrayEach(props || value, (subValue, key) => { if (props) { key = subValue subValue = value[key] } // Recursively populate clone (susceptible to call stack limits). assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack)) }) return result }
數(shù)組這里主要是會(huì)有個(gè)exec的特殊數(shù)組
function initCloneArray(array) { const { length } = array const result = new array.constructor(length) // Add properties assigned by `RegExp#exec`. // RegExp.exec返回的特殊數(shù)組 if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) { result.index = array.index result.input = array.input } return result }其他方法
Underscore庫(kù)或JSON.parse等
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/110196.html
摘要:中使用操作符具體做了哪些事情創(chuàng)建了一個(gè)空對(duì)象空對(duì)象的屬性指向構(gòu)造函數(shù)的屬性執(zhí)行構(gòu)造函數(shù),將的指向前端面試題及答案瀏覽器篇前端面試題及答案篇前端面試題及答案篇前端面試題及答案性能優(yōu)化篇 這篇文章并不是最全的前端面試題(沒(méi)有最全,只有更全),只是針對(duì)自己面試過(guò)程中遇到的一些難題、容易忽略的題做一個(gè)簡(jiǎn)單的筆記,方便后面有面試需要的小伙伴們借鑒,后續(xù)內(nèi)容會(huì)不定時(shí)更新,有錯(cuò)誤之處希望大家不吝指出...
摘要:它將返回目標(biāo)對(duì)象。有些文章說(shuō)是深拷貝,其實(shí)這是不正確的。深拷貝相比于淺拷貝速度較慢并且花銷較大。拷貝前后兩個(gè)對(duì)象互不影響。使用深拷貝的場(chǎng)景完全改變變量之后對(duì)沒(méi)有任何影響,這就是深拷貝的魔力。 一、賦值(Copy) 賦值是將某一數(shù)值或?qū)ο筚x給某個(gè)變量的過(guò)程,分為: 1、基本數(shù)據(jù)類型:賦值,賦值之后兩個(gè)變量互不影響 2、引用數(shù)據(jù)類型:賦址,兩個(gè)變量具有相同的引用,指向同一個(gè)對(duì)象,相互之間有...
摘要:深拷貝是一件看起來(lái)很簡(jiǎn)單的事情,但其實(shí)一點(diǎn)兒也不簡(jiǎn)單。我們也可以利用這個(gè)實(shí)現(xiàn)對(duì)象的深拷貝。而是利用之前已經(jīng)拷貝好的值。深拷貝的詳細(xì)的源碼可以在這里查看。大功告成我們雖然的確解決了深拷貝的大部分問(wèn)題。 js深拷貝是一件看起來(lái)很簡(jiǎn)單的事情,但其實(shí)一點(diǎn)兒也不簡(jiǎn)單。對(duì)于循環(huán)引用的問(wèn)題還有一些內(nèi)置數(shù)據(jù)類型的拷貝,如Map, Set, RegExp, Date, ArrayBuffer 和其他內(nèi)置...
摘要:總結(jié)綜上所述,數(shù)組的深拷貝比較簡(jiǎn)單,方法沒(méi)有什么爭(zhēng)議,對(duì)象的深拷貝,比較好的方法是用的方法實(shí)現(xiàn),或者遞歸實(shí)現(xiàn),比較簡(jiǎn)單的深復(fù)制可以使用實(shí)現(xiàn)參考資料知乎中的深拷貝和淺拷貝深入剖析的深復(fù)制 深淺復(fù)制對(duì)比 因?yàn)镴avaScript存儲(chǔ)對(duì)象都是存地址的,所以淺復(fù)制會(huì)導(dǎo)致 obj 和obj1 指向同一塊內(nèi)存地址。我的理解是,這有點(diǎn)類似數(shù)據(jù)雙向綁定,改變了其中一方的內(nèi)容,都是在原來(lái)的內(nèi)存基礎(chǔ)上做...
閱讀 3160·2023-04-26 02:33
閱讀 3116·2023-04-25 21:33
閱讀 915·2021-09-02 09:56
閱讀 2936·2019-08-30 15:44
閱讀 2466·2019-08-30 13:15
閱讀 1044·2019-08-30 13:04
閱讀 1644·2019-08-29 15:09
閱讀 3977·2019-08-26 18:26