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. ORACLE动态监听

    动态监听的原理 pmon在数据库启动到mount或open时,动态从参数文件中读取service_names值.service_names可以为多值(可以有64个,其中包括两个系统的).  servi ...

  2. 手动配置 ESXi 主机挂载 NFS 的最大值

    目录 目录 资料 手动配置 ESXi 主机挂载 NFS 的最大值 资料 官方 KB 地址 手动配置 ESXi 主机挂载 NFS 的最大值 Open: 清单 ==> ESXi 主机 ==> ...

  3. 阶段1 语言基础+高级_1-3-Java语言高级_04-集合_01 Collection集合_7_增强for循环

    collections实现了interable接口.实现了interable接口就可以使用Foreach int i是临时 变量

  4. 写Rust的感觉

    以前写代码,像是学会了语言规则,可以在不违反规则的情况下,随便使用特性,这个世界就是你的了. 写Rust,就像是一个法律文本,编译器像是一个法官. 你只能在法律容许的情况下,做事情,更法官很严格,在编 ...

  5. 接口自动化之ddt

    接口自动化会用到数据驱动模式,也就是一个ddt模块 目录 1.环境准备 2.调用时标准格式 3.应用(结合excle来传值) 1.环境准备 首先,需要安装ddt模块 pip install ddt 2 ...

  6. 分布式 vs 集群 主从 vs 集群

      理解 分布式 一个业务拆分成多个子业务,部署在不同的服务器上 集群 同一个业务部署在多个服务器上   更新 主从 服务器之间更新是异步的,从服务器可能和主服务器不一致 集群 更新是同步的,数据节点 ...

  7. ZOJ-1610 线段树+两种查询方法(弥补我线段树区间填充的短板)

    ZOJ-1610 线段树+两种查询方法(弥补我线段树区间填充的短板) 题意 题意:给一个n,代表n次操作,接下来每次操作表示把[l,r]区间的线段涂成k的颜色其中,l,r,k的范围都是0到8000 这 ...

  8. HTML+CSS ,原型

    此图是别人所作

  9. vue 跳转页面返回时tab状态有误的解决办法

    一.前言 最近在做新vue项目的时候遇到了一个问题,就是tab间的切换没有问题,当跳转到其他页面时,且这个页面并非子路由,再用浏览器的返回按钮返回首页时,tab的active始终指向默认的第一个选项. ...

  10. 利用js使图片外层盒子的高等于适应图片的高

    JS代码如下:<script> $(window).load(function(){ var width=$(window).width(); var img_1=$(".hot ...