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

语法:

Object.assign(target, ...sources)
参数 target
目标对象。
sources
源对象。

返回值

目标对象。

描述

如果目标对象中的属性具有相同的键,则属性将被源中的属性覆盖。后来的源的属性将类似地覆盖早先的属性。

Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象。该方法使用源对象的[[Get]]和目标对象的[[Set]],所以它会调用相关 getter 和 setter。因此,它分配属性,而不仅仅是复制或定义新的属性。如果合并源包含getter,这可能使其不适合将新属性合并到原型中。为了将属性定义(包括其可枚举性)复制到原型,应使用Object.getOwnPropertyDescriptor()Object.defineProperty() 。

String类型和 Symbol 类型的属性都会被拷贝。

在出现错误的情况下,例如,如果属性不可写,会引发TypeError,如果在引发错误之前添加了任何属性,则可以更改target对象。

注意,Object.assign 不会跳过那些值为 null 或 undefined 的源对象。

示例:
var obj = { a: 1 };
var copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
function test() {
'use strict'; let obj1 = { a: 0 , b: { c: 0}};
let obj2 = Object.assign({}, obj1);
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}} obj1.a = 1;
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}} obj2.a = 2;
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 0}} obj2.b.c = 3;
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}}
console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}} // Deep Clone
obj1 = { a: 0 , b: { c: 0}};
let obj3 = JSON.parse(JSON.stringify(obj1));
obj1.a = 4;
obj1.b.c = 4;
console.log(JSON.stringify(obj3)); // { a: 0, b: { c: 0}}
} test();

合并对象

var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 }; var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }, 注意目标对象自身也会改变。

合并具有相同属性的对象

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

属性被后续参数中具有相同属性的其他对象覆盖。

拷贝 symbol 类型的属性

var o1 = { a: 1 };
var o2 = { [Symbol('foo')]: 2 }; var obj = Object.assign({}, o1, o2);
console.log(obj); // { a : 1, [Symbol("foo")]: 2 } (cf. bug 1207182 on Firefox)
Object.getOwnPropertySymbols(obj); // [Symbol(foo)]

继承属性和不可枚举属性是不能拷贝的

var obj = Object.create({foo: 1}, { // foo 是个继承属性。
bar: {
value: 2 // bar 是个不可枚举属性。
},
baz: {
value: 3,
enumerable: true // baz 是个自身可枚举属性。
}
}); var copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }

原始类型会被包装为对象

var v1 = "abc";
var v2 = true;
var v3 = 10;
var v4 = Symbol("foo") var obj = Object.assign({}, v1, null, v2, undefined, v3, v4);
// 原始类型会被包装,null 和 undefined 会被忽略。
// 注意,只有字符串的包装对象才可能有自身可枚举属性。
console.log(obj); // { "0": "a", "1": "b", "2": "c" }

异常会打断后续拷贝任务

var target = Object.defineProperty({}, "foo", {
value: 1,
writable: false
}); // target 的 foo 属性是个只读属性。 Object.assign(target, {bar: 2}, {foo2: 3, foo: 3, foo3: 3}, {baz: 4});
// TypeError: "foo" is read-only
// 注意这个异常是在拷贝第二个源对象的第二个属性时发生的。 console.log(target.bar); // 2,说明第一个源对象拷贝成功了。
console.log(target.foo2); // 3,说明第二个源对象的第一个属性也拷贝成功了。
console.log(target.foo); // 1,只读属性不能被覆盖,所以第二个源对象的第二个属性拷贝失败了。
console.log(target.foo3); // undefined,异常之后 assign 方法就退出了,第三个属性是不会被拷贝到的。
console.log(target.baz); // undefined,第三个源对象更是不会被拷贝到的。

拷贝访问器

var obj = {
foo: 1,
get bar() {
return 2;
}
}; var copy = Object.assign({}, obj);
// { foo: 1, bar: 2 }
// copy.bar的值来自obj.bar的getter函数的返回值
console.log(copy); // 下面这个函数会拷贝所有自有属性的属性描述符
function completeAssign(target, ...sources) {
sources.forEach(source => {
let descriptors = Object.keys(source).reduce((descriptors, key) => {
descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
return descriptors;
}, {}); // Object.assign 默认也会拷贝可枚举的Symbols
Object.getOwnPropertySymbols(source).forEach(sym => {
let descriptor = Object.getOwnPropertyDescriptor(source, sym);
if (descriptor.enumerable) {
descriptors[sym] = descriptor;
}
});
Object.defineProperties(target, descriptors);
});
return target;
} var copy = completeAssign({}, obj);
console.log(copy);
// { foo:1, get bar() { return 2 } }

Polyfill

polyfill不支持 symbol 属性,因为ES5 中根本没有 symbol :

