Lodash 中 assign,extend 和 merge 的区别

转载 2016年08月22日 12:39:16

简介

我们经常在别人的代码中看见 assignextendmerge 函数,这三个函数用起来很相似,都是合并源对象的属性到目标对象中。

既然都是合并对象,为什么还分三个不同的函数呢?它们之间到底有什么区别呢?

assign(object, [sources])

我们先看看官方网站上面的定义:

Assigns own enumerable string keyed properties of source objects to the destination object. Source objects are applied from left to right. Subsequent sources overwrite property assignments of previous sources.

把源对象(sources)的属性分配到目标对象(object),源对象会从左往右地调用,后面对象的属性会覆盖前面的。

看看下面的例子:

assign({}, { a: 1 }, { b: 2 });
// { a: 1, b: 2 }
// 后面的 { a: 2 } 把前面的 { a: 1 } 覆盖了
assign({}, { a: 1 }, { b: 2 }, { a: 2 });
// { a: 2, b: 2 }
// 观察下面两个例子,如果属性值为 object,后面的值会覆盖前面的值
assign(
{},
{ a: 1 },
{ b: { c: 2, d: 3 } }
)
// { a: 1, b: { c: 2, d: 3 } }
assign(
{},
{ a: 1 },
{ b: { c: 2, d: 3 } },
{ b: { e: 4 } }
)
// { a: 1, b: { e: 4 } }
// `assign` 函数会忽略原型链上的属性。
function Foo() { this.c = 3; }
Foo.prototype.d = 4;
assign({ a: 1 }, new Foo());
// { a: 1, c: 3 }
// `assign` 会修改原来的对象
var test = { a: 1 };
assign(test, { b: 2 }); // { a: 1, b: 2 }
console.log(test); // { a: 1, b: 2 }

extend(object, [sources])

在 3.x 版本中,extend 是 assign 的别名,它们的作用是一模一样的。
在 4.x 版本中,extend 是 assignIn 的别名,和 assign 有点区别。

官方定义如下:

This method is like _.assign except that it iterates over own and inherited source properties.

在上面的例子中,我们知道 assign 函数不会把原型链上的属性合并到目标对象,而 extend 或 assignIn 函数则会!

// Important !! this is Lodash 4.x !!
// 把源对象原型链上的属性也合并到目标对象上!
function Foo() { this.c = 3; }
Foo.prototype.d = 4;
extend({ a: 1 }, new Foo());
// { a: 1, c: 3, d: 4 }

merge(object, [sources])

我们看看 merge 函数的定义:

This method is like _.assign except that it recursively merges own and inherited enumerable string keyed properties of source objects into the destination object. Source properties that resolve to undefined are skipped if a destination value exists. Array and plain object properties are merged recursively.Other objects and value types are overridden by assignment. Source objects are applied from left to right. Subsequent sources overwrite property assignments of previous sources.

merge 也和 assign 类似,不同的地方在于 merge 遇到相同属性的时候,如果属性值为纯对象(plain object)或者集合(collection)时,不是用后面的属性值去覆盖前面的属性值,而是会把前后两个属性值合并。
如果源对象的属性值为 undefined,则会忽略该属性。

assign(
{},
{ a: 1 },
{ b: { c: 2, d: 3} },
{ b: { e: 4 } }
)
// { a: 1, b: { e: 4 } }
merge(
{},
{ a: 1 },
{ b: { c: 2, d: 3} },
{ b: { e: 4 } }
)
// { a: 1, b: { c: 2, d: 3, e: 4 } }
// 合并集合
var users = {
'data': [{ 'user': 'barney' }, { 'user': 'fred' }]
};
var ages = {
'data': [{ 'age': 36 }, { 'age': 40 }]
};
merge({}, users, ages)
// { data: [ { user: 'barney', age: 36 }, { user: 'fred', age: 40 } ] }
// merge 函数会修改原来的对象!
merge(users, ages)
console.log(users) // { data: [ { user: 'barney', age: 36 }, { user: 'fred', age: 40 } ]

总结

