deep extend (like jQuery's) for nodeJS

后端 未结 11 857
情歌与酒
情歌与酒 2020-12-13 17:27

I am struggling with deep copies of objects in nodeJS. my own extend is crap. underscore\'s extend is flat. there are rather simple extend variants here on stackexchange, bu

相关标签:
11条回答
  • 2020-12-13 18:15

    just install extend. docs: node extend package install:

    npm install extend
    

    then enjoy it:

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

    deep is optional. default is false. if switch to true it will recursively merge your objects.

    0 讨论(0)
  • 2020-12-13 18:17

    It's already been ported. node-extend

    Note the project doesn't have tests and doesn't have much popularity, so use at your own risk.

    As mentioned you probably don't need deep copies. Try to change your data structures so you only need shallow copies.

    Few months later

    I wrote a smaller module instead, recommend you use xtend. It's not got an implementation containing jQuery baggage nor does it have bugs like node-extend does.

    0 讨论(0)
  • 2020-12-13 18:20

    You want jQuery's, so just use it:

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

    and a small test to show that it does deep copies

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

    But remember to provide attribution: https://github.com/jquery/jquery/blob/master/src/core.js

    0 讨论(0)
  • 2020-12-13 18:21

    A quick and dirty answer to deep copies is just to cheat with a little JSON. It's not the most performant, but it does do the job extremely well.

    function clone(a) {
       return JSON.parse(JSON.stringify(a));
    }
    
    0 讨论(0)
  • 2020-12-13 18:24

    In Node.js, You can use Extendify to create an _.extend function that supports nested objects extension (deep extend) and is also immutable to it's params (hence deep clone).

    _.extend = extendify({
        inPlace: false,
        isDeep: true
    });
    
    0 讨论(0)
提交回复
热议问题