index.js 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. module.exports = extend;
  2. /*
  3. var obj = {a: 3, b: 5};
  4. extend(obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8}
  5. obj; // {a: 4, b: 5, c: 8}
  6. var obj = {a: 3, b: 5};
  7. extend({}, obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8}
  8. obj; // {a: 3, b: 5}
  9. var arr = [1, 2, 3];
  10. var obj = {a: 3, b: 5};
  11. extend(obj, {c: arr}); // {a: 3, b: 5, c: [1, 2, 3]}
  12. arr.push(4);
  13. obj; // {a: 3, b: 5, c: [1, 2, 3, 4]}
  14. var arr = [1, 2, 3];
  15. var obj = {a: 3, b: 5};
  16. extend(true, obj, {c: arr}); // {a: 3, b: 5, c: [1, 2, 3]}
  17. arr.push(4);
  18. obj; // {a: 3, b: 5, c: [1, 2, 3]}
  19. extend({a: 4, b: 5}); // {a: 4, b: 5}
  20. extend({a: 4, b: 5}, 3); {a: 4, b: 5}
  21. extend({a: 4, b: 5}, true); {a: 4, b: 5}
  22. extend('hello', {a: 4, b: 5}); // throws
  23. extend(3, {a: 4, b: 5}); // throws
  24. */
  25. function extend(/* [deep], obj1, obj2, [objn] */) {
  26. var args = [].slice.call(arguments);
  27. var deep = false;
  28. if (typeof args[0] == 'boolean') {
  29. deep = args.shift();
  30. }
  31. var result = args[0];
  32. if (!result || (typeof result != 'object' && typeof result != 'function')) {
  33. throw new Error('extendee must be an object');
  34. }
  35. var extenders = args.slice(1);
  36. var len = extenders.length;
  37. for (var i = 0; i < len; i++) {
  38. var extender = extenders[i];
  39. for (var key in extender) {
  40. if (extender.hasOwnProperty(key)) {
  41. var value = extender[key];
  42. if (deep && isCloneable(value)) {
  43. var base = Array.isArray(value) ? [] : {};
  44. result[key] = extend(true, result.hasOwnProperty(key) ? result[key] : base, value);
  45. } else {
  46. result[key] = value;
  47. }
  48. }
  49. }
  50. }
  51. return result;
  52. }
  53. function isCloneable(obj) {
  54. return Array.isArray(obj) || {}.toString.call(obj) == '[object Object]';
  55. }