JS 对象合并与克隆方法的分类与比较
来源:互联网 发布:sql中别名 编辑:程序博客网 时间:2024/05/21 09:52
对象的合并与拷贝(又称复制或克隆)是前端们平时工作中绕不开的基本操作,使用场景非常多。也许你已经有了自己用惯了的工具方法,但是对于这个话题,你确定自己已经完全了解了吗?
合并与克隆的关系
拷贝可以认为是一种特殊情况下的合并:将一个空对象 {}
作为目标,与一个非空对象合并。
constructor
相同,一个 Person
类的实例被拷贝后应该还是一个 Person
,不能变成 Dog
,更不能变成一个不知道是什么东西的 Object
。此外,合并和拷贝在方法调用上也有差别。合并一般要求支持多个源对象向目标对象合并,而拷贝的源对象只有一个。
常见的合并与拷贝的方法
JSON.parse(JSON.stringify() )
来实现对象复制。ES5 中增加了原生的 Object.assign
来实现合并。而利用 ES6 中的扩展运算符,调用形如 {…x, …y}
的声明,也能实现对象的合并。除了这些原生的合并拷贝方法,我还找了jQuery@3.2.1,underscore@1.8.3,lodash@4.16.1
三个大名鼎鼎库中的相关方法。我们接下来将以他们作为例子,详细从合并与拷贝方法的各个维度上来分析。
说明:jQuery.extend
方法有很多调用方式,既可以拷贝又可以合并,所以在两个列表中都出现。另外,lodash
和 underscore
都使用下划线_,这里根据“先来后到”的顺序,用 _ 指代underscore
,用 l 指代 lodash
。
JSON.parse(JSON.stringify())
$.extend
_.clone
l.clone
l.cloneDeep
l.cloneWith
l.cloneDeepWith
{…x, …y}
Object.assign
$.extend
_.extend
_.extendOwn
l.assign
l.assignIn
l.assignWith
l.assignInWith
l.merge
l.mergeWith
拷贝方法分析
对于依赖 JSON 来拷贝对象的 JSON.parse(JSON.stringify())
方法来说,undefined
和 function
类型的属性会被忽略,而 Date
类型的属性则会被转换为字符串,这可能不是我们想要的。
2.是否能够正确处理 constructor?
Person
不能变为 Dog
,也不能变为 Object
。目标对象应该保留源对象的 constructor
。3.是否是深拷贝?
4.是否支持 customizer?
customizer
是指一个处理方法,允许用户定制拷贝中的处理过程,其作用类似 Array
系列方法中的遍历处理函数。一开始我也没想到这个维度,还是在研究 lodash
相关方法的时候才看到的。不得不说,这是一个很有用的特性。
function customizer(value) { if (_.isElement(value)) { return value.cloneNode(false); }}var el = _.cloneWith(document.body, customizer);
underscore
的clone
方法不支持深拷贝,比较弱。jquery
的extend
方法默认不使用深拷贝,但当第一个参数传入 true 时则使用深拷贝来处理。- lodash 提供了4个
clone
相关方法。只有 lodash 的 clone 方法正确处理了constructor
,而customizer
也只有lodash
一家独有(两个with 方法)。
合并方法分析:
1.原型属性是否参与合并?
原型属性参与合并时,源对象原型上的属性会被作为目标对象上的普通属性。如:
function Foo() { this.a = 1;}Foo.prototype.b = 2;let x = new Foo();assign({}, x);// {a: 1, b: 2}
字面意思。值 为undefined 的属性是否参与合并。
3.是否递归合并?
首先确认一点,所有的合并操作都不会是“浅”的,都不会直接把引用地址赋给目标对象。但在此基础上,又有不同的合并策略。比如:
let x = {a: {m: 1, n: 2}};let y = {a: {m: 2, o: 3}};assign(x ,y);// 非递归合并// {a: {m: 2, o: 3}}// 递归合并// {a: {m: 2 , n: 2, o: 3}}
4.是否支持 customizer?
- 原生方法中使用
Object.assign
方法和使用扩展操作符完全一样。 - 除了lodash 的
merge
,其余方法都不支持递归合并。 - 除了lodash 的
merge
,其余方法undefined
都参与合并。 - 除了lodash 的三个
with
方法,其余方法都不支持customizer
。
根据上面的两张表,读者可以自行选择合适的合并与拷贝方法了。如果有其他方法,也可以用这些维度来进行分析。
- JS 对象合并与克隆方法的分类与比较
- JS对象简单、深度克隆(赋值与引用的区别)
- JS对象简单、深度克隆(赋值与引用的区别)
- JS克隆对象方法
- 克隆JS对象的三个实用方法
- 克隆JS对象的三个实用方法
- 克隆JS对象的三个实用方法
- js中数组与数组,数组与对象,对象与对象间的合并
- js对象的克隆
- 44、对象的深克隆与浅克隆
- java基础入门-对象的浅克隆与深克隆
- 44、对象的深克隆与浅克隆
- java对象的深克隆与浅克隆
- [Java]对象的深克隆与浅克隆
- 序列化与对象的克隆
- JS 对象克隆方法总结
- JAVA对象深克隆与浅克隆
- 十三、文件的合并与分类
- Java 基础(10)—— static
- 友盟分享步骤&
- ActiveMQ+Spring项目实践
- Java读取文件内容和写入内容到文件
- Blueprint__蓝本
- JS 对象合并与克隆方法的分类与比较
- vuejs在服务器部署
- 机器学习第3章第7节 : 图片的平铺效果
- 分布式架构的演进
- 设计模式之一----单例模式
- 解决:Adobe crobat 9重复吊销序列号的问题
- tensorflow的tf.in_top_k()错误
- 无 Flash 时代,让直播拥抱 H5
- Material Design动画