3.深复制与浅复制

浅复制

js中内置了几种对对象进行复制的操作

//展开语法进行复制
let array = [1,2,3]
let newArr = [...array]

//Array.prototype.concat()合并数组进行复制
let array = [1,2,3]
let newArr = array.concat([])

//Array.prototype.slice()剪切原数组进行复制
let array = [1,2,3]
let newArr = array.slice()

//Array.from() 使用迭代器返回新数组
let array = [1,2,3]
let newArr = Array.from(array)

//Object.assign() 将一个或多个对象复制到一个新对象中
let array = [1,2,3]
let newArr = Object.assign(array)

//Object.create() 以现有对象为原型,创建一个新对象
let array = [1,2,3]
let newArr = Object.create(array)

//for...in 逐个进行复制
var obj = {a:1,b:2}
var newObj = {}
for(var prop in obj){
    newObj[prop] = obj[prop]
}

而以上全部方式,均为浅复制

深复制

深复制相对浅复制而言,可以避免复制的新对象因改变引用地址中数据而使源数值同步改变。

以递归的方式进行简单深复制
/**
 * 深复制
 * @param {*} obj 传入对象
 * @returns 复制出来的对象
 */
function deepClone(obj) {
    // 判断传入数据是否为空或者是否为对象,如果不是,则不需要复制,直接返回
    if (typeof obj !== 'object' || obj == null) {
        return obj
    }
    // 初始化返回结果
    let result
    // 通过原型链判断初始传入对象是否为数组
    if (obj instanceof Array) {
        result = []
    }else{
        result = {}
    }
    // 开始复制
    for (const key in obj) {
        // 判断key是否为对象自有属性,保证key不是原型的属性(不是继承来的)
        if (obj.hasOwnProperty.call(obj, key)) {
            // 递归,循环判断插入复制
            result[key] = deepClone(obj[key])
        }
    }
    return result
}

值得注意的是,这种方式其实并不完美,仅适合面试等考察代码逻辑等场景更全面的深复制方法,可以参考:终极深复制

而在编码过程中,建议使用以下方式进行深复制

//先用JSON.stringify将对象转化为字符串,再用JSON.parse将字符串转化为数组
//但是无法复制函数或者其他类型,只支持字符串,数值,对象,数组,布尔值,undefind.
//也无法复制对象原型链上的属性和方法.
var obj = {a:1,b:2}
var newObj = JSON.parse(JSON.stringify(obj))

该方式需要注意,仅可对可序列化的数据进行操作,如带有闭包的函数,symbol,递归数据以及其他无法序列化的情况下,使用该方式会失败。

structuredClone()
全局的 structuredClone() 方法使用 结构化克隆算法将给定的值进行 深拷贝
该方法还支持把原始值中的 可转移对象转移到新对象,而不是把属性引用拷贝过去。
可转移对象与原始对象分离并附加到新对象;它们不可以在原始对象中访问被访问到。
let array = [1,2,3]
let newArr = structuredClone(array);

值得注意的是,当遇到不可序列化数据时,会抛出错误DataCloneErrorDOMException

且该方法并不是js语言本身的特性,而是依赖于浏览器实现的,有可能会有兼容问题(概率很小)

总结

浅复制时,建议使用‘展开语法’

深复制时,建议使用‘JSON.stringify’(前提:可序列化)。当然以现在发展水平一般也不会出现兼容问题,‘structuredClone()’一样可以使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值