nodeJS的深度扩展(如jQuery)

时间:2012-02-22 16:59:05

标签: jquery node.js extend deep-copy

我正在努力研究nodeJS中对象的深层副本。我自己的延伸是废话。下划线的延伸是持平的。在stackexchange上有相当简单的扩展变体,但是没有一个甚至接近jQuery.extend(true,{},obj,obj,obj).. (大多数实际上都很糟糕,并且搞砸了asnyc代码的好处。)

因此,我的问题是:NodeJS有一个很好的深层副本吗?有人移植过jQuery吗?

11 个答案:

答案 0 :(得分:27)

它已被移植。 node-extend

请注意,该项目没有测试且没有太多受欢迎程度,因此请自担风险。

如前所述,您可能不需要深层拷贝。尝试更改您的数据结构,这样您只需要浅拷贝。

几个月后

我写了一个较小的模块,建议你使用xtend。它没有包含jQuery行李的实现,也没有像node-extend那样的bug。

答案 1 :(得分:14)

你想要jQuery,所以只需使用它:

function extend() {
    var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {},
        i = 1,
        length = arguments.length,
        deep = false,
        toString = Object.prototype.toString,
        hasOwn = Object.prototype.hasOwnProperty,
        push = Array.prototype.push,
        slice = Array.prototype.slice,
        trim = String.prototype.trim,
        indexOf = Array.prototype.indexOf,
        class2type = {
          "[object Boolean]": "boolean",
          "[object Number]": "number",
          "[object String]": "string",
          "[object Function]": "function",
          "[object Array]": "array",
          "[object Date]": "date",
          "[object RegExp]": "regexp",
          "[object Object]": "object"
        },
        jQuery = {
          isFunction: function (obj) {
            return jQuery.type(obj) === "function"
          },
          isArray: Array.isArray ||
          function (obj) {
            return jQuery.type(obj) === "array"
          },
          isWindow: function (obj) {
            return obj != null && obj == obj.window
          },
          isNumeric: function (obj) {
            return !isNaN(parseFloat(obj)) && isFinite(obj)
          },
          type: function (obj) {
            return obj == null ? String(obj) : class2type[toString.call(obj)] || "object"
          },
          isPlainObject: function (obj) {
            if (!obj || jQuery.type(obj) !== "object" || obj.nodeType) {
              return false
            }
            try {
              if (obj.constructor && !hasOwn.call(obj, "constructor") && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
                return false
              }
            } catch (e) {
              return false
            }
            var key;
            for (key in obj) {}
            return key === undefined || hasOwn.call(obj, key)
          }
        };
      if (typeof target === "boolean") {
        deep = target;
        target = arguments[1] || {};
        i = 2;
      }
      if (typeof target !== "object" && !jQuery.isFunction(target)) {
        target = {}
      }
      if (length === i) {
        target = this;
        --i;
      }
      for (i; i < length; i++) {
        if ((options = arguments[i]) != null) {
          for (name in options) {
            src = target[name];
            copy = options[name];
            if (target === copy) {
              continue
            }
            if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))) {
              if (copyIsArray) {
                copyIsArray = false;
                clone = src && jQuery.isArray(src) ? src : []
              } else {
                clone = src && jQuery.isPlainObject(src) ? src : {};
              }
              // WARNING: RECURSION
              target[name] = extend(deep, clone, copy);
            } else if (copy !== undefined) {
              target[name] = copy;
            }
          }
        }
      }
      return target;
    }

和一个小测试,以显示它做深拷贝

extend(true, 
    {
        "name": "value"
    }, 
    {
        "object": "value",
        "other": "thing",
        "inception": {
            "deeper": "deeper",
            "inception": {
                "deeper": "deeper",
                "inception": {
                    "deeper": "deeper"
                }
            }
        }
    }
)

但请记住提供归因:https://github.com/jquery/jquery/blob/master/src/core.js

答案 2 :(得分:11)

对深拷贝的快速而肮脏的回答只是用一点点JSON作弊。它并不是最高效的,但它确实能很好地完成这项任务。

function clone(a) {
   return JSON.parse(JSON.stringify(a));
}

答案 3 :(得分:11)

请使用内置的util模块:

var extend = require('util')._extend;

var merged = extend(obj1, obj2);

答案 4 :(得分:8)

我知道这是一个老问题,但我只想把lodash's merge作为一个好的解决方案。我建议lodash一般用于实用程序功能:)

答案 5 :(得分:1)

这适用于深度对象扩展...请注意它替换数组而不是它们的值,但显然可以按照您喜欢的方式更新。它应该保持枚举功能和你可能想要它做的所有其他事情

function extend(dest, from) {
    var props = Object.getOwnPropertyNames(from), destination;

    props.forEach(function (name) {
        if (typeof from[name] === 'object') {
            if (typeof dest[name] !== 'object') {
                dest[name] = {}
            }
            extend(dest[name],from[name]);
        } else {
            destination = Object.getOwnPropertyDescriptor(from, name);
            Object.defineProperty(dest, name, destination);
        }
    });
}

答案 6 :(得分:1)

在Node.js中,您可以使用Extendify创建一个支持嵌套对象扩展(深度扩展)的_.extend函数,并且它也是不可变的(因此深度克隆)。< / p>

_.extend = extendify({
    inPlace: false,
    isDeep: true
});

答案 7 :(得分:1)

node.extend做得很深,熟悉jQuery语法

答案 8 :(得分:1)

只需安装扩展。 文档: node extend package 安装:

npm install extend

然后享受它:

extend ( [deep], target, object1, [objectN] )

深是可选的。默认为false。如果切换为true,它将以递归方式合并您的对象。

答案 9 :(得分:0)

Sharped版本称为whet.extend

我用CoffeeScript重新编写node-extend并添加了travis-ci测试套件,因为我需要在节点中进行深度处理,所以现在就在这里。

是的,我认为在某些情况下它绝对正确地使用深度合并,例如我在配置工作时使用它,当我们需要将默认和用户分支合并在一起时。

答案 10 :(得分:0)

您也可以使用我的扩展插件版本 https://github.com/maxmara/dextend