欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳細(xì)聊聊JS中不一樣的深拷貝

 更新時(shí)間:2022年10月16日 09:14:36   作者:當(dāng)然是黑貓警長(zhǎng)啦  
對(duì)于js中的對(duì)象的深拷貝在項(xiàng)目的開(kāi)發(fā)中比較常用到,這篇文章主要給大家介紹了關(guān)于JS中不一樣的深拷貝的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

對(duì)于深拷貝這個(gè)概念在面試中時(shí)常被提起,面試官可能讓你實(shí)現(xiàn)深拷貝需要考慮那些因素,或者直接讓你手寫(xiě)封裝一個(gè)深拷貝,那么今天就和大家探討一下一個(gè)讓面試官感到牛的深拷貝,

1.思考

眾所周知普通的數(shù)據(jù)類(lèi)型是值存儲(chǔ),而復(fù)雜類(lèi)型是通過(guò)開(kāi)辟內(nèi)存空間來(lái)存儲(chǔ)數(shù)據(jù)的,我們通過(guò)內(nèi)存地址從而查找數(shù)據(jù),為了可以完全得到一個(gè)與原對(duì)象一模一樣但又沒(méi)有內(nèi)存地址關(guān)聯(lián)的深拷貝,我們需要考慮的因素其實(shí)有很多, 1.Object.create()創(chuàng)造的對(duì)象 , Object.create()詳細(xì)介紹

  let obj = Object.create(null)
            obj.name = '張三'
            obj.age = 22

這個(gè)對(duì)象是一個(gè)沒(méi)有原型的對(duì)象,大部分對(duì)象都有自己的原型,可以使用公共的方法,但這個(gè)卻不行,我們是不是應(yīng)該把它考慮進(jìn)去?

2.symbol作為屬性名的情況 Symbol詳細(xì)介紹 以及 for in 詳細(xì)介紹

let obj = {
            name: 'aa',
            age: 22,
            [Symbol('a')]: '獨(dú)一無(wú)二的'
            }

對(duì)于帶有symbol的屬性,在 for in 的迭代中是不可枚舉的,我們是不是需要考慮如何解決?

3.對(duì)于修改對(duì)象的屬性描述 Object.defineProperty()

let obj = { name: 'ayu', age: 22, sex: '男' }
Object.defineProperty(obj, 'age', {
    enumerable: true,
    configurable: true,
    value: 22,
    writable: false
})

這里我們改寫(xiě)了原對(duì)象的屬性描述,age變得無(wú)法枚舉,for in 也失去效果,并且很多默認(rèn)的屬性描述信息,我們是不是在拷貝后也應(yīng)該和原對(duì)象保持一致?

4.對(duì)象的循環(huán)引用

let obj = { name: 'ayu', age: 22, sex: '男' }
obj.e = e

obj對(duì)象中有個(gè)e的屬性指向obj,造成相互引用,當(dāng)我們?cè)诜庋b深拷貝時(shí),主要是通過(guò)遞歸來(lái)逐層查找屬性值的情況,然后對(duì)其進(jìn)行操作,如果出現(xiàn)這個(gè)情況,就會(huì)死循環(huán)遞歸造成棧內(nèi)存溢出,這種情況難道也不值得考慮嘛?

5.一些特殊的對(duì)象 都說(shuō)萬(wàn)物皆對(duì)象,對(duì)象其實(shí)有很多類(lèi)型,正則,日期(Date),等都需要特殊處理 而函數(shù)和數(shù)組就比較簡(jiǎn)單

6.深拷貝的多數(shù)要點(diǎn) 也就是當(dāng)一個(gè)對(duì)象里面嵌套了多層對(duì)象,這個(gè)大家應(yīng)該都知道,我們通常一般使用遞歸去處理,再結(jié)合上面分析的因素就可以封裝函數(shù)了

const isComplexDataType = (obj) => (typeof obj === 'object' || typeof obj === 'function') && obj !== null
const deepClone = function (obj, hash = new WeakMap()) {
    if (obj.constructor === Date) return new Date(obj) // 日期對(duì)象直接返回一個(gè)新的日期對(duì)象
    if (obj.constructor === RegExp) return new RegExp(obj) //正則對(duì)象直接返回一個(gè)新的正則對(duì)象
    //如果循環(huán)引用了就用 weakMap 來(lái)解決
    if (hash.has(obj)) return hash.get(obj)
    let allDesc = Object.getOwnPropertyDescriptors(obj)
    //遍歷傳入?yún)?shù)所有鍵的特性
    let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc)
    //繼承原型鏈
    hash.set(obj, cloneObj)
    for (let key of Reflect.ownKeys(obj)) {
        cloneObj[key] =
            isComplexDataType(obj[key]) && typeof obj[key] !== 'function' ? deepClone(obj[key], hash) : obj[key]
    }
    return cloneObj
}

