es6 javascript对象方法Object.assign()

2016年12月01日 16:42:34

阅读数:38583

1  基本用法

Object.assign方法用于对象的合并,将源对象( source )的所有可枚举属性,复制到目标对象( target )。

  1. var target = { a: 1 };
  2. var source1 = { b: 2 };
  3. var source2 = { c: 3 };
  4. Object.assign(target, source1, source2);
  5. target // {a:1, b:2, c:3}

Object.assign方法的第一个参数是目标对象,后面的参数都是源对象。

注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。

  1. var target = { a: 1, b: 1 };
  2. var source1 = { b: 2, c: 2 };
  3. var source2 = { c: 3 };
  4. Object.assign(target, source1, source2);
  5. target // {a:1, b:2, c:3}

如果只有一个参数,Object.assign会直接返回该参数。

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

如果该参数不是对象,则会先转成对象,然后返回。

  1. typeof Object.assign(2) // "object"

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

  1. Object.assign(undefined) //  报错
  2. Object.assign(null) //  报错

如果非对象参数出现在源对象的位置(即非首参数),那么处理规则有所不同。首先,这些参数都会转成对象,如果无法转成对象,就会跳过。这意味着,如果undefined和null不在首参数,就不会报错。

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

其他类型的值(即数值、字符串和布尔值)不在首参数,也不会报错。但是,除了字符串会以数组形式,拷贝入目标对象,其他值都不会产生效果。

  1. var v1 = 'abc';
  2. var v2 = true;
  3. var v3 = 10;
  4. var obj = Object.assign({}, v1, v2, v3);
  5. console.log(obj); // { "0": "a", "1": "b", "2": "c" }

上面代码中,v1、v2、v3分别是字符串、布尔值和数值,结果只有字符串合入目标对象(以字符数组的形式),数值和布尔值都会被忽略。这是因为只有字符串的包装对象,会产生可枚举属性。

  1. Object(true) // {[[PrimitiveValue]]: true}
  2. Object(10) // {[[PrimitiveValue]]: 10}
  3. Object('abc') // {0: "a", 1: "b", 2: "c", length: 3, [[PrimitiveValue]]: "abc"}

上面代码中,布尔值、数值、字符串分别转成对应的包装对象,可以看到它们的原始值都在包装对象的内部属性[[PrimitiveValue]]上面,这个属性是不会被Object.assign拷贝的。只有字符串的包装对象,会产生可枚举的实义属性,那些属性则会被拷贝。

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

  1. Object.assign({b: 'c'},
  2. Object.defineProperty({}, 'invisible', {
  3. enumerable: false,
  4. value: 'hello'
  5. })
  6. )
  7. // { b: 'c' }

上面代码中,Object.assign要拷贝的对象只有一个不可枚举属性invisible,这个属性并没有被拷贝进去。
属性名为 Symbol 值的属性,也会被Object.assign拷贝。

  1. Object.assign({ a: 'b' }, { [Symbol('c')]: 'd' })
  2. // { a: 'b', Symbol(c): 'd' }

2  注意点

Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。

  1. var obj1 = {a: {b: 1}};
  2. var obj2 = Object.assign({}, obj1);
  3. obj1.a.b = 2;
  4. obj2.a.b // 2

上面代码中,源对象obj1的a属性的值是一个对象,Object.assign拷贝得到的是这个对象的引用。这个对象的任何变化,都会反映到目标对象上面。

对于这种嵌套的对象,一旦遇到同名属性,Object.assign的处理方法是替换,而不是添加。

  1. var target = { a: { b: 'c', d: 'e' } }
  2. var source = { a: { b: 'hello' } }
  3. Object.assign(target, source)
  4. // { a: { b: 'hello' } }

上面代码中,target对象的a属性被source对象的a属性整个替换掉了,而不会得到{ a: { b: 'hello', d: 'e' } }的结果。这通常不是开发者想要的,需要特别小心。
有一些函数库提供Object.assign的定制版本(比如 Lodash 的_.defaultsDeep方法),可以解决浅拷贝的问题,得到深拷贝的合并。
注意,Object.assign可以用来处理数组,但是会把数组视为对象。

  1. Object.assign([1, 2, 3], [4, 5])
  2. // [4, 5, 3]

上面代码中,Object.assign把数组视为属性名为 0 、 1 、 2 的对象,因此目标数组的 0 号属性4覆盖了原数组的 0 号属性1。

3  常见用途

( 1 )为对象添加属性

  1. class Point {
  2. constructor(x, y) {
  3. Object.assign(this, {x, y});
  4. }
  5. }

上面方法通过Object.assign方法,将x属性和y属性添加到Point类的对象实例。

( 2 )为对象添加方法

  1. Object.assign(SomeClass.prototype, {
  2. someMethod(arg1, arg2) {
  3. ···
  4. },
  5. anotherMethod() {
  6. ···
  7. }
  8. });
  9. //  等同于下面的写法
  10. SomeClass.prototype.someMethod = function (arg1, arg2) {
  11. ···
  12. };
  13. SomeClass.prototype.anotherMethod = function () {
  14. ···
  15. };

上面代码使用了对象属性的简洁表示法,直接将两个函数放在大括号中,再使用 assign 方法添加到 SomeClass.prototype 之中。

( 3 )克隆对象

  1. function clone(origin) {
  2. return Object.assign({}, origin);
  3. }

