ES6中Object.assign() 方法

1. 对象合并
Object.assign 方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象上。
如下代码演示:

var target = {a: 0};
var source1 = {b: 1};
var source2 = {c: 2}; Object.assign(target, source1, source2);
console.log(target); // 输出 {a: 0, b: 1, c: 2}

1-1 如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
如下代码:

var target = {a: 0, b: 1};
var source1 = {a:1, b: 2, c:3};
var source2 = {c:5}; Object.assign(target, source1, source2); console.log(target); // 输出 {a: 1, b: 2, c: 5}

1-2 如果只有一个target(目标对象),Object.assign会直接返回该对象,如下代码:

var o = {a: 0};
Object.assign(o);
console.log(o); // {a: 0}

1-3 如果该参数不是对象,则会先转成对象,然后返回。
先是这样的,正常的返回是number类型。

var a = 1;
Object.assign(a);
console.log(a); //
console.log(typeof a); // number

然后直接判断类型,返回的是object类型

console.log(typeof Object.assign(2)) // object

1-4 对于null, undefined 来说 无法转换成Object,就会在控制台下报错,如下代码:

Object.assign(null);  // 报错
Object.assign(undefined); // 报错

1-5 对象合并,如果源对象是null的话或者是undefined的话,那么对象合并的时候不会报错,直接会跳过该对象的合并,直接返回目标对象。
如下代码:

var obj = {a: 1};
console.log(Object.assign(obj, null) === obj); // true
console.log(obj); // {a: 1} var obj = {a: 1};
console.log(Object.assign(obj, undefined) === obj); // true
console.log(obj); // {a: 1}

1-6 如果是数值,布尔型,和字符串合并对象的话,都不会报错,但是字符串会以数组的形式表现。
先看数值合并对象如下代码:

var obj = {a: 1};
console.log(Object.assign(obj, 12) === obj); // true
console.log(obj); // {a: 1}

布尔型合并对象如下代码:

var obj = {a: 1};
console.log(Object.assign(obj, true) === obj); // true
console.log(obj); // {a: 1}

字符串合并对象如下代码:

var obj = {a: 1};
console.log(Object.assign(obj, "bcd") === obj); // true
console.log(obj); // {0: 'b', 1: 'c', 2: 'd', a: 1}

如上代码,只有字符串和对象合并,这是因为只有字符串有包装对象,会产生可枚举类型属性。比如如下代码:

console.log(Object('bcd')); // {0: "b", 1: "c", 2: "d", length: 3, [[PrimitiveValue]]: "bcd"}
console.log(Object(1111)); // {[[PrimitiveValue]]: 1111}
console.log(Object(true)); // {[[PrimitiveValue]]: true}

上面代码可以看到原始值都在包装对象的内部属性[[PrimitiveValue]]上,这个属性没有被Object.assign合并,只有字符串的包装对象会产生可枚举的属性,属性则会被合并。
但是Object.assign合并的属性是有限的,只合并对象的自身的属性(不合并继承属性),也不合并不可枚举的属性。

2. Object.assign方法是浅拷贝

因此Object.assign方法是浅复制,不是深复制,也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝的是这个对象的引用。
比如如下代码:

var o1 = {a: {b: 1} };
var o2 = Object.assign({}, o1);
o1.a.b = 2;
console.log(o2.a.b); //

如上代码,o1是一个对象,该对象的属性也是一个对象,使用Object.assign拷贝o1对象到o2上来,然后手动改变o1对象的属性值,那么o2对象的属性值也会被改变。

但是如果对象的属性值不是一个对象的话,那么就不会影响该值,如下代码:

var o1 = {a: 1};
var o2 = Object.assign({}, o1);
o1.a = 2;
console.log(o1); // {a: 2}
console.log(o2.a); //

但是如果源对象和目标对象有同名属性的话,那么Object.assign会直接替换该属性。比如如下代码:

var target = {a: {b: 1}};
var source1 = {a: {b: 'hello'}};
Object.assign(target, source1);
console.log(target); // {a: {b: 'hello'}}

