深拷贝 VS 浅拷贝 VS 对象赋值

本文深入探讨了JavaScript中数据类型的存储方式,详细解释了深拷贝与浅拷贝的概念及其实现方法,包括对象赋值、浅拷贝的实现及深拷贝的多种实现方式,如JSON.parse(JSON.stringify())、手写递归方式以及使用lodash库。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据类型

  • 基本数据类型:string,Number,Boolean,Null,Undefined,Symbol
    • 特点:直接存储在栈(stack)中
  • 引用数据类型:Array,Obeject
    • 特点:存储的是该对象在栈中的引用,真实数据存放在堆内存里

深拷贝 && 浅拷贝

深拷贝和浅拷贝只是针对于引用数据类型的,浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象共享一个内存。深拷贝恰恰相反。

赋值 && 浅拷贝

对象赋值是把该对象存储在栈中的地址赋给一个新变量,而不是堆中的数据,也就是说,无论哪一个对象改变,另外一个对象会跟着改变

var obj1= {
    "name": "zhangsan",
    "age":"18",
    "language":[1,[2,3],[4,5]],
}
var obj2 = obj1
obj2.name = lisi"
obj2.language[1] = ["二", "三"]
console.log("obj1", obj1)
console.log("obj2", obj2)

结果是:

{
    "name": "lisi",
    "age":"18",
    "language":[1,["二", "三"],[4,5]],
}
{
    "name": "lisi",
    "age":"18",
    "language":[1,["二", "三"],[4,5]],
}

浅拷贝会创建一个全新的对象,这个对象有原对象一份精确的拷贝。其中,如果属性是基本类型,则拷贝的就是基本类型的值,如果是引用类型,拷贝的就是内存地址。默认拷贝构造函数只是对对象的浅拷贝。
一个亲拷贝的实现

function shallowCopy(src){
    var dis = {}
    for(var prop in src){
        if(src.hasOwnProperty(prop)){
            dis[prop] = src[prop]
        }
    }
    return dist
}

如果对对象 obj1 通过上边的方法进行浅拷贝出来一个obj3,然后对 Obj3 的 name 和 language 进行修改,最终结果是 obj1 的 name 未发生改变,而 language 值方发生了改变。看来,obj3.language[1] = [“二”, “三”] 的操作相应地址指向了内存中的数据[“二”, “三”],自然 obj1 中的相应地址也指向了它。

实现浅拷贝的 API

  • Object.assign() //当 Object 只有一层时,是深拷贝
  • Array.prototype.concat()
  • Array.prototype.slice()

深拷贝实现方式

  • JOSN.parse(JSON.Stringfy()):这种方法虽然可以实现数组或者对象的深拷贝,但不能处理函数
  • 手写递归方式
    递归方法实现深拷贝的原理:便利对象、数组,值到里边都是基本数据类型,然后再去fu’z,就是深拷贝
// 定义检测数据类型的功能函数
function checkedType(target){
    return Object.prototype.toString.call(target).slice(8, -1)
}
// 实现深拷贝
function clone(target){
    // 判断拷贝的数据类型
    // 初始化变量 result 成为最终克隆的数据
    let result, targetType = checkedType(target)
    if(targetType === Object){
        return result = {}
    } else if(targetType === Array) {
        return result = []
    } else {
        return target
    }
    // 遍历目标数据
    for(let i in target) {
        let value = target[i]
        if(checkedType(value) === "Object" || checkedType(value) === "Array") {
            return result[i] = clone(value)
        } else {
            result[i] = value
        }
    }
    return result
}
  • 函数库loadash
    该函数库有提供 _.cloneDeep 做深拷贝
var _ = require('lodash')
var obj1 = {
    a:1,
    b:{f:{g:1}},
    c:[1,2,3]
}
var obj2 = _.cloneDeep(obj1)
console.log(obj1.b.f === obj2.b.f)  //false
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值