成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

深拷貝的終極探索(99%的人都不知道)

qingshanli1988 / 2021人閱讀

摘要:劃重點(diǎn),這是一道面試必考題,我靠這道題刷掉了多少面試者嘿嘿首先這是一道非常棒的面試題,可以考察面試者的很多方面,比如基本功,代碼能力,邏輯能力,而且進(jìn)可攻,退可守,針對(duì)不同級(jí)別的人可以考察不同難度,比如漂亮妹子就出題,要是個(gè)帥哥那就得上了,

劃重點(diǎn),這是一道面試必考題,我靠這道題刷掉了多少面試者?(? ? ??)嘿嘿

首先這是一道非常棒的面試題,可以考察面試者的很多方面,比如基本功,代碼能力,邏輯能力,而且進(jìn)可攻,退可守,針對(duì)不同級(jí)別的人可以考察不同難度,比如漂亮妹子就出1☆題,要是個(gè)帥哥那就得上5☆了,(*^__^*) 嘻嘻……

無(wú)論面試者多么優(yōu)秀,漂亮的回答出問(wèn)題,我總能夠?yàn)t灑的再拋出一個(gè)問(wèn)題,看著面試者露出驚異的眼神,默默一轉(zhuǎn)身,深藏功與名

本文我將給大家破解深拷貝的謎題,由淺入深,環(huán)環(huán)相扣,總共涉及4種深拷貝方式,每種方式都有自己的特點(diǎn)和個(gè)性

深拷貝 VS 淺拷貝

再開(kāi)始之前需要先給同學(xué)科普下什么是深拷貝,和深拷貝有關(guān)系的另個(gè)一術(shù)語(yǔ)是淺拷貝又是什么意思呢?如果對(duì)這部分部分內(nèi)容了解的同學(xué)可以跳過(guò)

其實(shí)深拷貝和淺拷貝都是針對(duì)的引用類型,JS中的變量類型分為值類型(基本類型)和引用類型;對(duì)值類型進(jìn)行復(fù)制操作會(huì)對(duì)值進(jìn)行一份拷貝,而對(duì)引用類型賦值,則會(huì)進(jìn)行地址的拷貝,最終兩個(gè)變量指向同一份數(shù)據(jù)

// 基本類型
var a = 1;
var b = a;
a = 2;
console.log(a, b); // 2, 1 ,a b指向不同的數(shù)據(jù)

// 引用類型指向同一份數(shù)據(jù)
var a = {c: 1};
var b = a;
a.c = 2;
console.log(a.c, b.c); // 2, 2 全是2,a b指向同一份數(shù)據(jù)

對(duì)于引用類型,會(huì)導(dǎo)致a b指向同一份數(shù)據(jù),此時(shí)如果對(duì)其中一個(gè)進(jìn)行修改,就會(huì)影響到另外一個(gè),有時(shí)候這可能不是我們想要的結(jié)果,如果對(duì)這種現(xiàn)象不清楚的話,還可能造成不必要的bug

那么如何切斷a和b之間的關(guān)系呢,可以拷貝一份a的數(shù)據(jù),根據(jù)拷貝的層級(jí)不同可以分為淺拷貝和深拷貝,淺拷貝就是只進(jìn)行一層拷貝,深拷貝就是無(wú)限層級(jí)拷貝

var a1 = {b: {c: {}};

var a2 = shallowClone(a1); // 淺拷貝
a2.b.c === a1.b.c // true

var a3 = clone(a3); // 深拷貝
a3.b.c === a1.b.c // false

淺拷貝的實(shí)現(xiàn)非常簡(jiǎn)單,而且還有多種方法,其實(shí)就是遍歷對(duì)象屬性的問(wèn)題,這里只給出一種,如果看不懂下面的方法,或?qū)ζ渌椒ǜ信d趣,可以看我的這篇文章

function shallowClone(source) {
    var target = {};
    for(var i in source) {
        if (source.hasOwnProperty(i)) {
            target[i] = source[i];
        }
    }

    return target;
}
最簡(jiǎn)單的深拷貝

