Js中对象的深拷贝和浅拷贝

浅拷贝:只拷贝对象的基础属性值,对属性值为对象或数组的属性则拷贝指针。 
深拷贝:拷贝对象的所有属性作为一个全新的对象。拷贝前后的对象互不影响。

浅拷贝仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么深拷贝出来的对象也会相应改变。

一、对象引用

对象引用容易理解,直接赋值,修改复制后的数组,原对象会随之改变。

//对象引用
var boy = {
	age:18
    }
var girl = boy;
console.log(boy === girl);//true
girl.age = 20;
console.log(boy.age);//20 

理解:使用“=”进行赋值,girl和boy指向了同一内容地址,修改一个,另一个也会修改。

二、浅拷贝

使用Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

//浅拷贝
var boy = {
	age:18
    }
var girl = Object.assign({}, boy);
console.log(boy === girl);//false
girl.age = 20;
console.log(boy.age);//18

理解:上述代码将原始对象拷贝到一个空对象,就得到原始对象的克隆,原对象和拷贝对象指向不同的内存地址,修改原对象和克隆对象,互补影响。

var boy = {
	age:18,
	address:{
		home:'北京'
	}
}
var girl = Object.assign({}, boy);
console.log(boy === girl);//false
girl.address.home = '上海';
console.log(boy.address.home);//上海 

理解:上述代码将原始对象拷贝到一个空对象,就得到原始对象的克隆。因为Object.assign()只是浅拷贝girl.address是对栈对象的引用,因此内层对象的修改会影响原始对象。

三、深拷贝

1、JSON.parse()与JSON.stringify()深拷贝

可以通过JSON对象的方法,来进行对象的深拷贝,代码如下:

//纯数据json对象的深度克隆
function deepClone(obj) {
     return JSON.parse(JSON.stringify(obj));
}

理解:通过对象符串化和字符串对象化进行对象的拷贝。此方法只使用与纯JSON对象的深拷贝

2、对象遍历

//包含其他负责的内容 date对象 null undefined
var obj1={
	name:"张三",
	age:20,
	height:[12,26,46],
	address:{
	    home:'北京'
	},
	birthday:new Date(),
	father:null,
	mother:undefined,
	school:[
			{
				middleschool:'北大附中',
			},
			{
				university:'清华大学',
			}
		]
	}
	function clone(obj) { 
	    if(obj === null) return null 
	    if(typeof obj !== 'object') return obj;
	    if(obj.constructor === Date) return new Date(obj); 
	    if(obj.constructor === RegExp) return new RegExp(obj);
	    var newObj = new obj.constructor ();  //保持继承链
	    for (var key in obj) {
		 if (obj.hasOwnProperty(key)) {   //不遍历其原型链上的属性
		      var val = obj[key];
		      newObj[key] = typeof val === 'object' ? arguments.callee(val) : val; // 使用arguments.callee解除与函数名的耦合
		  }
            }  
            return newObj;  
	}; 
        console.log(obj1);
    console.log(clone(obj1));

理解:

(1)、用 new obj.constructor ()构造函数新建一个空的对象,可以保持原形链的继承;

(2)、用obj.hasOwnProperty(key)来判断属性是否来自原型链上,因为for..in..也会遍历其原型链上的可枚举属性。

(3)、函数用到递归算法,在函数有名字,而且名字以后也不会变的情况下,这样定义没有问题。但问题是这个函数的执行与函数名 factorial 紧紧耦合在了一起。为了消除这种紧密耦合的现象,需要使用 arguments.callee

参考:https://www.cnblogs.com/wangyulue/articles/7684515.html
























你可能感兴趣的:(JavaScript)