[转]理解Object.assign

本节内容我们继续探讨关于ES2015的一些新的内容,Object.assign函数的使用,使用该函数我们可以快速的复制一个或者多个对象到目标对象中,本文内容涉及es6,es7相关的对象复制的内容,以及一些es5的替代方案的介绍。

函数原型

首先看一下函数的定义: 函数参数为一个目标对象(该对象作为最终的返回值),源对象(此处可以为任意多个)。通过调用该函数可以拷贝所有可被枚举的自有属性值到目标对象中。

Object.assign(target, ...sources)

这里我们需要强调的三点是:

  1. 可被枚举的属性
  2. 自有属性
  3. string或者Symbol类型是可以被直接分配的

拷贝过程中将调用源对象的getter方法,并在target对象上使用setter方法实现目标对象的拷贝。

函数实例

这里我们通过几个MDN上的例子来介绍一下使用方法:

实例一

我们参考上面的原型函数说明即可知道其最开始的o1因为设置为target,则调用其setter方法设置了其他对象的属性到自身。

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 }, target object itself is changed.

实例二

我们自定义了一些对象,这些对象有一些包含了不可枚举的属性,另外注意使用 Object.defineProperty 初始化的对象默认是不可枚举的属性。对于可枚举的对象我们可以直接使用Object.keys()获得,或者使用for-in循环遍历出来.

对于不可枚举的属性,使用Object.assign的时候将被自动忽略。

var obj = Object.create({ foo: 1 }, { // foo is an inherit property.
  bar: {
    value: 2  // bar is a non-enumerable property.
  },
  baz: {
    value: 3,
    enumerable: true  // baz is an own enumerable property.
  }
});

var copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }  

实例三

对于只读的属性,当分配新的对象覆盖他的时候,将抛出异常:

var target = Object.defineProperty({}, ‘foo‘, {
  value: 1,
  writable: false
}); 

Object.assign(target, { bar: 2 })

//{bar: 2, foo: 1}

Object.assign(target, { foo: 2 })
//Uncaught TypeError: Cannot assign to read only property ‘foo‘ of object ‘#<Object>‘(…)

Polyfill

这里我们简单的看下如何实现es5版本的Object.assign:

实现步骤:

  1. 判断是否原生支持该函数,如果不存在的话创建一个立即执行函数,该函数将创建一个assign函数绑定到Object上。
  2. 判断参数是否正确(目的对象不能为空,我们可以直接设置{}传递进去,但必须设置该值)
  3. 使用Object在原有的对象基础上返回该对象,并保存为out
  4. 使用for…in循环遍历出所有的可枚举的自有对象。并复制给新的目标对象(hasOwnProperty返回非原型链上的属性)

源码如下:

 if (typeof Object.assign != ‘function‘) {
  (function () {
	Object.assign = function (target) {
	 ‘use strict‘;
	 if (target === undefined || target === null) {
	   throw new TypeError(‘Cannot convert undefined or null to object‘);
	 }

	 var output = Object(target);
	 for (var index = 1; index < arguments.length; index++) {
	   var source = arguments[index];
	   if (source !== undefined && source !== null) {
	     for (var nextKey in source) {
	       if (source.hasOwnProperty(nextKey)) {
	         output[nextKey] = source[nextKey];
	       }
	     }
	   }
	 }
	 return output;
	};
})();
}

扩展内容

1.深度复制