深拷貝的問(wèn)題其實(shí)可以分解成兩個(gè)問(wèn)題,淺拷貝+遞歸,什么意思呢?假設(shè)我們有如下數(shù)據(jù)

var a1 = {b: {c: {d: 1}};

只需稍加改動(dòng)上面淺拷貝的代碼即可,注意區(qū)別

function clone(source) {
    var target = {};
    for(var i in source) {
        if (source.hasOwnProperty(i)) {
            if (typeof source[i] === "object") {
                target[i] = clone(source[i]); // 注意這里
            } else {
                target[i] = source[i];
            }
        }
    }

    return target;
}

大部分人都能寫(xiě)出上面的代碼,但當(dāng)我問(wèn)上面的代碼有什么問(wèn)題嗎?就很少有人答得上來(lái)了,聰明的你能找到問(wèn)題嗎?

其實(shí)上面的代碼問(wèn)題太多了,先來(lái)舉幾個(gè)例子吧

沒(méi)有對(duì)參數(shù)做檢驗(yàn)

判斷是否對(duì)象的邏輯不夠嚴(yán)謹(jǐn)

沒(méi)有考慮數(shù)組的兼容

(⊙o⊙),下面我們來(lái)看看各個(gè)問(wèn)題的解決辦法,首先我們需要抽象一個(gè)判斷對(duì)象的方法,其實(shí)比較常用的判斷對(duì)象的方法如下,其實(shí)下面的方法也有問(wèn)題,但如果能夠回答上來(lái)那就非常不錯(cuò)了,如果完美的解決辦法感興趣,不妨看看這里吧

function isObject(x) {
    return Object.prototype.toString.call(x) === "[object Object]";
}

函數(shù)需要校驗(yàn)參數(shù),如果不是對(duì)象的話直接返回

function clone(source) {
    if (!isObject(source)) return source;

    // xxx
}

關(guān)于第三個(gè)問(wèn)題,嗯,就留給大家自己思考吧,本文為了減輕大家的負(fù)擔(dān),就不考慮數(shù)組的情況了,其實(shí)ES6之后還要考慮set, map, weakset, weakmap,/(ㄒoㄒ)/~~

其實(shí)吧這三個(gè)都是小問(wèn)題,其實(shí)遞歸方法最大的問(wèn)題在于爆棧,當(dāng)數(shù)據(jù)的層次很深是就會(huì)棧溢出

下面的代碼可以生成指定深度和每層廣度的代碼,這段代碼我們后面還會(huì)再次用到

function createData(deep, breadth) {
    var data = {};
    var temp = data;

    for (var i = 0; i < deep; i++) {
        temp = temp["data"] = {};
        for (var j = 0; j < breadth; j++) {
            temp[j] = j;
        }
    }

    return data;
}

createData(1, 3); // 1層深度,每層有3個(gè)數(shù)據(jù) {data: {0: 0, 1: 1, 2: 2}}
createData(3, 0); // 3層深度,每層有0個(gè)數(shù)據(jù) {data: {data: {data: {}}}}

當(dāng)clone層級(jí)很深的話就會(huì)棧溢出,但數(shù)據(jù)的廣度不會(huì)造成溢出

clone(createData(1000)); // ok
clone(createData(10000)); // Maximum call stack size exceeded

clone(createData(10, 100000)); // ok 廣度不會(huì)溢出

其實(shí)大部分情況下不會(huì)出現(xiàn)這么深層級(jí)的數(shù)據(jù),但這種方式還有一個(gè)致命的問(wèn)題,就是循環(huán)引用,舉個(gè)例子

var a = {};
a.a = a;

clone(a) // Maximum call stack size exceeded 直接死循環(huán)了有沒(méi)有,/(ㄒoㄒ)/~~

關(guān)于循環(huán)引用的問(wèn)題解決思路有兩種,一直是循環(huán)檢測(cè),一種是暴力破解,關(guān)于循環(huán)檢測(cè)大家可以自己思考下;關(guān)于暴力破解我們會(huì)在下面的內(nèi)容中詳細(xì)講解

一行代碼的深拷貝

有些同學(xué)可能見(jiàn)過(guò)用系統(tǒng)自帶的JSON來(lái)做深拷貝的例子,下面來(lái)看下代碼實(shí)現(xiàn)

function cloneJSON(source) {
    return JSON.parse(JSON.stringify(source));
}

其實(shí)我第一次簡(jiǎn)單這個(gè)方法的時(shí)候,由衷的表示佩服,其實(shí)利用工具,達(dá)到目的,是非常聰明的做法

下面來(lái)測(cè)試下cloneJSON有沒(méi)有溢出的問(wèn)題,看起來(lái)cloneJSON內(nèi)部也是使用遞歸的方式

cloneJSON(createData(10000)); // Maximum call stack size exceeded

既然是用了遞歸,那循環(huán)引用呢?并沒(méi)有因?yàn)樗姥h(huán)而導(dǎo)致棧溢出啊,原來(lái)是JSON.stringify內(nèi)部做了循環(huán)引用的檢測(cè),正是我們上面提到破解循環(huán)引用的第一種方法:循環(huán)檢測(cè)

