Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Something like jQuery.extend() but standalone?

Tags:

javascript

I'm looking for a way to merge two configuration objects together, something like:

var developmentConfig = {
  url: "localhost",
  port: 80
};

var productionConfig = {
  url: "example.com"
};

var config = isDevelopment ? developmentConfig : jQuery.extend(developmentConfig, productionConfig);

However, this is a Node.js app and I don't want to include jQuery and am looking for something similar but standalone. I know I could write something similar myself but I'd rather use something tested and proven (there are edge cases, complications when the config objects use richer hierarchies etc.)

Edit: Simple iteration is not enough because that does not handle hierarchical structures. Neither does Underscore's extend.

like image 541
Borek Bernard Avatar asked Sep 07 '12 11:09

Borek Bernard


2 Answers

If all you need is extend, then it's pretty simple to write that in a couple of lines. If you want recursive extension, it's tricky to do that completely generically if you want have circular structures, objects with complex prototype chains, etc. If it's just some nested plain objects, then this should work:

function extend (target, source) {
  target = target || {};
  for (var prop in source) {
    if (typeof source[prop] === 'object') {
      target[prop] = extend(target[prop], source[prop]);
    } else {
      target[prop] = source[prop];
    }
  }
  return target;
}

If you're looking for a lightweight library that does this (minus the recursion, for the reasons listed above) and other similar functions not provided by javascript, look at Underscore which is available via NPM for node too.

like image 85
nickf Avatar answered Nov 20 '22 01:11

nickf


One more example of simple standalone function for future pilgrims across this question with protection from merge of the properties of different types:

function extend(obj) {
    Array.prototype.slice.call(arguments, 1).forEach(function(source) {
        if (source) {
            for (var prop in source) {
                if (source[prop].constructor === Object) {
                    if (!obj[prop] || obj[prop].constructor === Object) {
                        obj[prop] = obj[prop] || {};
                        extend(obj[prop], source[prop]);
                    } else {
                        obj[prop] = source[prop];
                    }
                } else {
                    obj[prop] = source[prop];
                }
            }
        }
    });
    return obj;
}

Usage:

extend({ name:'Maria', address:{ city:'Moscow', street:'Lenina str, 52' } }, { name:'Marianna', address:{ zip:1200003 }})
=> { name:'Marianna', address:{ city:'Moscow', street:'Lenina str, 52', zip:1200003 } }
like image 5
Maxim Ponomarev Avatar answered Nov 20 '22 01:11

Maxim Ponomarev