【问题标题】:Recursive/deep extend/assign in Underscore.js?Underscore.js 中的递归/深度扩展/分配?
【发布时间】:2021-08-03 20:04:31
【问题描述】:

有没有办法获取Underscore.js extend函数:

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

...递归工作?

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

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

【问题讨论】:

  • 您能否在标题中添加“deep”和“assign”字样,以便通过 Google 轻松找到该主题。就像“Underscore.js 中的递归/深度扩展/赋值?”

标签: javascript underscore.js


【解决方案1】:

使用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 在cmets 中所说,lodash 中也有同样的功能,叫做_.merge

_.merge(a,b);

【讨论】:

  • 您也可以使用_.merge递归合并源对象自己的可枚举属性,这些属性不会解析为未定义到目标对象中。跨度>
  • 这没有回答问题
  • @wapsee,相反,我认为这是最有用的答案。
【解决方案2】:

jQuery 有一个 extend() 函数,它的作用与它的 Underscore 对应物相同,但也有一个 deep 参数,允许它根据需要递归合并:

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

或者,如果您不想覆盖 baseOperation

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

【讨论】:

  • 谢谢你的这个,比起自己写,最好还是自己用,反正项目中很多情况下都是用jquery的。
  • 这是很多人在找到这个页面时真正想要的 :)
  • 第二个是百万美元的答案!!!我只能给你+1 :)
【解决方案3】:

Underscore has no plans to add 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;
}

【讨论】:

  • 这似乎会在遇到不是对象的属性时按原样抛出异常。在尝试递归之前,您需要验证 target[prop] 和 source[prop] 都是对象。也许像if (prop in target && typeof(target[prop]) == 'object' && typeof(source[prop]) == 'object') 这样的第三行代替。
  • 是的,我希望这个extend 函数只扩展(扩展?)对象,而不覆盖其中的任何属性(描述说只有普通对象)。如果你愿意,if (typeof target[prop] == 'object') 应该足够了。
  • 我不确定两个具有相同属性的对象如何使它们不是普通对象。如果它处理具有相同属性的对象(并且本着 _.extend 的精神更多),则此函数的用处大约提高 5 倍。此外,仅检查目标 [prop] 是否为对象仍会在源 prop 不是对象且目标 prop 为:jsfiddle.net/wizzard/HY4yQ 的情况下(疯狂地)给出意外结果@ 诚然,您可能需要添加一些额外的如果您有这样的情况,请考虑此功能。
  • @wizzard:当然,我的个人库中有extend 功能的更复杂的变体——这里的这个并不是非常通用的。它只是处理 OP 具​​有他想要混合的(深度嵌套的)属性的问题中的用例。
  • 下划线不会,但它的替换 lodash 有它,它的 _.merge function,参见。 @Paolo_Moretti 评论:_.merge(target, source)
【解决方案4】:

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

【讨论】:

    【解决方案5】:

    Kurt Milam 发布了mixin that adds a deepExtend method to underscore.js。它甚至处理正则表达式(如果你愿意的话)。 文档摘录:

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

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

    注意:保持干燥。

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

    【讨论】:

      【解决方案6】:

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

      您可以使用 lodash 的 merge

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-16
        • 1970-01-01
        • 2021-10-09
        • 2016-08-16
        • 2017-02-20
        • 1970-01-01
        • 1970-01-01
        • 2021-01-06
        相关资源
        最近更新 更多