js實現深拷貝(深度克隆)


淺克隆(淺拷貝)

在數據類型為引用類型的時候,當你給這個變量賦值,其實是引用這個變量在內存中的地址。如下:

var obj = {name: 'ccc', age: 18}    // 定義一個變量為對象,引用類型
var cloneObj = obj      // 創建一個新變量,並賦值
console.log(cloneObj)   // {name: 'ccc', age: 18}  
console.log(cloneObj === obj)   // true

淺克隆帶來的問題:

var obj = {name: 'ccc', age: 18}    // 定義一個變量為對象,引用類型
var cloneObj = obj      // 創建一個新變量,並賦值
console.log(cloneObj)   // {name: 'ccc', age: 18}  
console.log(cloneObj === obj)   // true

obj.name = 'www'
console.log(cloneObj)   // { name: 'www', age: 18 }

我們可以發現,我們修改了obj變量的屬性值的時候,cloneObj的屬性值也跟着發生了變化。原因是他們雖然是兩個變量,但是引用的變量是同一個變量。看下圖分析:

深度克隆(深拷貝)

深度克隆,就是解決淺度克隆帶來的問題的。直接上代碼:

function deepClone(o) {
    // 判斷如果不是引用類型,直接返回數據即可
    if (typeof o === 'string' || typeof o === 'number' || typeof o === 'boolean' || typeof o === 'undefined') {
        return o
    } else if (Array.isArray(o)) { // 如果是數組,則定義一個新數組,完成復制后返回
        // 注意,這里判斷數組不能用typeof,因為typeof Array 返回的是object
        console.log(typeof [])  // --> object
        var _arr = []
        o.forEach(item => { _arr.push(item) })
        return _arr
    } else if (typeof o === 'object') {
        var _o = {}
        for (let key in o) {
            _o[key] = deepClone(o[key])
        }
        return _o
    }
}

var arr = [1, 2, 3, 5]
var cloneArr = deepClone(arr)
console.log(cloneArr)   // --> [ 1, 2, 3, 5 ]
console.log(arr === cloneArr)   // --> false

var obj = { name: 'ccc', age: 18 }
var cloneObj = deepClone(obj)
console.log(cloneObj)   // --> { name: 'ccc', age: 18 }
console.log(obj === cloneObj)   // false
obj.name = 'www'
console.log(obj)    // --> { name: 'www', age: 18 }
console.log(cloneObj)   // --> { name: 'ccc', age: 18 }

obj和cloneObj分別指向自己所存的變量地址,互不影響,代碼注釋挺詳細了,看下圖:

注意:上圖深度克隆代碼只供參考了解,還有很多細節沒有考慮,比如數組和對象的嵌套拷貝等等,具體使用請查看Lodash中的cloneDeep()方法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM