深入扩展(如jQuery的)为nodeJS

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

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

你想要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; } 

和一个小的testing,以显示它深层复制

 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

它已经被移植了 节点延伸

注意该项目没有testing,并没有太多的普及,所以使用风险自负。

如上所述,您可能不需要深层复制。 尝试改变你的数据结构,所以你只需要浅拷贝。

几个月后

我写了一个较小的模块,build议您使用xtend 。 它没有包含jQuery包的实现,也没有像node-extend那样的错误。

请使用内置的util模块:

 var extend = require('util')._extend; var merged = extend(obj1, obj2); 

深拷贝的一个快速和肮脏的答案只是作弊与一个小JSON。 这不是最高性能的,但它确实做得非常好。

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

我知道这是一个古老的问题,但我只想把lodash的合并作为一个很好的解决scheme。 我build议lodash实用function一般:)

这适用于深入的对象扩展…被警告,它取代了数组,而不是它们的值,但显然可以更新你喜欢的方式。 它应该保持枚举function和所有其他的东西,你可能希望它做的

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

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

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

node.extend做的很深并且有熟悉的jQuery语法

只需安装扩展。 docs: 节点扩展包安装:

 npm install extend 

然后享受它:

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

深是可选的。 默认为false。 如果切换为true,它将recursion地合并你的对象。

被称为whet.extend的分解版本。

我用CoffeeScript重新编写node-extend并添加了travis-citesting套件,因为我需要在Node中进行深度应对,所以现在就在这里。

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

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