深浅拷贝

JS的数据类型分为两种,一种是基本数据类型,另一种是引用数据类型。
基本数据类型有6种:undefinednullnumberbooleanstringsymbol(ES6)。
引用数据类型只有1种:object

JS中的变量都保存在栈内存中,对于基本数据类型,变量值保存的是基本数据类型的值;对于引用数据类型,浏览器会在堆内存中分配一块内存给它,而栈内存中的变量值保存的是这块内存的地址。因为保存在栈内存的必须是大小固定的数据,引用数据类型的大小不固定,因此只能保存在堆内存中,而把它的地址保存在栈内存中。

var a = 1;
var obj1 = {
    name:'obj'
};

在这里插入图片描述

使用赋值运算符(=)将一个变量赋值给另一个变量的时候,复制的是栈内存中的变量值,因此,对于基本数据类型,复制的是基本数据类型的值,对于引用数据类型,复制的是地址。对于基本数据类型,没有深浅拷贝的说法,深浅拷贝只限于引用数据类型。

浅拷贝

浅拷贝创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。

方法一
//浅拷贝函数
function qiankaobei(obj){
	var newObj = obj instanceof Array ? [] : {};
	for(var i in obj){
		if(obj.hasOwnProperty(i)){
			newObj[i] = obj[i];
		}
	}
	return obj;
}

var arr1 = [[1,2],3];
var arr2 = qiankaobei(arr1);			//浅拷贝
arr2[0][0] = 0;
console.log(arr1[0][0]);				//0,修改arr2会影响到arr1
方法二

使用JQuery的$.extend()方法实现浅拷贝。
语法:var newObj = $.extend(false,{},obj)
如果第一个参数是false,那么$.extend()方法会返回一个浅拷贝后的对象。

var obj = {
	name: 'XD',
	friend: ['JH','ZH'],
	sayName: function(){
		console.log(this.name);
	}
};    
var newObj = $.extend(false,{},obj);

newObj		// {name: "XD", friend: Array(2), sayName: ƒ}
obj2.sayName === obj.sayName	//true

newObj.friend[0] = 123;
obj.friend[0]	//123

newObj.name = 456;
obj.name	//"XD"
深拷贝

深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

方法一
//深拷贝函数
function shenkaobei(obj){
    if(typeof obj !== 'object'){
        return;
    }
    var newObj = obj instanceof Array ? [] : {};
    //var newObj = Array.isArray(obj) ? [] : {};
    for(var i in obj){
        if(obj.hasOwnProperty(i)){
            if(typeof obj[i] === 'object'){
                newObj[i] = shenkaobei(obj[i]);
            }else{
                newObj[i] = obj[i];
            }
        }
    }
    return newObj;
}

var arr1 = [[1,2],3];
var arr2 = shenkaobei(arr1);		//深拷贝
arr2[0][0] = 0;
console.log(arr1[0][0]);			//1,修改arr2不会影响到arr1
方法二

利用JSON.parse(JSON.stringify(obj))可以实现深拷贝。

var arr1 = [[1,2],3];
var arr2 = JSON.parse(JSON.stringify(arr1));		//深拷贝
arr2[0][0] = 0;
console.log(arr1[0][0]);			//1,修改arr2不会影响到arr1

缺点:

  1. 非数组对象的属性不能保证以特定的顺序出现在序列化后的字符串中;
  2. 布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值;
  3. undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时);
  4. 所有以 symbol 为属性键的属性都会被完全忽略掉,即便 replacer 参数中强制指定包含了它们;
  5. 不可枚举的属性会被忽略。
var obj = {
    sayName: function(){
        console.log('hi');
    },
    arr: [1,undefined,null,Symbol()],
    [Symbol()]: 123
}
var obj2 = JSON.parse(JSON.stringify(obj));

obj2	//{arr: Array(4)}
obj.arr	//[1,null,null,null]
方法三

使用JQuery的$.extend()方法实现深拷贝。
语法:var newObj = $.extend(true,{},obj)
如果第一个参数是true,那么$.extend()方法会返回一个深拷贝后的对象。

var obj = {
	name: 'XD',
	friend: ['JH','ZH'],
	sayName: function(){
		console.log(this.name);
	}
};    
var newObj = $.extend(true,{},obj);

newObj		// {name: "XD", friend: Array(2), sayName: ƒ}
obj2.sayName === obj.sayName	//true

newObj.friend[0] = 123;
obj.friend[0]	//"JH"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值