思路 從deepclone這個(gè)函數(shù)開(kāi)始說(shuō)起

  • 1.如果對(duì)象的構(gòu)造器是Date構(gòu)造器,則我們使用Dte構(gòu)造器再構(gòu)造一個(gè)Date
  • 如果對(duì)象的構(gòu)造器是正則構(gòu)造器再構(gòu)造一個(gè)正則
  • WeakMap我們先不提,allDesc是拿到原對(duì)象所有的屬性(可枚舉以及不可枚舉)以及對(duì)應(yīng)的屬性描述信息
  • cloneObj是我們根據(jù)第三步拷貝的一個(gè)新的對(duì)象的信息,不過(guò)是一個(gè)淺拷貝,而且我們考慮了原型不存在的情況 Object.assin與Object.create的區(qū)別
  • 通過(guò)for of 循環(huán) Reflect.ownKeys(obj) Reflect.ownKeys()用法 (Reflect.ownKeys()可以遍歷對(duì)象自身所有的屬性(symbol,不可枚舉都可以),然后重新將obj的key以及對(duì)應(yīng)的值賦值給cloneObj,并且對(duì)obj[key]的值做了討論,當(dāng)它是對(duì)象并且不是函數(shù)時(shí),我們遞歸處理,否則里面為普通值,直接賦給ObjClone

對(duì)于deepClone的第二個(gè)參數(shù)WeakMap來(lái)講, 請(qǐng)大家想想最開(kāi)始我們提到的一個(gè)問(wèn)題,我們有一個(gè)對(duì)象,然后我們填了了一個(gè)屬性,屬性為這個(gè)對(duì)象,這是在相互引用,如果我們處理這樣的對(duì)象,也使用遞歸處理,那么就是死循環(huán),因此我們需要一個(gè)數(shù)據(jù)結(jié)構(gòu)來(lái)解決,每次我們遞歸處理的時(shí)候,都把obj,以及賦值的cloneobj對(duì)應(yīng)存儲(chǔ),當(dāng)遇到死循環(huán)的時(shí)候直接return這個(gè)對(duì)象即可 WeakMap詳細(xì)介紹·

(本文用到大量ES5以后的API,推薦閱讀阮一峰老師的ES6,這樣才能理解的透徹)

總結(jié)

到此這篇關(guān)于JS中不一樣的深拷貝的文章就介紹到這了,更多相關(guān)JS深拷貝內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JS實(shí)現(xiàn)簡(jiǎn)易換圖時(shí)鐘功能分析

    JS實(shí)現(xiàn)簡(jiǎn)易換圖時(shí)鐘功能分析

    這篇文章主要介紹了JS實(shí)現(xiàn)簡(jiǎn)易換圖時(shí)鐘功能,結(jié)合實(shí)例形式分析了javascript結(jié)合時(shí)間函數(shù)定時(shí)變換顯示圖片實(shí)現(xiàn)時(shí)鐘功能的相關(guān)操作技巧,代碼中備有較為詳盡的注釋便于理解,需要的朋友可以參考下
    2018-01-01
  • BootStrap輪播HTML代碼(推薦)

    BootStrap輪播HTML代碼(推薦)

    本文給大家分享bootstrap輪播h tml代碼,代碼簡(jiǎn)單易懂非常不錯(cuò),具有參考借鑒,需要的朋友參考下吧
    2016-12-12
  • javascript下查找父節(jié)點(diǎn)的簡(jiǎn)單方法

    javascript下查找父節(jié)點(diǎn)的簡(jiǎn)單方法

    javascript下查找父節(jié)點(diǎn)的簡(jiǎn)單方法...
    2007-08-08
  • 利用Three.js如何實(shí)現(xiàn)陰影效果實(shí)例代碼

    利用Three.js如何實(shí)現(xiàn)陰影效果實(shí)例代碼

    使用three.js可以方便的讓我們?cè)诰W(wǎng)頁(yè)中做出各種不同的3D效果,下面這篇文章主要給大家介紹了關(guān)于利用Three.js如何實(shí)現(xiàn)陰影效果的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-09-09
  • JavaScript之RegExp_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    JavaScript之RegExp_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    正則表達(dá)式是一種用來(lái)匹配字符串的強(qiáng)有力的武器。它的設(shè)計(jì)思想是用一種描述性的語(yǔ)言來(lái)給字符串定義一個(gè)規(guī)則,凡是符合規(guī)則的字符串,我們就認(rèn)為它“匹配”了,否則,該字符串就是不合法的
    2017-06-06
  • 旺旺在線客服代碼 旺旺客服代碼生成器

    旺旺在線客服代碼 旺旺客服代碼生成器

    很多朋友想在網(wǎng)站上插入自己的阿里旺旺在線聯(lián)系圖片,就像是和QQ一樣,小編為大家詳細(xì)講解了旺旺在線客服代碼以及旺旺客服代碼生成器,希望能夠幫助到大家。
    2018-01-01
  • 微信小程序?qū)崿F(xiàn)錨點(diǎn)跳轉(zhuǎn)

    微信小程序?qū)崿F(xiàn)錨點(diǎn)跳轉(zhuǎn)

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)錨點(diǎn)跳轉(zhuǎn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • JavaScript無(wú)縫滾動(dòng)效果的實(shí)例代碼

    JavaScript無(wú)縫滾動(dòng)效果的實(shí)例代碼

    本文給大家分享一段實(shí)例代碼有關(guān)js實(shí)現(xiàn)無(wú)縫滾動(dòng)效果,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下
    2017-03-03
  • js點(diǎn)擊事件鏈接的問(wèn)題解決

    js點(diǎn)擊事件鏈接的問(wèn)題解決

    這篇文章主要介紹了js點(diǎn)擊事件鏈接的問(wèn)題解決方法,需要的朋友可以參考下
    2014-04-04
  • 詳解處理bootstrap4不支持遠(yuǎn)程靜態(tài)框問(wèn)題

    詳解處理bootstrap4不支持遠(yuǎn)程靜態(tài)框問(wèn)題

    這篇文章主要介紹了詳解處理bootstrap4不支持遠(yuǎn)程靜態(tài)框問(wèn)題,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07

最新評(píng)論