深聊js中的数据拷贝及其实现原理

浅拷贝概念「新的对象复制已有对象中非对象属性的值和对象属性的引用」。也可以理解为:「一个新的对象直接拷贝已存在的对象的对象属性的引用」,即浅拷贝。常见的浅拷贝的情景如下

1. Object.assign

let user = { name: 'lp', skill: {js:90,css:80}}
let cuser = Object.assign({},user)
cuser.name = 'lxp'
cuser.skill.css = 90
console.log('user =>',user) // user => { name: 'lp', skill: { js: 90, css: 90 } }
console.log('cuser =>',cuser) // cuser => { name: 'lxp', skill: { js: 90, css: 90 } }

2. Array.prototype.slice()

let person = ['lp','peng',{name:'8888'}]
let cperson = Array.prototype.slice.call(person)
cperson[0] = 'lp88888'
cperson[2]['name'] = 'ping9999'
console.log('person=>',person) // person=> [ 'lp', 'peng', { name: 'ping9999' } ]
console.log('cperson =>',cperson) // cperson => [ 'lp88888', 'peng', { name: 'ping9999' } ]

3. Array.prototype.concat()

let user  = [{name: "lipeng"},   {age: 28}];
let user1 = [{age: 20},{addr: "七台河"}];
let user2 = user.concat(user1);
user1[0]["age"] = 25;
console.log(user);  // [ { name: 'lipeng' }, { age: 28 } ]
console.log(user1); // [ { age: 25 }, { addr: '七台河' } ]
console.log(user2); // [ { name: 'lipeng' }, { age: 28 }, { age: 25 }, { addr: '七台河' } ]

4. 扩展运算符(...)

let user = { name: "lp", skill: { JavaScript: 90, CSS: 80}};
let cuser = {...user};
cuser.name = "lxp";
cuser.skill.CSS = 90;
console.log('user =>',user) // user => { name: 'lp', skill: { JavaScript: 90, CSS: 90 } }
console.log('cuser =>',cuser) // cuser => { name: 'lxp', skill: { JavaScript: 90, CSS: 90 } }

5.浅拷贝的实现原理

function cloneShallow(source) {
    let target = Array.isArray(source) ? [] : {};
    for (let key in source) {
        if (Object.prototype.hasOwnProperty.call(source, key)) {
            target[key] = source[key];
        }
    }
    return target;
}

深拷贝概念:复制变量值,对于引用数据,则递归至基本类型后,再复制。深拷贝后的对象「与原来的对象完全隔离」,互不影响,对一个对象的修改并不会影响另一个对象。即为 深拷贝,常见深拷贝如下:

1. JSON.parse和JSON.stringify()

let user = { name: "zs", skill: { JavaScript: 90, CSS: 80 }, person: [{ name: 'zs', age: 28 }] };
let cuser = JSON.parse(JSON.stringify(user));
cuser.name = "ls";
cuser.skill.CSS = 90;
cuser.person[0].name = 'ls'
console.log(cuser) // { name: 'ls',skill: { JavaScript: 90, CSS: 90 }, person: [ { name: 'ls', age: 28 } ] }
console.log(user) // { name: 'zs', skill: { JavaScript: 90, CSS: 80 }, person: [ { name: 'zs', age: 28 } ] }

2. 深拷贝原理

function deepClone(origin, target){

    var target = target || {},
        toStr = Object.prototype.toString,
        arrStr = "[object Array]";
    for (var prop in origin) {
        if (origin.hasOwnProperty(prop)) {
            if (origin[prop] !== "null" && typeof (origin[prop]) == 'object') {
                if (toStr.call(origin[prop]) == arrStr) {
                    target[prop] = [];
                } else {
                    target[prop] = {};
                }
                deepClone(origin[prop], target[prop]);
            } else {
                target[prop] = origin[prop];
            }
        }
    }
    return target;
}

3.可以解析时间和正则的深度克隆

function deepClone(source) {
    if(source == null) return null;
    if(source instanceof Date) return new Date(source);
    if(source instanceof RegExp) return new RegExp(source);
    if(typeof source !== 'object') return source;
    // 保留着类的继承关系
    const target = new source.constructor();
    for(let key in source){
        target[key] = typeof source[key] === 'object' ? deepClone(source[key]): source[key];
    }
   
    return target
}

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值