web-dev-qa-db-ja.com

nodeJSの(jQueryのような)深い拡張

NodeJSのオブジェクトのディープコピーに苦労しています。私自身の拡張はがらくたです。アンダースコアの延長はフラットです。 stackexchangeにはかなり単純な拡張バリアントがありますが、jQuery.extend(true、{}、obj、obj、obj)に近いものはありません。

したがって、私の質問:NodeJSの優れたディープコピーはありますか?誰かjQueryを移植しましたか?

42
itsatony

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

14
jcolebrand

すでに移植されています。 ノード拡張

プロジェクトにはテストがなく、あまり人気がないため、ご自身の責任で使用してください。

前述のように、おそらくディープコピーは必要ありません。データ構造を変更して、浅いコピーのみが必要になるようにしてください。

数ヶ月後

代わりに小さなモジュールを作成しました。 xtend を使用することをお勧めします。 jQueryバゲッジを含む実装も、node-extendのようなバグもありません。

27
Raynos

組み込みのutilモジュールを使用してください:

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

var merged = extend(obj1, obj2);
11
ScriptMaster

ディープコピーに対する迅速で汚い答えは、ちょっとしたJSONをごまかすことです。最もパフォーマンスの高いものではありませんが、非常にうまく機能します。

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

これは古い質問であることは知っていますが、良い解決策として lodashのマージ をミックスに投入したいと思います。一般的なユーティリティ関数にはlodashをお勧めします:)

8
thataustin

node.extend それは深く、使い慣れたjQuery構文を持っています

1
Stanislav

Node.jsでは、 Extendify を使用して、ネストされたオブジェクトの拡張(深い拡張)をサポートし、そのパラメーターに対して不変である(したがって、深いクローン)_.extend関数を作成できます。

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

extendをインストールするだけです。 docs: ノード拡張パッケージ インストール:

npm install extend

それを楽しんでください:

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

deepはオプションです。デフォルトはfalseです。 trueに切り替えると、オブジェクトが再帰的にマージされます。

1
Amin

これは、オブジェクトの深い拡張に対して機能します。配列ではなく、値を置き換えますが、お好みに応じて更新できることに注意してください。列挙機能と、おそらく実行したい他のすべての機能を維持する必要があります

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

拡張プラグインの私のバージョンを使用することもできます https://github.com/maxmara/dextend

0
Vlad Miller

whet.extend と呼ばれるシャープなバージョン。

CoffeeScriptで node-extend を書き直し、travis-ciテストスイートを追加します。これは、Node私自身、今ここにあります。

そして、はい、場合によっては、ディープマージを使用することが絶対に正しいと思います。たとえば、デフォルトとユーザーのブランチをマージする必要があるときに、config worksで使用します。

0
Meettya