[转]理解Object.assign
本节内容我们继续探讨关于ES2015的一些新的内容,Object.assign函数的使用,使用该函数我们可以快速的复制一个或者多个对象到目标对象中,本文内容涉及es6,es7相关的对象复制的内容,以及一些es5的替代方案的介绍。
函数原型
首先看一下函数的定义: 函数参数为一个目标对象(该对象作为最终的返回值),源对象(此处可以为任意多个)。通过调用该函数可以拷贝所有可被枚举的自有属性值到目标对象中。
Object.assign(target, ...sources)
这里我们需要强调的三点是:
- 可被枚举的属性
- 自有属性
- 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:
实现步骤:
- 判断是否原生支持该函数,如果不存在的话创建一个立即执行函数,该函数将创建一个assign函数绑定到Object上。
- 判断参数是否正确(目的对象不能为空,我们可以直接设置{}传递进去,但必须设置该值)
- 使用Object在原有的对象基础上返回该对象,并保存为out
- 使用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
[转]理解Object.assign的更多相关文章
- javascript系列--Object.assign实现浅拷贝的原理以及实现
一.前言 之前在前面一篇学习了赋值,浅拷贝和深拷贝.介绍了这三者的相关知识和区别. 传送门:https://www.mwcxs.top/page/592.html 本文会介绍浅拷贝Object.ass ...
- 【JS】307- 复习 Object.assign 原理及其实现
点击上方"前端自习课"关注,学习起来~ }let b = { name: "muyiy", book: { title: " ...
- JavaScript 复制对象【Object.assign方法无法实现深复制】
在JavaScript这门语言中,数据类型分为两大类:基本数据类型和复杂数据类型.基本数据类型包括Number.Boolean.String.Null.String.Symbol(ES6 新增),而复 ...
- es6 Object.assign ECMAScript 6 笔记(六) ECMAScript 6 笔记(一) react入门——慕课网笔记 jquery中动态新增的元素节点无法触发事件解决办法 响应式图像 弹窗细节 微信浏览器——返回操作 Float 的那些事 Flex布局 HTML5 data-* 自定义属性 参数传递的四种形式
es6 Object.assign 目录 一.基本用法 二.用途 1. 为对象添加属性 2. 为对象添加方法 3. 克隆对象 4. 合并多个对象 5. 为属性指定默认值 三.浏览器支持 ES6 O ...
- 一个 Object.assign 的误解
mozilla中对 Object.assign 的解释如下地址: mozilla 其中有说到 注意, Object.assign 会跳过那些值为 null 或 undefined 的源对象. 一直以为 ...
- Object.assign方法复制或合并对象
Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象 var obj = { a: 1 }; var copy = Object.assign({ ...
- Object.assign()方法
对象的扩展 1.ES6中,对象的属性和方法可简写:对象的属性值可不写,前提是属性名已经声明: var name = "zhangsan"; "; var obj = { ...
- 微信不支持Object.assign
微信不支持Object.assign,让我Vue怎么用QAQ... 解决方法: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Refe ...
- object.assign()方法的使用
地址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
随机推荐
- 获取html元素所在页面的坐标
function findPosition(oElement) { var x2 = 0; var y2 = 0; var width = oElement.offsetWidth; var heig ...
- php5.4新特性实践
本机安装的是wampserver2.2e-php5.4.3-httpd2.2.22-mysql5.5.24-32b.exe集成包 自带了php5.4 1. 数组写法 定义一个数组 过去: $arr = ...
- E QUERY [main] SyntaxError: identifier starts immediately after numeric literal mongodb mapReduce 异常分析 集合命名规范
异常信息 repl_test:PRIMARY> db.0917order_totals_b.find()2018-09-28T15:13:03.992+0800 E QUERY [main] S ...
- 费马小定理 Fermat Theory
w 整数的质数次方和自身的差是是质数的倍数 费马小定理(Fermat Theory)是数论中的一个重要定理,其内容为: 假如p是质数,且Gcd(a,p)=1,那么 a(p-1)≡1(mod p).即: ...
- 设置请求timeout超时
import requests r = requests.get("http://www.cnblogs.com/yoyoketang/", timeout=1) # 设置超时 p ...
- JavaWeb—拦截器Interceptor
1.概念 java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止其执行,同时也提供了一种可以提取A ...
- solrcloud配置步骤
SolrCloud是Solr4.0版本以后基于Solr和Zookeeper的分布式搜索方案.SolrCloud是Solr的基于Zookeeper一种部署方式. 版本信息:solr版本6.2.0+tom ...
- SQL模糊查找
编辑器加载中... /*********************实现模糊查找**************************/ SELECT [UserId] ,[UserName] ,[User ...
- Struts2笔记02——Struts2 概述(转)
原始内容:https://www.tutorialspoint.com/struts_2/basic_mvc_architecture.htm Struts2是基于MVC设计模式的一种流行.成熟的We ...
- DNS 递归/迭代 原理
递归查询 递归:客户端只发一次请求,要求对方给出最终结果.一般客户机和服务器之间属递归查询,即当客户机向DNS服务器发出请求后,若DNS服务器本身不能解析,则会向另外的DNS服务器发出查询请求,得到结 ...