Es6 Object.assign()用法 以及浅拷贝、深拷贝的实现方式

1、MDN 文档已详细介绍 Object.assign()用法:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

Object.assign

用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象

 

1

<script>
	 let obj1 = {name:'山东',id:1,city:{name:'青岛',cityId:'2'}};
	 let obj2 = Object.assign(obj1);
	 obj2.city.name = '济南'; 
	 obj2.city.cityId = 3;
	 console.log(obj1);   //它将返回目标对象
	
</script>

Object.assign(target, ...sources)   

target:目标对象

sources:源对象

返回值:目标对象

 

//2、如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。后面的源对象的属性将类似地覆盖前面的源对象的属性。

let obj1 = {name:'山东',id:1};
let obj2 = {name:'青岛',id:2};
let obj3 = Object.assign(obj1,obj2);
console.log(obj1,obj3);  //后面的源对象的属性将类似地覆盖前面的源对象的属性。

//3、由于undefined和null无法转成对象,所以如果它们作为参数,就会报错。

Object.assign(undefined) // 报错
Object.assign(null) // 报错
//4、注意:Object.assign 不会在那些source对象值为 null 或 undefined 的时候抛出错误

let obj = {id: 1};
Object.assign(obj, undefined) === obj // true
Object.assign(obj, null) === obj // true


如果非对象参数出现在源对象的位置(即非首参数),那么处理规则有所不同。首先,这些参数都会转成对象,如果无法转成对象,就会跳过。这意味着,如果undefined和null不在首参数,就不会报错。
//5、 其他类型的值(即数值、字符串和布尔值)不在首参数,也不会报错。但是,除了字符串会以数组形式,拷贝入目标对象,其他值都不会产生效果。(数值和布尔值都会被忽略。这是因为只有字符串的包装对象,会产生可枚举属性。)

const a = '山东';
const b = true;
const c = 10;
const obj = Object.assign({}, a, b, c);
console.log(obj);

// 6、拷贝的属性是有限制的,只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false)

 const ccc = Object.assign({b: 'c'},
		  Object.defineProperty({}, 'invisible', {
		    enumerable: false,
		    value: 'hello'
		  })
 )
    console.log(ccc)

 

 

// 7、 属性名为 Symbol 值的属性,也会被Object.assign拷贝。

    const ccc = Object.assign({b: 'c'},{ [Symbol('d')]: 'e' })
		 
    console.log(ccc)

 

2、浅拷贝:只针对Object和Array这样的对象数据类型

// 浅拷贝的实现方式

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>浅/深拷贝</title>
</head>
<body>
	
</body>
<script>
	 // 1、直接复制一个变量

	 let obj1 = {name:'山东',id:1,city:{name:'青岛',cityId:'2'}};
	 let obj2 = obj1;
	 obj2.city.name = '济南'; 
	 obj2.city.cityId = 3;
	 console.log(obj1, obj2);  // 修改复制的对象会影响原对象
	
</script>
</html>

// 2、Object.assign()   第一条已介绍

 let obj1 = {name:'山东',id:1,city:{name:'青岛',cityId:'2'}};
 let obj2 = Object.assign(obj1);
 obj2.city.name = '济南'; 
 obj2.city.cityId = 3;
 console.log(obj1);

 

 // 3、Array.prototype.concat()  注意: 修改新对象会改到原对象:

    let arr = [1, 2, {
	    name: '山东'
	    }];
	let arr2 = arr.concat();
	arr[0] = 8;
    arr2[1] = '这是和arr1的区别'; 
	arr2[2].name = '山西';
	console.log(arr,arr2);



    var arr1 = ["1","2","3"];
	var arr2 = arr1.concat();
	arr2[1] = "9";
	console.log(arr1,arr2);  //["1","2","3"]   ["1","9","3"];

// 4、Array.prototype.slice()   注意:修改新对象会改到原对象

	let arr = [1, 2, {
	   name: ' 山东'
	     }];
	 let arr3 = arr.slice();
	 arr3[2].name = '山西'
	 console.log(arr,arr3);

 

 

//补充  

关于Array的slice和concat方法的补充说明:Array的slice和concat方法不修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。


如果该元素是个对象引用(不是实际的对象),slice 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变


对于字符串、数字及布尔值来说(不是 String、Number 或者 Boolean 对象),slice 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组

 3、深拷贝

	// 深拷贝

	// 1、JSON.parse(JSON.stringify())
    
    let arr = [1, 2, {
	name: '山东'
   }];
    let arr3 = JSON.parse(JSON.stringify(arr))
	arr3[1] = 6;
	arr3[2].name = '山西';
	console.log(arr,arr3);

    //原理:首先用JSON.stringify()将对象转化成JSON字符串,再用JSON。parse()将字符串解析成对象。 
            这样新的对象就会产生。而且对象会开辟新的栈。实现了深拷贝。


    // 注意:这种方法虽然可以实现数组或者对象的深拷贝,但是不能处理函数

     let arr = [1, 2, {
	name: '山东'
   },function add() {
   }];
    let arr3 = JSON.parse(JSON.stringify(arr))
	arr3[1] = 6;
	arr3[2].name = '山西';
	console.log(arr,arr3);

	// 因为JSON.stringify()方法是将一个对象或者数组转化成一个JSON字符串,不能接收函数

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值