35

有没有办法获得 Underscore.jsextend功能:

将源对象中的所有属性复制到目标对象,然后返回目标对象。它是有序的,因此最后一个源将覆盖先前参数中的同名属性。

...递归工作?

实际上,query属性 increditOperation将完全覆盖query定义的属性baseOperation

var url = require('url')
  , _ = require('underscore'),
  , baseOperation = {
        host: 'gateway.skebby.it',
        pathname: 'api/send/smseasy/advanced/http.php',
        protocol: 'https',
        query: {
            'username': 'foo',
            'password': 'bar',
        }
    };

var creditOperation = _.extend(baseOperation, {
    query: {
        'method': 'baz'
    }
});

console.log(url.format(creditOperation));

我想得到这个creditOperation

{
    host: 'gateway.skebby.it',
    pathname: 'api/send/smseasy/advanced/http.php',
    protocol: 'https',
    query: {
        'username': 'foo',
        'password': 'bar',
        'method': 'baz'
    }
}
4

6 回答 6

40

使用Lodash(下划线的分叉)你可以。Lodash 的_.extend方法接受第三个(或更高)参数作为函数,它接收值(旧的和新的);所以你可以做这样的事情:

var deep = function(a, b) {
    return _.isObject(a) && _.isObject(b) ? _.extend(a, b, deep) : b;
};

var a = {a:{b:{c:1}}},
    b = {a:{b:{z:1}}};

_.extend(a,b,deep);

更新。 正如Paolo Moretti在评论中所说, lodash中有一个相同的函数,称为_.merge

_.merge(a,b);
于 2013-09-03T15:17:10.627 回答
24

jQuery 有一个extend()函数,它和它的 Underscore 对应物做同样的事情,但也有一个深层参数,允许它按照你的需要递归地合并:

var creditOperation = $.extend(true, baseOperation, {
    query: {
        'method': 'baz'
    }
});

或者,如果您不想覆盖baseOperation

var creditOperation = $.extend(true, {}, baseOperation, {
    query: {
        'method': 'baz'
    }
});
于 2014-07-02T23:27:26.957 回答
21

Underscore 没有计划添加深度扩展,因为它被认为太复杂而无法处理不同类型的对象。相反,鼓励用户实施他们自己的解决方案,并支持他们需要的东西。

在您的情况下,它只是普通对象,因此实现非常简单:

_.deepObjectExtend = function(target, source) {
    for (var prop in source)
        if (prop in target)
            _.deepObjectExtend(target[prop], source[prop]);
        else
            target[prop] = source[prop];
    return target;
}
于 2013-02-12T23:43:58.697 回答
8

Bergi 深度扩展的独立版本,包括当值是字符串而不是对象时的修复。也修补得更严格。

function deepObjectExtend (target, source) {
    for (var prop in source) {
        if (source.hasOwnProperty(prop)) {
            if (target[prop] && typeof source[prop] === 'object') {
                deepObjectExtend(target[prop], source[prop]);
            }
            else {
                target[prop] = source[prop];
            }
        }
    }
    return target;
}
于 2015-04-10T13:56:37.570 回答
2

Kurt Milam 发布了一个mixin,它deepExtend为 underscore.js 添加了一个方法。它甚至处理正则表达式(如果你愿意的话)。文档摘录:

将其与 underscore.js 混合: _.mixin({deepExtend: deepExtend});

像这样称呼它:var myObj = _.deepExtend(grandparent, child, grandchild, greatgrandchild)

注意:保持干燥。

如果您使用 JSON 配置文档,此功能特别有用。它允许您使用最常见的设置创建默认配置文档,然后针对特定情况覆盖这些设置。它接受任意数量的对象作为参数,让您对配置文档层次结构进行细粒度控制。

于 2015-08-26T16:07:48.060 回答
2

underscore 的 extend() 不做深度扩展;事实上,下划线并没有可以深度扩展的功能。

您可以为此使用 lodash 的合并

于 2016-08-12T00:04:52.803 回答