module.exports = extend; /* var obj = {a: 3, b: 5}; extend(obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8} obj; // {a: 4, b: 5, c: 8} var obj = {a: 3, b: 5}; extend({}, obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8} obj; // {a: 3, b: 5} var arr = [1, 2, 3]; var obj = {a: 3, b: 5}; extend(obj, {c: arr}); // {a: 3, b: 5, c: [1, 2, 3]} arr.push(4); obj; // {a: 3, b: 5, c: [1, 2, 3, 4]} var arr = [1, 2, 3]; var obj = {a: 3, b: 5}; extend(true, obj, {c: arr}); // {a: 3, b: 5, c: [1, 2, 3]} arr.push(4); obj; // {a: 3, b: 5, c: [1, 2, 3]} extend({a: 4, b: 5}); // {a: 4, b: 5} extend({a: 4, b: 5}, 3); {a: 4, b: 5} extend({a: 4, b: 5}, true); {a: 4, b: 5} extend('hello', {a: 4, b: 5}); // throws extend(3, {a: 4, b: 5}); // throws */ function extend(/* [deep], obj1, obj2, [objn] */) { var args = [].slice.call(arguments); var deep = false; if (typeof args[0] == 'boolean') { deep = args.shift(); } var result = args[0]; if (!result || (typeof result != 'object' && typeof result != 'function')) { throw new Error('extendee must be an object'); } var extenders = args.slice(1); var len = extenders.length; for (var i = 0; i < len; i++) { var extender = extenders[i]; for (var key in extender) { if (extender.hasOwnProperty(key)) { var value = extender[key]; if (deep && isCloneable(value)) { var base = Array.isArray(value) ? [] : {}; result[key] = extend(true, result.hasOwnProperty(key) ? result[key] : base, value); } else { result[key] = value; } } } } return result; } function isCloneable(obj) { return Array.isArray(obj) || {}.toString.call(obj) == '[object Object]'; }