var a = {};
a.a = a;

cloneJSON(a) // Uncaught TypeError: Converting circular structure to JSON
破解遞歸爆棧

其實(shí)破解遞歸爆棧的方法有兩條路,第一種是消除尾遞歸,但在這個(gè)例子中貌似行不通,第二種方法就是干脆不用遞歸,改用循環(huán),當(dāng)我提出用循環(huán)來(lái)實(shí)現(xiàn)時(shí),基本上90%的前端都是寫(xiě)不出來(lái)的代碼的,這其實(shí)讓我很震驚

舉個(gè)例子,假設(shè)有如下的數(shù)據(jù)結(jié)構(gòu)

var a = {
    a1: 1,
    a2: {
        b1: 1,
        b2: {
            c1: 1
        }
    }
}

這不就是一個(gè)樹(shù)嗎,其實(shí)只要把數(shù)據(jù)橫過(guò)來(lái)看就非常明顯了

    a
  /   
 a1   a2        
 |    /          
 1   b1 b2     
     |   |        
     1  c1
         |
         1       

用循環(huán)遍歷一棵樹(shù),需要借助一個(gè)棧,當(dāng)棧為空時(shí)就遍歷完了,棧里面存儲(chǔ)下一個(gè)需要拷貝的節(jié)點(diǎn)

首先我們往棧里放入種子數(shù)據(jù),key用來(lái)存儲(chǔ)放哪一個(gè)父元素的那一個(gè)子元素拷貝對(duì)象

然后遍歷當(dāng)前節(jié)點(diǎn)下的子元素,如果是對(duì)象就放到棧里,否則直接拷貝

function cloneLoop(x) {
    const root = {};

    // 棧
    const loopList = [
        {
            parent: root,
            key: undefined,
            data: x,
        }
    ];

    while(loopList.length) {
        // 深度優(yōu)先
        const node = loopList.pop();
        const parent = node.parent;
        const key = node.key;
        const data = node.data;

        // 初始化賦值目標(biāo),key為undefined則拷貝到父元素,否則拷貝到子元素
        let res = parent;
        if (typeof key !== "undefined") {
            res = parent[key] = {};
        }

        for(let k in data) {
            if (data.hasOwnProperty(k)) {
                if (typeof data[k] === "object") {
                    // 下一次循環(huán)
                    loopList.push({
                        parent: res,
                        key: k,
                        data: data[k],
                    });
                } else {
                    res[k] = data[k];
                }
            }
        }
    }

    return root;
}

改用循環(huán)后,再也不會(huì)出現(xiàn)爆棧的問(wèn)題了,但是對(duì)于循環(huán)引用依然無(wú)力應(yīng)對(duì)

破解循環(huán)引用

有沒(méi)有一種辦法可以破解循環(huán)應(yīng)用呢?別著急,我們先來(lái)看另一個(gè)問(wèn)題,上面的三種方法都存在的一個(gè)問(wèn)題就是引用丟失,這在某些情況下也許是不能接受的