if (typeof Object.assign != 'function') {
// Must be writable: true, enumerable: false, configurable: true
Object.defineProperty(Object, "assign", {
value: function assign(target, varArgs) { // .length of function is 2
'use strict';
if (target == null) { // TypeError if undefined or null
throw new TypeError('Cannot convert undefined or null to object');
} var to = Object(target); for (var index = 1; index < arguments.length; index++) {
var nextSource = arguments[index]; if (nextSource != null) { // Skip over if undefined or null
for (var nextKey in nextSource) {
// Avoid bugs when hasOwnProperty is shadowed
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
to[nextKey] = nextSource[nextKey];
}
}
}
}
return to;
},
writable: true,
configurable: true
});
}

												

js把两个对象合并成一个对象的更多相关文章

  1. 把两个object对象合并成一个对象 属性名称相同的变为后面对象的值

    object.assign(from,obj)------object.assign(目标对象,被合并的对象)

  2. ES6将两个数组合并成一个对象数组

    需求 有这么两个数组 let metrodates = [ "2008-01", "2008-02", "2008-03",..ect ]; ...

  3. js中两个对象的比较

    代码取自于underscore.js 1.8.3的isEqual函数. 做了一些小小的修改,主要是Function的比较修改. 自己也加了一些代码解读. <!DOCTYPE html> & ...

  4. Clojure:将两个list合并成一个map

    假设我们有两个list,分别是: (def a [“one” “two” “three”]) (def b [1 2 3]) 我们要把它们合为一个键值对应的map,做法很简单: 1. 先将a和b合为一 ...

  5. js 实现 多层级对象合并

    js 实现 多层级对象合并 首先 需求是使用js对数据的格式进行转换 把一个二维数组(包含层级信息,层级数是不固定的)list 转换为多层级的对象 我的思路就是 循环先把list里单条信息转换为 多层 ...

  6. js 判断两个对象是否相等

    最近碰到的一个面试题,不算高频,记录一下 判断两个对象是否相等,大致分为三步 首先判断两个比较对象是不是 Object 如果都是对象 再比较 对象的长度是否相等 如果两个对象的长度相等 再比较对象属性 ...

  7. 将两个DataTable合并成一个DataTable

    转载自 http://blog.csdn.net/wangxiaojia42121/article/details/53330464 谢谢 //两个结构一样的DT合并DataTable DataTab ...

  8. 两个list合并成一个list的操作

    addAll  添加另一集合里面的元素 add 添加整个集合包括 [] Stream 操作 合并两个lis  出自http://www.it1352.com/963663.html public cl ...

  9. 关于比较js中两个对象相等 ==

    “如果两个操作数都是对象,则比较他们是不是同一个对象(引用的对象在内存中的地址一样),如果两个操作数都指向同一个对象,则相等操作符返回true,否则,返回false”. 我做了一个例子 functio ...

随机推荐

  1. fedora23然后创建workspace?或者说是panel面板?

    好像在fedora23中 无法再添加工作空间workspace. 系统会自动的在非空工作空间后面再生成一个空的工作空间. 而且 工作空间 好像不只 4个, 可以有很多个. panel面板好像也不能添加 ...

  2. Maven的一些常用命令

    将本项目的源码部署到本地仓库 mvn clean source:jar install 将本地jar包部署到本地仓库,首先将jar包放在当前目录下,然后执行,这样做比直接把jar包copy到本地仓库更 ...

  3. Python 笔试集:什么时候 i = i + 1 并不等于 i += 1?

    ​​增强型赋值语句是经常被使用到的,因为从各种学习渠道中,我们能够得知 i += 1 的效率往往要比 i = i + 1 更高一些(这里以 += 为例,实际上增强型赋值语句不仅限于此).所以我们会乐此 ...

  4. Jmeter之CSV Data Set Config

    在很多情况下,需要针对测试数据做参数化操作,Jmeter提供了很好用的CSV Data Set Config插件. 一.界面显示 二.界面说明 1.名称:标识,建议设置为该组件是提供什么功能 2.注释 ...

  5. 【HANA系列】SAP HANA 1.0 SPS 11 新特性

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA 1.0 SPS ...

  6. 【MM系列】SAP MM模块-库存盘点BAPI的使用及注意点

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP MM模块-库存盘点BAPI的 ...

  7. 阅读笔记09-Java程序员必备的Intellij插件

    1. .ignore 生成各种ignore文件,一键创建git ignore文件的模板,免得自己去写 地址:plugins.jetbrains.com/plugin/7495--ignore 2. l ...

  8. 应用安全 - 软件漏洞 - Jira漏洞汇总

    CVE-2019-8451 ssrf url = url + '/plugins/servlet/gadgets/makeRequest?url=' + host + '@www.baidu.com/ ...

  9. CEPH集群搭建(CentOS 7)

    以包含四个节点的集群为例,其中包括一个 ceph-deploy 管理节点和一个三节点的Ceph存储集群. 下图中每个节点代表一台机器. 创建一个 Ceph 存储集群,它有一个 Monitor 和两个 ...

  10. [Python3 填坑] 012 字典的遍历在 Python2 与 Python3 中区别

    目录 1. print( 坑的信息 ) 2. 开始填坑 2.1 Python2 中字典的遍历 2.2 Python3 中字典的遍历 2.3 结论 1. print( 坑的信息 ) 挖坑时间:2019/ ...