工作日常--js引用类型数据深拷贝与浅拷贝

js数据类型
  • 简单数据类型

    简单的数据类型包括Undifine,NULL,Bolean,String,Number。这些数据类型的数据的保存是在堆中存储的。堆中存放的数据是先进先出。FIFO(first in first out)

  • 引用类型

    引用类型包括Object和Array,引用数据类型是存放在栈中的。栈中存放的数据是先进后出的。FILO(frist in last out)

关于js的浅拷贝和深拷贝

++只有引用数据类型才会有深拷贝和浅拷贝这么一说。由于js的存储都是存地址的,浅拷贝会导致obj1和obj2指向同一个内存地址。这么一来,如果操作其中的任意一个obj那么就会导致元内存地址的数据更改。所以需要使用到深拷贝,为拷贝出的对象开辟一块新的内存地址。这样一来,就会出现原对象与新拷贝的对象在不同的内存地址。从而达到前后对象相互不影响。++

浅拷贝

数组的浅拷贝

var oldArray = [1,2,3,4,5,6];
var newArray = [];
newArray = oldArray;
newArray[0] = '改变的元素';
console.log(oldArray); // '改变的元素',2,3,4,5,6
console.log(newArray); // '改变的元素',2,3,4,5,6

对象的浅拷贝

function copyObject(obj){
    var outObj = {};
    for(var item in obj){
        outObj.item = obj[item];
    }
    return outObj;
}

// Object.assign() 将元对象的属性枚举到新的对象,然后返回新的对象

var obj = {
    name:'二货',
    sex:'male',
    age:23
}
var b = {};
Object.assign(b,obj);
if(b === obj)  // true
深拷贝

数组的concat与slice方法(假装深拷贝)

++concat与slice方法都是浅拷贝一个数组的元素然后拷贝给一个新的数组。只是如果数组的单个元素是数字,字符串等简单数据类型的时候,原数组的对象不会受新数组的影响。如果数组的项是引用类型数组或对象,则就是浅拷贝。++

var origin = [1,2,3,4,5];
var copySlice = origin.slice(0);
var copyConcat = origin.concat();
copySlice[0] = 'one';
copyConcat[0] = 'concat';
console.log(origin); // [1,2,3,4,5]

var origin = [[1,2,3],{name:'lol'}];
var copySlice = origin.slice(0);
var copyConcat = origin.concat();
copySlice[0][0] = 'slice';
copyConcat[1].name = 'concat';
console.log(origin) // [['slice',2,3],{name:'concat'}]

深拷贝实现方法JSON.parse和JSON.stringify();

这种方法使用较为简单,可以满足基本的深拷贝需求,而且能够处理JSON格式能表示的所有数据类型,但是对于正则表达式类型、函数类型等无法进行深拷贝(而且会直接丢失相应的值)。还有一点不好的地方是它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。同时如果对象中存在循环引用的情况也无法正确处理。

//例1
var source = { name:"source", child:{ name:"child" } } 
var target = JSON.parse(JSON.stringify(source));
target.name = "target";  //改变target的name属性
console.log(source.name); //source 
console.log(target.name); //target
target.child.name = "target child"; //改变target的child 
console.log(source.child.name); //child 
console.log(target.child.name); //target child
//例2
var source = { name:function(){console.log(1);}, child:{ name:"child" } } 
var target = JSON.parse(JSON.stringify(source));
console.log(target.name); //undefined
//例3
var source = { name:function(){console.log(1);}, child:new RegExp("e") }
var target = JSON.parse(JSON.stringify(source));
console.log(target.name); //undefined
console.log(target.child); //Object {}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值