注意:Object.assign可以用来处理数组,但是会把数组视为对象。
也就是说对象里面有键值对索引,如果把两个数组合并的话,那么得到不是合并后新增的数组,而是会把对应相同的键替换掉,如下使用数组的demo代码如下:

var targetArrs = [1, 2, 3];
var sourceArrs = [4, 5];
Object.assign(targetArrs, sourceArrs);
console.log(targetArrs); // [4, 5, 3]

如上代码,目标对象有1,2,3属性,源对象有4,5值,如果使用Object.assign的话,那么源对象的键4,5 和目标对象的1,2键是相同的,因此值直接替换掉。

3. Object.assign 常见使用在哪些地方?
    3-1 为对象添加属性。比如如下代码:

class A {
constructor(x, y) {
Object.assign(this, {x, y});
}
}

如上方法通过Object.assign方法,将x属性和y属性添加到A类的对象实列中。

3-2 为对象添加方法

Object.assign(A.prototype, {
xMethod(x, y) {
...
},
yMethod() { }
});
// 相当于如下代码:
A.prototype.xMethod = function(x, y) {};
A.prototype.yMethod = function() {}

3-3 克隆对象

function clone(obj) {
return Object.assign({}, obj);
}

3-4 合并多个对象
如下一开始的代码:

var target = {a: 0};
var source1 = {b: 1};
var source2 = {c: 2};
Object.assign(target, source1, source2);
console.log(target); // 输出 {a: 0, b: 1, c: 2}

4. 对象深度克隆
浅度克隆和深度克隆的含义如下:
浅度克隆: 原始类型为值传递,对象类型为引用传递。
深度克隆: 所有元素或属性都是完全复制的,与原对象完全脱离,也就是说所有对于源对象的修改都不会反映到新对象中。反之,所有对于新对象的修改也不会反映到源对象中。
注意:Object.assign 是浅度克隆的。

4-1 ES5中我们可以通过递归的方式去调用函数来实现深度克隆。
代码如下:

function deepClone(obj) {
var newObj = obj instanceof Array ? [] : {};
for (var i in obj) {
newObj[i] = Object.prototype.toString.call(obj[i]) === "[object Object]" ? deepClone(obj[i]) : obj[i];
}
return newObj;
}
var obj = {a: {b: 1} };
var newObj = deepClone(obj);
console.log(newObj); // 打印输出 {a: {b: 1}} // 修改对象 obj
obj.a.b = 2;
console.log(obj); // 打印输出 {a: {b: 2}}
console.log(newObj); // 打印输出 {a: {b: 1}} 原对象的修改不会影响到新对象中

如上面的代码,在JS中,我们使用递归的方式,循环遍历对象的所有属性和方法,实现深度克隆,因此当我们深度克隆到新对象中的时候,再去更改源对象的属性值的时候,不会影响到新对象。

对象和数组一起的深度克隆

function typeOf(obj) {
const toString = Object.prototype.toString;
const map = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regExp',
'[object Undefined]': 'undefined',
'[object Null]': 'null',
'[object Object]': 'object'
};
return map[toString.call(obj)];
}
function deepCopy(data) {
const t = this.typeOf(data);
let o,
i;
if (t === 'array') {
o = [];
} else if (t === 'object') {
o = {};
} else {
return data;
}
if (t === 'array') {
for (let i = 0; i < data.length; i++) {
o.push(this.deepCopy(data[i]));
}
} else if (t === 'object') {
for (i in data) {
o[i] = this.deepCopy(data[i]);
}
}
return o;
}

