index.js 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. 'use strict';
  2. var hasOwn = Object.prototype.hasOwnProperty;
  3. var toStr = Object.prototype.toString;
  4. var isPlainObject = function isPlainObject(obj) {
  5. if (!obj || toStr.call(obj) !== '[object Object]') {
  6. return false;
  7. }
  8. var hasOwnConstructor = hasOwn.call(obj, 'constructor');
  9. var hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf');
  10. // Not own constructor property must be Object
  11. if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) {
  12. return false;
  13. }
  14. // Own properties are enumerated firstly, so to speed up,
  15. // if last one is own, then all properties are own.
  16. var key;
  17. for (key in obj) { /**/ }
  18. return typeof key === 'undefined' || hasOwn.call(obj, key);
  19. };
  20. module.exports = function extend() {
  21. var options, name, src, copy, copyIsArray, clone;
  22. var target = arguments[0];
  23. var i = 1;
  24. var length = arguments.length;
  25. var deep = false;
  26. // Handle a deep copy situation
  27. if (typeof target === 'boolean') {
  28. deep = target;
  29. target = arguments[1] || {};
  30. // skip the boolean and the target
  31. i = 2;
  32. } else if ((typeof target !== 'object' && typeof target !== 'function') || target == null) {
  33. target = {};
  34. }
  35. for (; i < length; ++i) {
  36. options = arguments[i];
  37. // Only deal with non-null/undefined values
  38. if (options == null) continue;
  39. // Extend the base object
  40. for (name in options) {
  41. if (name === '__proto__') continue;
  42. src = target[name];
  43. copy = options[name];
  44. // Prevent never-ending loop
  45. if (target === copy) continue;
  46. // Recurse if we're merging plain objects
  47. if (deep && copy && isPlainObject(copy)) {
  48. clone = src && isPlainObject(src) ? src : {};
  49. // Never move original objects, clone them
  50. target[name] = extend(deep, clone, copy);
  51. // Don't bring in undefined values
  52. } else if (typeof copy !== 'undefined') {
  53. target[name] = copy;
  54. }
  55. }
  56. }
  57. // Return the modified object
  58. return target;
  59. };