相同之处

  • 都可以用来合并对象
  • 都会修改原来的对象 (如果原来的对象是作为函数的第一个参数的话)

不同之处

  • assign 函数不会处理原型链上的属性,也不会合并相同的属性,而是用后面的属性值覆盖前面的属性值

  • extend

    • 3.x 版本中和 assign 一样
    • 4.x 版本中会合并原型链上的属性
  • merge 遇到相同属性名的时候,如果属性值是纯对象或集合的时候,会合并属性值

参考资料

https://lodash.com/docs
http://stackoverflow.com/questions/19965844/lodash-difference-between-extend-assign-and-merge

原文链接:https://scarletsky.github.io/2016/04/02/assign-vs-extend-vs-merge-in-lodash/

nodejs通过lodash合并去重由unixtime和Date组成的两个数组

1. 问题起源 最近在实现一个API,其中有一部分功能是需要从Mongodb中取出一个由Date对象组成的数组,然后将客户端传过来的unixtime合并到该数组中,并且去重复。 比如,假设从m...
  • zhubaitian
  • zhubaitian
  • 2017年04月28日 13:32
  • 2218

lodash的2个数组对象操作

根据数组对象 下的属性名称 来返回相应 的值数据格式如下var data=[{test1:[...]},{test2:[...]},{test3:[...]},{test4:[...]},{test5...
  • dcsky185
  • dcsky185
  • 2016年04月21日 21:14
  • 3692

lodash 中文学习拾零之 Object篇

作者:Soaring_Tiger 转载请注明出处 http://blog.csdn.net/Soaring_Tiger前情提要1 : lodash中文学习拾零之Array篇 前情提要2:lodash...
  • Soaring_Tiger
  • Soaring_Tiger
  • 2015年09月05日 22:13
  • 3022

js obj合并 添加 移除 Object.assign $.extend splice

var a={"楼盘":"","交易类型":"","数据类型":"","期间":"","成交时间":""}var b={"姓名":"","工号":"","companyName":"","统计时间":...
  • q3585914
  • q3585914
  • 2017年04月28日 17:24
  • 1826

deepClone, extend, 深克隆对象和Object.assign(ES6)

在看 you might not need jQuery的时候,看到了$.extend函数来拷贝某个对象。测试了一下原文代码,居然复制不到深层的。原代码如下:var deepExtend = func...
  • github_36487770
  • github_36487770
  • 2017年10月27日 14:28
  • 195

详解js中extend函数

为了简化类的声明,可以把派生子类的整个过程包装在一个extend的函数,和其他语言中的extend关键字类似,基于一个给定的类结构创建一个新的类 function extend(subClass,...
  • sysuzhyupeng
  • sysuzhyupeng
  • 2017年02月03日 14:54
  • 471

merge javascript Object

/**merge javascript Object*/ function mergeObj(obj1,obj2){   for(var key in obj2){   obj1[key]=ob...
  • hety119
  • hety119
  • 2015年07月16日 15:47
  • 615

Lodash 中 assign,extend 和 merge 的区别

简介 我们经常在别人的代码中看见 assign,extend,merge 函数,这三个函数用起来很相似,都是合并源对象的属性到目标对象中。 既然都是合并对象,为什么还分三个不同的函数呢?它...
  • u011153667
  • u011153667
  • 2016年08月22日 12:39
  • 1801

Lodash中十个常用的工具函数

当你使用JavaScript进行编程的时候,你很可能需要经常重复写一些工具函数,尤其是处理字符串和对象。 即使ES6已经被标准化了,JavaScript开发者依然无法获得像Objective-C或Ru...
  • Qianliwind
  • Qianliwind
  • 2017年03月16日 23:37
  • 239

Python中append和+以及extend的区别

当我我们在使用List的扩展操作时候,常常会用到append方法和+运算符,不注意他们之间的区别常常会导致错误,下面举例说明他们的错误 1)append: s1 = [1,2,3] s2 ...
  • dpengwang
  • dpengwang
  • 2018年01月19日 07:47
  • 49
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Lodash 中 assign,extend 和 merge 的区别
举报原因:
原因补充:

(最多只允许输入30个字)