上面代码将原始对象拷贝到一个空对象,就得到了原始对象的克隆。
不过,采用这种方法克隆,只能克隆原始对象自身的值,不能克隆它继承的值。如果想要保持继承链,可以采用下面的代码。

  1. function clone(origin) {
  2. let originProto = Object.getPrototypeOf(origin);
  3. return Object.assign(Object.create(originProto), origin);
  4. }

( 4 )合并多个对象

将多个对象合并到某个对象。

  1. const merge =(target, ...sources) => Object.assign(target, ...sources);

如果希望合并后返回一个新对象,可以改写上面函数,对一个空对象合并。

  1. const merge =(...sources) => Object.assign({}, ...sources);

( 5 )为属性指定默认值

  1. const DEFAULTS = {
  2. logLevel: 0,
  3. outputFormat: 'html'
  4. };
  5. function processContent(options) {
  6. let options = Object.assign({}, DEFAULTS, options);
  7. }

上面代码中,DEFAULTS对象是默认值,options对象是用户提供的参数。Object.assign方法将DEFAULTS和options合并成一个新对象,如果两者有同名属性,则option的属性值会覆盖DEFAULTS的属性值。
注意,由于存在深拷贝的问题,DEFAULTS对象和options对象的所有属性的值,都只能是简单类型,而不能指向另一个对象。否则,将导致DEFAULTS对象的该属性不起作用。

es6 javascript对象方法Object.assign()的更多相关文章

  1. es6 javascript对象方法Object.assign() 对象的合并复制等

    Object.assign方法用于对象的合并,将源对象( source )的所有可枚举属性,复制到目标对象( target ). 详细使用稳步到前辈: http://blog.csdn.net/qq_ ...

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

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

  3. ES6新增对象方法的访问描述符:get(只读)、set(只写)

    Es6新增对象方法的访问描述符:get(只读).set(只写),可以直接使用,一般用于数据监听,用途类似于vue.$watch. var obj = { a:1, get bar() { return ...

  4. ES6遍历对象方法

    ES6 一共有 5 种方法可以遍历对象的属性. (1)for...in for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性). let obj = {a:1,b:2,c:3 ...

  5. Javascript 对象(object)合并

    对象的合并 需求:设有对象 o1 ,o2,需要得到对象 o3 var o1 = { a:'a' }, o2 = { b:'b' }; // 则 var o3 = { a:'a', b:'b' } 方法 ...

  6. 对象浅拷贝Object.assign

    const target = { a: { b: { c: { d: 1 } }, e: 5, f: 6, h: 10 } } const source = { a: { b: { c: { d: 1 ...

  7. JavaScript深入理解对象方法——Object.entries()

    Object.entries()方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环也枚举原型链中的属性) 示例 ...

  8. Javascript 对象(Object)

    //声明方式 //调用 Object构造函数创建 var user = new Object(); user.name = "小白"; user.say = function () ...

  9. es6 Object.assign

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

随机推荐

  1. C#调整图片亮度和对比度

    BitmapSource bitmap = null; ; ; private void SetBrightness(int degree) { degree = degree * / ; Write ...

  2. 用C实现单隐层神经网络的训练和预测(手写BP算法)

    实验要求:•实现10以内的非负双精度浮点数加法,例如输入4.99和5.70,能够预测输出为10.69•使用Gprof测试代码热度 代码框架•随机初始化1000对数值在0~10之间的浮点数,保存在二维数 ...

  3. #2009. 「SCOI2015」小凸玩密室

    神仙题啊.完全想不出 首先看方案.可以从任意一个点开始,在这个点要先走完子树,然后走到父亲,再走兄弟,再走父亲的父亲,父亲的兄弟..一直走到1,1的另外一个子树,结束. 完全不会鸭.jpg 设f[i] ...

  4. idea 误删out目录中的文件导致开启服务器后无法访问页面的问题

    只需要把out目录整个删除掉,然后再重新开启服务器,服务器就会自动生成新的out目录 同理,target目录也是整个删除掉就能重新生成

  5. 简单字典实现(KV问题)

    搜索二叉树基本概念请看上篇博客 这两个问题都是典型的K(key)V(value)问题,我们用KV算法解决. 判断一个单词是否拼写正确:假设把所有单词都按照搜索树的性质插入到搜索二叉树中,我们判断一个单 ...

  6. Myeclipse提高运行速度的方法

    下文是在其他博客拷过来的,借鉴借鉴,留个笔记,哈哈 1.老是弹出Quick update error .关闭myeclipse的Quick Update自动更新功能这个问题的解决办法是关闭自动更新Wi ...

  7. mac指令备忘

    在这里简单记录下最近使用的快捷键,备忘,随时更新. 简单指令记录 mkdir 创建路径 pwd 输出当前路径 ls 查看目录 cd touch 创建文件 tree 输出目录树 mv 源文件 目标文件或 ...

  8. docker server gave HTTP response to HTTPS client 问题处理办法

    vi /etc/docker/daemon.json [root@localhost ~]# cat /etc/docker/daemon.json {"insecure-registrie ...

  9. Centos7 安装与破解 Confluence 6.7.1

    1.1硬件需求建议: CPU:32/64 bit 2.27GHz双核心以上之CPU: 内存:8GB以上: 硬盘:300GB,7200转以上: 建议数据库.Confluence等各自独立一台服务器(本测 ...

  10. Hyperledger Fabric CA User’s Guide——CA用户指南(一)

    Fabric CA用户指南 Hyperledger Fabric CA是一种用于Hyperledger Fabric的认证机构(CA). 它提供了如下特性: 登记身份(注册ID),或者连接到作为用户注 ...