舉個(gè)例子,假如一個(gè)對(duì)象a,a下面的兩個(gè)鍵值都引用同一個(gè)對(duì)象b,經(jīng)過(guò)深拷貝后,a的兩個(gè)鍵值會(huì)丟失引用關(guān)系,從而變成兩個(gè)不同的對(duì)象,o(╯□╰)o

var b = 1;
var a = {a1: b, a2: b};

a.a1 === a.a2 // true

var c = clone(a);
c.a1 === c.a2 // false

如果我們發(fā)現(xiàn)個(gè)新對(duì)象就把這個(gè)對(duì)象和他的拷貝存下來(lái),每次拷貝對(duì)象前,都先看一下這個(gè)對(duì)象是不是已經(jīng)拷貝過(guò)了,如果拷貝過(guò)了,就不需要拷貝了,直接用原來(lái)的,這樣我們就能夠保留引用關(guān)系了,?(? ? ??)嘿嘿

但是代碼怎么寫(xiě)呢,o(╯□╰)o,別急往下看,其實(shí)和循環(huán)的代碼大體一樣,不一樣的地方我用// ==========標(biāo)注出來(lái)了

引入一個(gè)數(shù)組uniqueList用來(lái)存儲(chǔ)已經(jīng)拷貝的數(shù)組,每次循環(huán)遍歷時(shí),先判斷對(duì)象是否在uniqueList中了,如果在的話就不執(zhí)行拷貝邏輯了

find是抽象的一個(gè)函數(shù),其實(shí)就是遍歷uniqueList

// 保持引用關(guān)系
function cloneForce(x) {
    // =============
    const uniqueList = []; // 用來(lái)去重
    // =============

    let root = {};

    // 循環(huán)數(shù)組
    const loopList = [
        {
            parent: root,
            key: undefined,
            data: x,
        }
    ];

    while(loopList.length) {
        // 深度優(yōu)先
        const node = loopList.pop();
        const parent = node.parent;
        const key = node.key;
        const data = node.data;

        // 初始化賦值目標(biāo),key為undefined則拷貝到父元素,否則拷貝到子元素
        let res = parent;
        if (typeof key !== "undefined") {
            res = parent[key] = {};
        }
        
        // =============
        // 數(shù)據(jù)已經(jīng)存在
        let uniqueData = find(uniqueList, data);
        if (uniqueData) {
            parent[key] = uniqueData.target;
            break; // 中斷本次循環(huán)
        }

        // 數(shù)據(jù)不存在
        // 保存源數(shù)據(jù),在拷貝數(shù)據(jù)中對(duì)應(yīng)的引用
        uniqueList.push({
            source: data,
            target: res,
        });
        // =============
    
        for(let k in data) {
            if (data.hasOwnProperty(k)) {
                if (typeof data[k] === "object") {
                    // 下一次循環(huán)
                    loopList.push({
                        parent: res,
                        key: k,
                        data: data[k],
                    });
                } else {
                    res[k] = data[k];
                }
            }
        }
    }

    return root;
}

function find(arr, item) {
    for(let i = 0; i < arr.length; i++) {
        if (arr[i].source === item) {
            return arr[i];
        }
    }

    return null;
}

下面來(lái)驗(yàn)證一下效果,amazing

var b = 1;
var a = {a1: b, a2: b};

a.a1 === a.a2 // true

var c = cloneForce(a);
c.a1 === c.a2 // true

接下來(lái)再說(shuō)一下如何破解循環(huán)引用,等一下,上面的代碼好像可以破解循環(huán)引用啊,趕緊驗(yàn)證一下

驚不驚喜,(*^__^*) 嘻嘻……

var a = {};
a.a = a;

cloneForce(a)

看起來(lái)完美的cloneForce是不是就沒(méi)問(wèn)題呢?cloneForce有兩個(gè)問(wèn)題

第一個(gè)問(wèn)題,所謂成也蕭何,敗也蕭何,如果保持引用不是你想要的,那就不能用cloneForce了;

