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

gre*_*emo 31 javascript underscore.js

有没有办法获得Underscore.js extend功能:

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

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

实际上,queryproperty in 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));
Run Code Online (Sandbox Code Playgroud)

我想得到这个creditOperation:

{
    host: 'gateway.skebby.it',
    pathname: 'api/send/smseasy/advanced/http.php',
    protocol: 'https',
    query: {
        'username': 'foo',
        'password': 'bar',
        'method': 'baz'
    }
}
Run Code Online (Sandbox Code Playgroud)

gob*_*was 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);
Run Code Online (Sandbox Code Playgroud)

UPD. 正如Paolo Moretti在评论中所说,在lodash中有一个名为_.merge的相同功能:

_.merge(a,b);
Run Code Online (Sandbox Code Playgroud)

  • 您还可以使用[`_.merge`](http://lodash.com/docs#merge):_递归地将源对象的自身可枚举属性合并到目标对象_中,这些属性未解析为未定义. (13认同)
  • @wapsee,相反,我认为这是最有用的答案. (3认同)

小智 23

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

var creditOperation = $.extend(true, baseOperation, {
    query: {
        'method': 'baz'
    }
});
Run Code Online (Sandbox Code Playgroud)

或者,如果您不想覆盖baseOperation:

var creditOperation = $.extend(true, {}, baseOperation, {
    query: {
        'method': 'baz'
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 这是很多人在找到这个页面时真正想要的:) (3认同)

Ber*_*rgi 20

不,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;
}
Run Code Online (Sandbox Code Playgroud)

  • 当它遇到一个不是对象的属性时,它似乎会抛出一个异常.在尝试递归之前,您需要验证目标[prop]和source [prop]都是对象.也许类似于`if(prop in target && typeof(target [prop])=='object'&& typeof(source [prop])=='object')`代替第三行. (6认同)
  • 下划线不会,但它的替换[lodash](http://devdocs.io/lodash/index#merge)有它的[`_.merge`函数](http://devdocs.io/lodash/index #merge),cf.@Paolo_Moretti评论:`_.merge(目标,来源)` (3认同)

Kre*_*ieD 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;
}
Run Code Online (Sandbox Code Playgroud)