当我们调用下面的函数的时候,由于Object.assign将覆盖之前的内容,所以并不能完全的做到融合对象,而是全部替换掉,所以返回的对象内容将变成最后一个值; {a: {c: 3}

Object.assign({a: {b: 0}}, {a: {b: 1, c: 2}}, {a: {c: 3}});

如何深层次的融合对象,比如我们期望的输出结果为:

{a:{b:1,c:3}}

这样我们必须实现自己的算法来完成深层复制了,不过github上已经有很多好的解决方案,比如deep-merge 通过递归的方式逐层的去调用assign函数。

2.ES2016实现

在es7中我们使用rest属性可以捕获所有剩余的对象内容比如下面的例子(可使用babel-repl页面测试,浏览器一般尚未支持):

let { fname, lname, ...rest } = { fname: "Hemanth", lname: "HM", location: "Earth", type: "Human" };
fname; //"Hemanth"
lname; //"HM"
rest; // {location: "Earth", type: "Human"}

这样我们就可以使用该特性来实现assign函数

let oldObj1={a:"a",b:{b1:"b1"}}
let oldObj2={a:"a1",b:{b2:"b2"},c:"c"}

let newObject={...oldObj1,...oldObj2};
console.log(newObject)

{"a":"a1","b":{"b2":"b2"},"c":"c"}

不过仍旧只是浅层的替换,并没有实现深层次的合并。

原文地址: https://cnodejs.org/topic/56c49662db16d3343df34b13

时间: 2024-12-19 16:57:26

[转]理解Object.assign的相关文章

一个 Object.assign 的误解

mozilla中对 Object.assign 的解释如下地址: mozilla 其中有说到 注意, Object.assign 会跳过那些值为 null 或 undefined 的源对象. 一直以为是对象中如果是null 或者 undefined ,那么会不进行覆盖, 但是测试结果却是覆盖. 很是疑惑. 经询问以及查找, 发现是如下的例子,才不会进行覆盖 Object.assign({obj1: "objvalue"}, null); Object.assign({obj1: &qu

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 如果目标对象与源对象有同名属性,或多个源对象有同名

Object.assign()

Object.assign() 方法用于将所有可枚举的属性的值从一个或多个源对象复制到目标对象.它将返回目标对象. 语法 Object.assign(target, ...sources) 参数 target 目标对象. sources (多个)源对象. 返回值 目标对象. 描述 如果目标对象中的属性具有相同的键,则属性将被源中的属性覆盖.后来的源的属性将类似地覆盖早先的属性. Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象身上.该方法使用源对象的 [ [ Get

[ES6] Object.assign (with defaults value object)

function spinner(target, options = {}){ let defaults = { message: "Please wait", spinningSpeed: 5, cssClass: ".is-spinning" }; let settings = Object.assign( {}, defaults, options ); if(settings.spinningSpeed !== defaults.spinningSpeed)

Object.assign()方法

转载:http://www.cnblogs.com/zhaowenxin/p/6160676.html 对象的扩展 1.ES6中,对象的属性和方法可简写:对象的属性值可不写,前提是属性名已经声明: 1 var name = "zhangsan"; 2 var password = "1111111"; 3 var obj = { 4 name, 5 password, 6 arr:[1,2,3,4], 7 sayName(){ 8 console.log(this.

javascript:理解Object

Object对象的类型是Object,Object的原始值是什么?需要用constructor的prototype,constructor的意思就是这个函数有一个默认的属性prototype,而这个prototype.valueof的constructor默认指向这个函数原始值.Object.constructor.valueof()可以输出Object的原始值,输出为Function Function(){[native code]}.不过现在的浏览器可以直接输出原始值alert(Object

js 合并多个对象 Object.assign

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象.它将返回目标对象. 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 }, 注意目标对象自身也会改变.

ES6对象方法Object.assign()

1  基本用法 Object.assign方法用于对象的合并,将源对象( source )的所有可枚举属性,复制到目标对象( target ). [javascript] view plain copy var target = { a: 1 }; var source1 = { b: 2 }; var source2 = { c: 3 }; Object.assign(target, source1, source2); target // {a:1, b:2, c:3} Object.ass

Object.assign() 从一个或多个源对象复制到目标对象

Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象.它将返回目标对象. 1.语法: Object.assign(target, ... , sources) 参数: ① target:目标对象 ② sources:源对象 返回值: 目标对象 2.示例: ① 复制一个对象 var obj = { a: 1 }; var copy = Object.assign({},obj); console.log(copy); 注意:该方法还有许多用处,待完善- 原文地