第二個(gè)問(wèn)題,cloneForce在對(duì)象數(shù)量很多時(shí)會(huì)出現(xiàn)很大的問(wèn)題,如果數(shù)據(jù)量很大不適合使用cloneForce

性能對(duì)比

上邊的內(nèi)容還是有點(diǎn)難度,下面我們來(lái)點(diǎn)更有難度的,對(duì)比一下不同方法的性能

我們先來(lái)做實(shí)驗(yàn),看數(shù)據(jù),影響性能的原因有兩個(gè),一個(gè)是深度,一個(gè)是每層的廣度,我們采用固定一個(gè)變量,只讓一個(gè)變量變化的方式來(lái)測(cè)試性能

測(cè)試的方法是在指定的時(shí)間內(nèi),深拷貝執(zhí)行的次數(shù),次數(shù)越多,證明性能越好

下面的runTime是測(cè)試代碼的核心片段,下面的例子中,我們可以測(cè)試在2秒內(nèi)運(yùn)行clone(createData(500, 1)的次數(shù)

function runTime(fn, time) {
    var stime = Date.now();
    var count = 0;
    while(Date.now() - stime < time) {
        fn();
        count++;
    }

    return count;
}

runTime(function () { clone(createData(500, 1)) }, 2000);

下面來(lái)做第一個(gè)測(cè)試,將廣度固定在100,深度由小到大變化,記錄1秒內(nèi)執(zhí)行的次數(shù)

深度 clone cloneJSON cloneLoop cloneForce
500 351 212 338 372
1000 174 104 175 143
1500 116 67 112 82
2000 92 50 88 69

將上面的數(shù)據(jù)做成表格可以發(fā)現(xiàn),一些規(guī)律

隨著深度變小,相互之間的差異在變小

clone和cloneLoop的差別并不大

cloneLoop > cloneForce > cloneJSON

我們先來(lái)分析下各個(gè)方法的時(shí)間復(fù)雜度問(wèn)題,各個(gè)方法要做的相同事情,這里就不計(jì)算,比如循環(huán)對(duì)象,判斷是否為對(duì)象

clone時(shí)間 = 創(chuàng)建遞歸函數(shù) + 每個(gè)對(duì)象處理時(shí)間

cloneJSON時(shí)間 = 循環(huán)檢測(cè) + 每個(gè)對(duì)象處理時(shí)間 * 2 (遞歸轉(zhuǎn)字符串 + 遞歸解析)

cloneLoop時(shí)間 = 每個(gè)對(duì)象處理時(shí)間

cloneForce時(shí)間 = 判斷對(duì)象是否緩存中 + 每個(gè)對(duì)象處理時(shí)間

cloneJSON的速度只有clone的50%,很容易理解,因?yàn)槠鋾?huì)多進(jìn)行一次遞歸時(shí)間

cloneForce由于要判斷對(duì)象是否在緩存中,而導(dǎo)致速度變慢,我們來(lái)計(jì)算下判斷邏輯的時(shí)間復(fù)雜度,假設(shè)對(duì)象的個(gè)數(shù)是n,則其時(shí)間復(fù)雜度為O(n2),對(duì)象的個(gè)數(shù)越多,cloneForce的速度會(huì)越慢

1 + 2 + 3 ... + n = n^2/2 - 1

關(guān)于clone和cloneLoop這里有一點(diǎn)問(wèn)題,看起來(lái)實(shí)驗(yàn)結(jié)果和推理結(jié)果不一致,其中必有蹊蹺

接下來(lái)做第二個(gè)測(cè)試,將深度固定在10000,廣度固定為0,記錄2秒內(nèi)執(zhí)行的次數(shù)

寬度 clone cloneJSON cloneLoop cloneForce
0 13400 3272 14292 989

排除寬度的干擾,來(lái)看看深度對(duì)各個(gè)方法的影響

隨著對(duì)象的增多,cloneForce的性能低下凸顯