ES6中Object.assign() 方法的更多相关文章

  1. ES6中Object.is方法比较两个值是否相等

    Object.is: let obj={a:1,b:2}; Object.is(obj,obj);//true Object.is(obj,{obj});//false Object.is({},{} ...

  2. 解决webpack和gulp打包js时ES6转译ES5时Object.assign()方法没转译成功的问题

    在webpack或gulp打包的配置文件中package.json 引入"@babel/plugin-transform-object-assign": "^7.2.0& ...

  3. ES6 的Object.assign(target, source_1, ···)方法与对象的扩展运算符

    一.基本概念 Object.assign方法用来将源对象(source)的所有可枚举属性,复制到目标对象(target).它至少需要两个对象作为参数,第一个参数是目标对象,后面的参数都是源对象. Ob ...

  4. Object.assign()方法

    对象的扩展 1.ES6中,对象的属性和方法可简写:对象的属性值可不写,前提是属性名已经声明: var name = "zhangsan"; "; var obj = { ...

  5. ES6之Object.assign()详解

    译者按: 这篇博客将介绍ES6新增的Object.assign()方法. 原文: ECMAScript 6: merging objects via Object.assign() 译者: Funde ...

  6. ES6学习--Object.assign()

    ES6提供了Object.assign(),用于合并/复制对象的属性. Object.assign(target, source_1, ..., source_n) 1. 初始化对象属性 构造器正是为 ...

  7. JavaScript 复制对象【Object.assign方法无法实现深复制】

    在JavaScript这门语言中,数据类型分为两大类:基本数据类型和复杂数据类型.基本数据类型包括Number.Boolean.String.Null.String.Symbol(ES6 新增),而复 ...

  8. javascript学习总结之Object.assign()方法详解

    最近再写ES6的文章时候发现自己对Object.assign()方法不太了解,之前也没有接触过所以就就查阅了相关的资料,为了自己以后肯能会用到以及对知识进行巩固,所以在这里记录下自己学习的点点滴滴,毕 ...

  9. ES6的Object.assign()基本用法

    Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target). 例如: const target = {a:1}, const source1 ...

随机推荐

  1. blfs(systemv版本)学习笔记-配置远程访问和管理lfs系统

    我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! 要实现远程管理和配置lfs系统需要配置以下软件包: 前几页章节脚本的配置:https://www.cnblogs.com/ren ...

  2. js之跑马灯广告

    目标效果:每过1秒重复把广告的第一个字符放到最后,达到动态跑马灯效果 代码如下: <!DOCTYPE html> <html lang="en"> < ...

  3. 【CSS学习】--- overflow属性

    一.前言 在网页布局中,未处理的溢出元素绝对算得上是个“毒瘤”.因为如果一个“盒子”周围还有其它元素,而从这个盒子中溢出的元素会和盒子周围的元素发生层叠,并脱离了整个HTML元素,所以我们应当合理使用 ...

  4. 【pygame游戏编程】第四篇-----打字测速游戏

    下面我们一起用pygame编写一个打字测速游戏 这是一个很实用的有趣的小游戏: 开始之前先来学习几个小函数: 1. ord(ch) python内置函数,传入一个字符,返回字符的ascii码 2.ch ...

  5. 洛谷P3193 [HNOI2008]GT考试(dp 矩阵乘法)

    题意 题目链接 Sol 设\(f[i][j]\)表示枚举到位置串的第i位,当前与未知串的第j位匹配,那么我们只要保证在转移的时候永远不会匹配即可 预处理出已知串的每个位置加上某个字符后能转移到的位置, ...

  6. link标签链接CSS和@import加载的区别

    link:基本语法 <link rel="stylesheet" href="路径"> @import 基本语法 <style> @im ...

  7. Angular基础(四) 创建Angular应用

    应用(Application)是由组件构成的树.树的根部是最顶层的组件即应用本身,启动的时候,浏览器会最先渲染顶层组件,然后根据树形结构,迭代渲染子组件.组件是可装配的,可以互相组合以构成更大的组件. ...

  8. winsock编程学习笔记

    以下部分转自博客http://blog.csdn.net/phunxm/article/details/5085869 套接字地址(sockaddr.sockaddr_in) /* * Structu ...

  9. (后端)NoSuchMethodError

    这个错误是说编译时有这个方法,但运行时没有了 请使用:mvn clean install

  10. scrapy系列(二)——startproject、genspider创建项目与模板使用

    阅读本文之前需要安装scrapy,如果你还没有安装该框架,那么可以看之前一篇文章scrapy1.2windows安装. 现在默认大家都已经成功的安装了scrapy可以开始大展身手了.本文主要讲的是新建 ...