JS每日一題:深拷貝與淺拷貝的區別?如何實現一個深拷貝

20190311期

深拷貝與淺拷貝的區別?如何實現一個深拷貝jquery

在回答這個問題前,咱們先來回顧一下JS中兩大數據類型git

  • 基本類型 Undefined、Null、Boolean、Number、String
  • 引用類型 Object Array
基本類型

基本類型就是值類型, 存放在棧(stack)內存中的簡單數據段,數據大小肯定,內存空間大小能夠分配github

引用類型

引用類型, 存放在堆(heap)內存中的對象,變量實際保存的是一個指針,這個指針指向另外一個位置函數

根據上面的分析,咱們分別是兩處類型作一個copy處理oop

let obj = {
    name: '每日一題',
    value: 'JS'
}

let obj2 = obj
let obj3 = obj.name

console.log(obj2.value) //JS
console.log(obj3) // 每日一題

// 改變obj2,obj3
obj2.value = 'CSS'
obj3 = 'HTML'

console.log(obj.value) // CSS
console.log(obj.name) // 每日一題

從上面的輸出結束來看,咱們能夠猜想obj,obj2操做的是同一個對象,而obj和obj3是徹底獨立的, 說到這裏就進入了深淺拷貝學習

淺拷貝

概念: 對於字符串類型,淺拷貝是對值的複製,對於對象來講,淺拷貝是對對象地址的複製, 也就是拷貝的結果是兩個對象指向同一個地址

基本概念回過頭去看上面的代碼咱們就能分析出來其都是淺複製大數據

深拷貝

概念: 深拷貝開闢一個新的棧,兩個對象對應兩個不一樣的地址,修改一個對象的屬性,不會改變另外一個對象的屬性

如何實現深拷貝

JSON.stringify()

首先安利一個無腦黑科技騷操做
* 缺點: JSON.stringify()沒法正確處理函數翻譯

let obj = {
    name: '每日一題',
    value: 'JS'
}
console.log(JSON.parse(JSON.stringify(obj))) // 深拷貝了一份obj

let obj = {
    name: '每日一題',
    value: 'JS',
    fn: function(){}
}
console.log(JSON.parse(JSON.stringify(obj))) // obj.fn 丟失
遞歸

講到深copy不少人都會想到extend方法,沒錯,這玩意deep爲true確實能深copy,咱們就過來翻一翻他的源碼指針

這邊以你們熟悉的jquery爲例code

// 源碼地址 https://github.com/jquery/jquery/blob/5bdc85b82b84e5459462ddad9002f22d1ce74f21/src/core.js#L125

// 只取核心邏輯代碼,感興趣的能夠自行去源碼地址查看具體實現
// 有英文註釋,我就不蹩腳翻譯了
// 總體思路就是遞歸對象,判斷類型,處理類型
    for ( ; i < length; i++ ) {

        // Only deal with non-null/undefined values
        if ( ( options = arguments[ i ] ) != null ) {

            // Extend the base object
            for ( name in options ) {
                copy = options[ name ];

                // Prevent never-ending loop
                if ( target === copy ) {
                    continue;
                }

                // Recurse if we're merging plain objects or arrays
                if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
                    ( copyIsArray = Array.isArray( copy ) ) ) ) {
                    src = target[ name ];

                    // Ensure proper type for the source value
                    if ( copyIsArray && !Array.isArray( src ) ) {
                        clone = [];
                    } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {
                        clone = {};
                    } else {
                        clone = src;
                    }
                    copyIsArray = false;

                    // Never move original objects, clone them
                    target[ name ] = jQuery.extend( deep, clone, copy );

                // Don't bring in undefined values
                } else if ( copy !== undefined ) {
                    target[ name ] = copy;
                }
            }
        }
    }

總結

  • 淺拷貝是複製,兩個對象指向同一個地址
  • 深拷貝是新開棧,兩個對象指向不一樣的地址

關於JS每日一題

JS每日一題能夠當作是一個語音答題社區
天天利用碎片時間採用60秒內的語音形式來完成當天的考題
羣主在第二天0點推送當天的參考答案

  • 注 毫不僅限於完成當天任務,更可能是查漏補缺,學習羣內其它同窗優秀的答題思路

點擊加入答題

相關文章
相關標籤/搜索