Underscore.js中的递归/深度扩展/分配?

时间:2013-02-12 23:28:29

标签: javascript underscore.js

有没有办法让Underscore.js extend起作用:

  

将源对象中的所有属性复制到   目标对象,并返回目标对象。这是有序的,   所以最后一个源将覆盖相同名称的属性   以前的论点。

......递归地工作?

实际上,query中的creditOperation属性将完全覆盖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'
    }
}

6 个答案:

答案 0 :(得分:38)

使用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);

<强> UPD。 正如Paolo Moretti在评论中所说, lodash 中有相同的功能,名为 _。合并

_.merge(a,b);

答案 1 :(得分:23)

jQuery有一个extend()函数,它与Underscore对应函数做同样的事情,但也有一个参数,允许它根据需要递归合并:

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

或者,如果您不想覆盖 baseOperation

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

答案 2 :(得分:20)

不,Underscore will not contain a deep extend因为处理不同类型的对象太复杂了。相反,鼓励用户实施他们自己的解决方案,并支持他们所需的。

在你的情况下,它只是普通的对象,所以实现非常简单:

_.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;
}

答案 3 :(得分:6)

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;
}

答案 4 :(得分:2)

Kurt Milam发表了mixin that adds a deepExtend method to underscore.js。它甚至可以处理正则表达式(如果需要)。 摘自文档:

  

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

     

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

     

注意:保持干燥。

     

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

答案 5 :(得分:1)

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

你可以使用lodash的merge