JS进阶-浅克隆与深克隆

271 阅读1分钟

1.浅克隆

Object.assign

var obj1 = {
    a: 1,
    b: {
        a: 2
    }
}
// 浅拷贝
var obj2 = Object.assign({}, obj1)
// 修改obj2.a属性不会受影响
obj2.a = 2
console.log(obj1.a) // 1
// 修改obj2.b.a属性会受影响
obj2.b.a = 3
console.log(obj1.b.a) // 3

Array.prototype.concat

var arr1 = [1, [2]]
// 浅拷贝
var arr2 = Array.prototype.concat.call([], arr1)
// 修改arr2[0]不会受影响
arr2[0] = 2
console.log(arr1[0]) // 1
// 修改arr[1][0]会受影响
arr2[1][0] = 1
console.log(arr1[1][0]) // 1

$.extend

// jq中的方法
// 用法
var obj = {
    a: 1,
    b: {
        a: 2
    }
}
var obj1 = $.extend({}, obj)
console.log(obj.b === obj1.b)   // true

2.深克隆

JSON

// 劣势:会忽略undefined、function的克隆
function deepClone(obj) {
    return JSON.parse(JSON.stringify(obj))
}

$.extend

var obj = {
    a: 1,
    b: {
        a: 2
    }
}
// 第一个参数如果为true,表示进行深克隆
var obj1 = $.extend(true, {}, obj)
console.log(obj.b === obj1.b)   // false

手写一个deepClone

var deepClone = (function() {
    var checkType = function(anyType, type) {
        return Object.prototype.toString.call(anyType) === ('[object ' + type + ']')
    }

    return function(o) {
        // typeof null === 'object' 需排除
        if (typeof o === 'object' && o !== null) {
            // 数组或对象
            if (checkType(o, 'Array')) {
                var len = o.length
                var arr = new Array(len)
                for (var i = 0; i < len; i++) {
                    arr[i] = deepClone(o[i])
                }
                return arr
            } else {
                var obj = {}
                for (var prop in o) {
                    // 防止克隆原型上的属性
                    if (o.hasOwnProperty(prop)) {
                        obj[prop] = deepClone(o[prop])
                    }
                }
                return obj
            }
        } else {
            return o
        }
    }
})()

var obj = {
    a: 1,
    b: {
        a: 2
    }
}
var obj1 = deepClone(obj)
console.log(obj.b === obj1.b)   // false