cloneJSON的性能也大打折扣,這是因?yàn)檠h(huán)檢測(cè)占用了很多時(shí)間

cloneLoop的性能高于clone,可以看出遞歸新建函數(shù)的時(shí)間和循環(huán)對(duì)象比起來(lái)可以忽略不計(jì)

下面我們來(lái)測(cè)試一下cloneForce的性能極限,這次我們測(cè)試運(yùn)行指定次數(shù)需要的時(shí)間

var data1 = createData(2000, 0);
var data2 = createData(4000, 0);
var data3 = createData(6000, 0);
var data4 = createData(8000, 0);
var data5 = createData(10000, 0);

cloneForce(data1)
cloneForce(data2)
cloneForce(data3)
cloneForce(data4)
cloneForce(data5)

通過(guò)測(cè)試發(fā)現(xiàn),其時(shí)間成指數(shù)級(jí)增長(zhǎng),當(dāng)對(duì)象個(gè)數(shù)大于萬(wàn)級(jí)別,就會(huì)有300ms以上的延遲

總結(jié)

尺有所短寸有所長(zhǎng),無(wú)關(guān)乎好壞優(yōu)劣,其實(shí)每種方法都有自己的優(yōu)缺點(diǎn),和適用場(chǎng)景,人盡其才,物盡其用,方是真理

下面對(duì)各種方法進(jìn)行對(duì)比,希望給大家提供一些幫助

clone cloneJSON cloneLoop cloneForce
難度 ☆☆ ☆☆☆ ☆☆☆☆
兼容性 ie6 ie8 ie6 ie6
循環(huán)引用 一層 不支持 一層 支持
棧溢出 會(huì) 會(huì) 不會(huì) 不會(huì)
保持引用
適合場(chǎng)景 一般數(shù)據(jù)拷貝 一般數(shù)據(jù)拷貝 層級(jí)很多 保持引用關(guān)系

本文的靈感都來(lái)自于@jsmini/clone,如果大家想使用文中的4種深拷貝方式,可以直接使用@jsmini/clone這個(gè)庫(kù)

// npm install --save @jsmini/clone
import { clone, cloneJSON, cloneLoop, cloneForce } from "@jsmini/clone";

本文為了簡(jiǎn)單和易讀,示例代碼中忽略了一些邊界情況,如果想學(xué)習(xí)生產(chǎn)中的代碼,請(qǐng)閱讀@jsmini/clone的源碼

@jsmini/clone孵化于jsmini,jsmini致力于為大家提供一組小而美,無(wú)依賴的高質(zhì)量庫(kù)

jsmini的誕生離不開(kāi)jslib-base,感謝jslib-base為jsmini提供了底層技術(shù)

感謝你閱讀了本文,相信現(xiàn)在你能夠駕馭任何深拷貝的問(wèn)題了,如果有什么疑問(wèn),歡迎和我討論

最后推薦下我的新書(shū)《React狀態(tài)管理與同構(gòu)實(shí)戰(zhàn)》,深入解讀前沿同構(gòu)技術(shù),感謝大家支持

京東:https://item.jd.com/12403508.html

當(dāng)當(dāng):http://product.dangdang.com/25308679.html

最后最后招聘前端,后端,客戶端啦!地點(diǎn):北京+上海+成都,感興趣的同學(xué),可以把簡(jiǎn)歷發(fā)到我的郵箱: [email protected]

原文網(wǎng)址:http://yanhaijing.com/javascr...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/98326.html

