NodeJSのオブジェクトのディープコピーに苦労しています。私自身の拡張はがらくたです。アンダースコアの延長はフラットです。 stackexchangeにはかなり単純な拡張バリアントがありますが、jQuery.extend(true、{}、obj、obj、obj)に近いものはありません。
したがって、私の質問: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;
}
ディープコピーを行うことを示す小さなテスト
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
組み込みのutilモジュールを使用してください:
var extend = require('util')._extend;
var merged = extend(obj1, obj2);
ディープコピーに対する迅速で汚い答えは、ちょっとしたJSONをごまかすことです。最もパフォーマンスの高いものではありませんが、非常にうまく機能します。
function clone(a) {
return JSON.parse(JSON.stringify(a));
}
これは古い質問であることは知っていますが、良い解決策として lodashのマージ をミックスに投入したいと思います。一般的なユーティリティ関数にはlodashをお勧めします:)
node.extend それは深く、使い慣れたjQuery構文を持っています
Node.jsでは、 Extendify を使用して、ネストされたオブジェクトの拡張(深い拡張)をサポートし、そのパラメーターに対して不変である(したがって、深いクローン)_.extend関数を作成できます。
_.extend = extendify({
inPlace: false,
isDeep: true
});
extendをインストールするだけです。 docs: ノード拡張パッケージ インストール:
npm install extend
それを楽しんでください:
extend ( [deep], target, object1, [objectN] )
deepはオプションです。デフォルトはfalseです。 trueに切り替えると、オブジェクトが再帰的にマージされます。
これは、オブジェクトの深い拡張に対して機能します。配列ではなく、値を置き換えますが、お好みに応じて更新できることに注意してください。列挙機能と、おそらく実行したい他のすべての機能を維持する必要があります
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);
}
});
}
拡張プラグインの私のバージョンを使用することもできます https://github.com/maxmara/dextend
whet.extend と呼ばれるシャープなバージョン。
CoffeeScriptで node-extend を書き直し、travis-ciテストスイートを追加します。これは、Node私自身、今ここにあります。
そして、はい、場合によっては、ディープマージを使用することが絶対に正しいと思います。たとえば、デフォルトとユーザーのブランチをマージする必要があるときに、config worksで使用します。