js手写题——浅拷贝与深拷贝

基本数据类型存放在栈内存中,引用数据类型如对象、数组存放在堆内存中,其变量是存在栈内存中的指针。
比较两个引用类型变量时,是比较的地址,而不是比较的引用类型的值。

var a = [1,2,3];
var b = [1,2,3];
console.log(a === b);  // false

浅拷贝:

直接复制、Object.assign()、concat、slice、展开运算符(只拷贝一层)
for…in…

var obj={
    id:1,
    name:'andy',
    msg:{
        age:18
    }
}
var o={};
for(var k in obj){
     o[k]=obj[k];//只拷贝地址
}
//console.log(obj);
//o.msg.age=20;
//console.log(obj);

ES6中实现浅拷贝Object.assign(target,…sources)

var obj={
    id:1,
    name:'andy',
    msg:{
        age:18
    }
}
var o={};
Object.assign(o,obj);
console.log(o);

手写Object.assign,即浅拷贝:

Object.myAssign = function(target, ...source) {
    if (target == null) {
        throw new TypeError('Cannot convert undefined or null to object')
    }
    let ret = Object(target) 
    source.forEach(function(obj) {
        if (obj != null) {
            for (let key in obj) {
                if (obj.hasOwnProperty(key)) {
                    ret[key] = obj[key]
                }
            }
        }
    })
    return ret
}

concat

var a = [1, [2, 3, 4], {
    name: 'Fan'
}];
var b = a.concat(5)//b=[1,[2,3,4],{name:'fan'},5]

a[0] = 6;
console.log(b[0]) // 1 看起来像深拷贝

a[1][0] = 999;
console.log(b[1][0]) // 999 浅拷贝

a[2].name = 'Liu'
console.log(b[2].name) // 'Liu' 浅拷贝

slice

var a = [1, [2, 3, 4], {
    name: 'Fan'
}];
var b = a.slice(0)

a[0] = 6;
console.log(b[0]) // 1 看起来像深拷贝

a[1][0] = 999;
console.log(b[1][0]) // 999 浅拷贝

a[2].name = 'Liu'
console.log(b[2].name) // 'Liu' 浅拷贝

展开运算符…
只拷贝一层

var person1 = {
  name: '小明',
  age: 18,
  sex: '男',
  hobby: {
    music: '伤感类歌曲',
    like: '吃饭、睡觉、打游戏',
  }
}

var xiaoHong = {...person1}
xiaoHong.name = '小红';
xiaoHong.hobby.music = '小清新歌曲';

console.log(person1)
// 输出: {name: "小明", age: 18, sex: "男", hobby: {music: "小清新歌曲",like: "吃饭、睡觉、打游戏"}}
console.log(xiaoHong)
// 输出: {name: "小红", age: 18, sex: "男", hobby: {music: "小清新歌曲",like: "吃饭、睡觉、打游戏"}}

深拷贝:

JSON.parse(JSON.stringify())

var str1 = {
    name: 'Fan', 
    age: 22,
    other: {
        school: 'HuangHuai'
    }
}
var str2 = JSON.parse(JSON.stringify(str1));//JSON.stringify将对象转变为字符串,这样用JSON.parse时是在为一个字符串转对象开辟新的内存空间
str2.name = 'Jun'
console.log(str1.name) // Fan
str2.other.school = 'ShiYan'
console.log(str1.other.school) // HuangHuai

缺点:只能拷贝符合JSON格式的数据,不能拷贝函数。

开辟新内存+递归

function deepClone(source){
    if(source===null) return source;
    if(source instanceof Date) return new Date(source);
    if(source instanceof RegExp) return new RegExp(source);
    const target=Array.isArray(source)?[]:{};
    for(let key in source){//for...in...遍历会遍历到原型链上的属性
        if(source.hasOwnProperty(key)){//只复制元素自身的属性,不复制原型链上的
            target[key]= (typeof source[key]==='object'?deepClone(source[key]):source[key]);
        }
    }
    return target;
}

for…of…不能遍历对象,可以遍历数组,返回的是每一项的值;for…in…都能遍历,遍历的是key(属性)。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值