web-dev-qa-db-fra.com

extension profonde (comme celle de jQuery) pour nodeJS

Je me bats avec des copies profondes d'objets dans nodeJS. ma propre extension est de la merde. le prolongement du trait de soulignement est plat. il existe des variantes d'extension assez simples ici sur stackexchange, mais aucune n'est même proche de jQuery.extend (true, {}, obj, obj, obj) .. (la plupart sont en fait terribles et bousillent les avantages du code asnyc.)

d'où ma question: existe-t-il une bonne copie complète pour NodeJS? Quelqu'un a-t-il porté jQuery?

42
itsatony

Vous voulez jQuery, alors utilisez-le:

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

et un petit test pour montrer qu'il fait des copies profondes

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

Mais n'oubliez pas de fournir l'attribution: https://github.com/jquery/jquery/blob/master/src/core.js

14
jcolebrand

Il a déjà été porté. extension de noeud

Notez que le projet n'a pas de tests et n'a pas beaucoup de popularité, alors utilisez-le à vos risques et périls.

Comme mentionné, vous n'avez probablement pas besoin de copies complètes. Essayez de modifier vos structures de données afin de n'avoir besoin que de copies superficielles.

Quelques mois plus tard

J'ai plutôt écrit un module plus petit, je vous recommande d'utiliser xtend . Il n'a pas d'implémentation contenant des bagages jQuery ni de bugs comme node-extend.

27
Raynos

Veuillez utiliser le module util intégré:

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

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

Une réponse rapide et sale aux copies profondes est juste de tricher avec un peu de JSON. Ce n'est pas le plus performant, mais il fait extrêmement bien le travail.

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

Je sais que c'est une vieille question, mais je voudrais juste jeter la fusion de lodash dans le mix comme une bonne solution. Je recommanderais lodash pour les fonctions utilitaires en général :)

8
thataustin

node.extend le fait en profondeur et a une syntaxe jQuery familière

1
Stanislav

Dans Node.js, vous pouvez utiliser Extendify pour créer une fonction _.extend qui prend en charge l'extension des objets imbriqués (deep extend) et est également immuable à ses paramètres (d'où le clone profond).

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

installez simplement extend. docs: package d'extension de noeud install:

npm install extend

alors profitez-en:

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

profond est facultatif. la valeur par défaut est false. si vous passez à true, il fusionnera récursivement vos objets.

1
Amin

Cela fonctionne pour une extension d'objet profonde ... soyez averti qu'il remplace les tableaux plutôt que leurs valeurs, mais cela peut évidemment être mis à jour comme vous le souhaitez. Il doit conserver les capacités d'énumération et toutes les autres choses que vous voulez probablement qu'il fasse

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

Vous pouvez également utiliser ma version du plugin d'extension https://github.com/maxmara/dextend

0
Vlad Miller

Version affûtée appelée whet.extend .

Je réécris node-extend avec CoffeeScript et j'ajoute la suite de tests travis-ci, car j'ai besoin d'une adaptation profonde dans Node pour moi-même, maintenant c'est ici.

Et oui, je pense que dans certains cas, il est absolument correct d'utiliser la fusion profonde, par exemple, je l'utilise dans les travaux de configuration, lorsque nous devons fusionner les branches par défaut et les branches utilisateur ensemble.

0
Meettya