merge.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*!
  2. * @name JavaScript/NodeJS Merge v1.2.1
  3. * @author yeikos
  4. * @repository https://github.com/yeikos/js.merge
  5. * Copyright 2014 yeikos - MIT license
  6. * https://raw.github.com/yeikos/js.merge/master/LICENSE
  7. */
  8. ;(function(isNode) {
  9. /**
  10. * Merge one or more objects
  11. * @param bool? clone
  12. * @param mixed,... arguments
  13. * @return object
  14. */
  15. var Public = function(clone) {
  16. return merge(clone === true, false, arguments);
  17. }, publicName = 'merge';
  18. /**
  19. * Merge two or more objects recursively
  20. * @param bool? clone
  21. * @param mixed,... arguments
  22. * @return object
  23. */
  24. Public.recursive = function(clone) {
  25. return merge(clone === true, true, arguments);
  26. };
  27. /**
  28. * Clone the input removing any reference
  29. * @param mixed input
  30. * @return mixed
  31. */
  32. Public.clone = function(input) {
  33. var output = input,
  34. type = typeOf(input),
  35. index, size;
  36. if (type === 'array') {
  37. output = [];
  38. size = input.length;
  39. for (index=0;index<size;++index)
  40. output[index] = Public.clone(input[index]);
  41. } else if (type === 'object') {
  42. output = {};
  43. for (index in input)
  44. output[index] = Public.clone(input[index]);
  45. }
  46. return output;
  47. };
  48. /**
  49. * Merge two objects recursively
  50. * @param mixed input
  51. * @param mixed extend
  52. * @return mixed
  53. */
  54. function merge_recursive(base, extend) {
  55. if (typeOf(base) !== 'object')
  56. return extend;
  57. for (var key in extend) {
  58. if (typeOf(base[key]) === 'object' && typeOf(extend[key]) === 'object') {
  59. base[key] = merge_recursive(base[key], extend[key]);
  60. } else {
  61. base[key] = extend[key];
  62. }
  63. }
  64. return base;
  65. }
  66. /**
  67. * Merge two or more objects
  68. * @param bool clone
  69. * @param bool recursive
  70. * @param array argv
  71. * @return object
  72. */
  73. function merge(clone, recursive, argv) {
  74. var result = argv[0],
  75. size = argv.length;
  76. if (clone || typeOf(result) !== 'object')
  77. result = {};
  78. for (var index=0;index<size;++index) {
  79. var item = argv[index],
  80. type = typeOf(item);
  81. if (type !== 'object') continue;
  82. for (var key in item) {
  83. if (key === '__proto__') continue;
  84. var sitem = clone ? Public.clone(item[key]) : item[key];
  85. if (recursive) {
  86. result[key] = merge_recursive(result[key], sitem);
  87. } else {
  88. result[key] = sitem;
  89. }
  90. }
  91. }
  92. return result;
  93. }
  94. /**
  95. * Get type of variable
  96. * @param mixed input
  97. * @return string
  98. *
  99. * @see http://jsperf.com/typeofvar
  100. */
  101. function typeOf(input) {
  102. return ({}).toString.call(input).slice(8, -1).toLowerCase();
  103. }
  104. if (isNode) {
  105. module.exports = Public;
  106. } else {
  107. window[publicName] = Public;
  108. }
  109. })(typeof module === 'object' && module && typeof module.exports === 'object' && module.exports);