相關(guān)文章

  • 【進(jìn)階4-3期】面試題之如何實(shí)現(xiàn)一個(gè)拷貝

    摘要:今天這篇文章我們來(lái)看看一道必會(huì)面試題,即如何實(shí)現(xiàn)一個(gè)深拷貝。木易楊注意這里使用上面測(cè)試用例測(cè)試一下一個(gè)簡(jiǎn)單的深拷貝就完成了,但是這個(gè)實(shí)現(xiàn)還存在很多問(wèn)題。 引言 上篇文章詳細(xì)介紹了淺拷貝 Object.assign,并對(duì)其進(jìn)行了模擬實(shí)現(xiàn),在實(shí)現(xiàn)的過(guò)程中,介紹了很多基礎(chǔ)知識(shí)。今天這篇文章我們來(lái)看看一道必會(huì)面試題,即如何實(shí)現(xiàn)一個(gè)深拷貝。本文會(huì)詳細(xì)介紹對(duì)象、數(shù)組、循環(huán)引用、引用丟失、Symbo...

    longmon 評(píng)論0 收藏0
  • 關(guān)于JSON.parse()和JSON.stringify()性能小測(cè)試

    摘要:我們一般用來(lái)深拷貝,其過(guò)程說(shuō)白了,就是利用將對(duì)象序列化字符串,再使用來(lái)反序列化還原對(duì)象。至于這行代碼為什么能實(shí)現(xiàn)深拷貝,以及它有什么局限性等等,不是本文要介紹的。小結(jié)論能不用和就不用,采用替代方案且性能更優(yōu)的。 JSON.parse(JSON.stringify(obj))我們一般用來(lái)深拷貝,其過(guò)程說(shuō)白了,就是利用 JSON.stringify 將js對(duì)象序列化(JSON字符串),再使...

    oogh 評(píng)論0 收藏0
  • 拷貝拷貝

    摘要:二淺拷貝與深拷貝深拷貝和淺拷貝是只針對(duì)和這樣的引用數(shù)據(jù)類型的。淺拷貝是按位拷貝對(duì)象,它會(huì)創(chuàng)建一個(gè)新對(duì)象,這個(gè)對(duì)象有著原始對(duì)象屬性值的一份精確拷貝。對(duì)于字符串?dāng)?shù)字及布爾值來(lái)說(shuō)不是或者對(duì)象,會(huì)拷貝這些值到新的數(shù)組里。 一、數(shù)據(jù)類型 數(shù)據(jù)分為基本數(shù)據(jù)類型(String, Number, Boolean, Null, Undefined,Symbol)和對(duì)象數(shù)據(jù)類型。 基本數(shù)據(jù)類型的特點(diǎn):直...

    hzc 評(píng)論0 收藏0
  • 拷貝拷貝

    摘要:二淺拷貝與深拷貝深拷貝和淺拷貝是只針對(duì)和這樣的引用數(shù)據(jù)類型的。淺拷貝是按位拷貝對(duì)象,它會(huì)創(chuàng)建一個(gè)新對(duì)象,這個(gè)對(duì)象有著原始對(duì)象屬性值的一份精確拷貝。對(duì)于字符串?dāng)?shù)字及布爾值來(lái)說(shuō)不是或者對(duì)象,會(huì)拷貝這些值到新的數(shù)組里。 一、數(shù)據(jù)類型 數(shù)據(jù)分為基本數(shù)據(jù)類型(String, Number, Boolean, Null, Undefined,Symbol)和對(duì)象數(shù)據(jù)類型。 基本數(shù)據(jù)類型的特點(diǎn):直...

    史占廣 評(píng)論0 收藏0
  • 「前端面試題系列9」淺拷貝拷貝含義、區(qū)別及實(shí)現(xiàn)(文末有崗位內(nèi)推哦~)

    摘要:深拷貝與淺拷貝的出現(xiàn),就與這兩個(gè)數(shù)據(jù)類型有關(guān)。這時(shí),就需要用淺拷貝來(lái)實(shí)現(xiàn)了。數(shù)據(jù)一但過(guò)多,就會(huì)有遞歸爆棧的風(fēng)險(xiǎn)。這個(gè)方法是在解決遞歸爆棧問(wèn)題的基礎(chǔ)上,加以改進(jìn)解決循環(huán)引用的問(wèn)題。但如果你并不想保持引用,那就改用用于解決遞歸爆棧即可。 前言 這是前端面試題系列的第 9 篇,你可能錯(cuò)過(guò)了前面的篇章,可以在這里找到: 數(shù)組去重(10 種濃縮版) JavaScript 中的事件機(jī)制(從原生到...

    caige 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<