index.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*!
  2. * copy-to - index.js
  3. * Copyright(c) 2014 dead_horse <dead_horse@qq.com>
  4. * MIT Licensed
  5. */
  6. 'use strict';
  7. /**
  8. * slice() reference.
  9. */
  10. var slice = Array.prototype.slice;
  11. /**
  12. * Expose copy
  13. *
  14. * ```
  15. * copy({foo: 'nar', hello: 'copy'}).to({hello: 'world'});
  16. * copy({foo: 'nar', hello: 'copy'}).toCover({hello: 'world'});
  17. * ```
  18. *
  19. * @param {Object} src
  20. * @return {Copy}
  21. */
  22. module.exports = Copy;
  23. /**
  24. * Copy
  25. * @param {Object} src
  26. * @param {Boolean} withAccess
  27. */
  28. function Copy(src, withAccess) {
  29. if (!(this instanceof Copy)) return new Copy(src, withAccess);
  30. this.src = src;
  31. this._withAccess = withAccess;
  32. }
  33. /**
  34. * copy properties include getter and setter
  35. * @param {[type]} val [description]
  36. * @return {[type]} [description]
  37. */
  38. Copy.prototype.withAccess = function (w) {
  39. this._withAccess = w !== false;
  40. return this;
  41. };
  42. /**
  43. * pick keys in src
  44. *
  45. * @api: public
  46. */
  47. Copy.prototype.pick = function(keys) {
  48. if (!Array.isArray(keys)) {
  49. keys = slice.call(arguments);
  50. }
  51. if (keys.length) {
  52. this.keys = keys;
  53. }
  54. return this;
  55. };
  56. /**
  57. * copy src to target,
  58. * do not cover any property target has
  59. * @param {Object} to
  60. *
  61. * @api: public
  62. */
  63. Copy.prototype.to = function(to) {
  64. to = to || {};
  65. if (!this.src) return to;
  66. var keys = this.keys || Object.keys(this.src);
  67. if (!this._withAccess) {
  68. for (var i = 0; i < keys.length; i++) {
  69. key = keys[i];
  70. if (to[key] !== undefined) continue;
  71. to[key] = this.src[key];
  72. }
  73. return to;
  74. }
  75. for (var i = 0; i < keys.length; i++) {
  76. var key = keys[i];
  77. if (!notDefined(to, key)) continue;
  78. var getter = this.src.__lookupGetter__(key);
  79. var setter = this.src.__lookupSetter__(key);
  80. if (getter) to.__defineGetter__(key, getter);
  81. if (setter) to.__defineSetter__(key, setter);
  82. if (!getter && !setter) {
  83. to[key] = this.src[key];
  84. }
  85. }
  86. return to;
  87. };
  88. /**
  89. * copy src to target,
  90. * override any property target has
  91. * @param {Object} to
  92. *
  93. * @api: public
  94. */
  95. Copy.prototype.toCover = function(to) {
  96. var keys = this.keys || Object.keys(this.src);
  97. for (var i = 0; i < keys.length; i++) {
  98. var key = keys[i];
  99. delete to[key];
  100. var getter = this.src.__lookupGetter__(key);
  101. var setter = this.src.__lookupSetter__(key);
  102. if (getter) to.__defineGetter__(key, getter);
  103. if (setter) to.__defineSetter__(key, setter);
  104. if (!getter && !setter) {
  105. to[key] = this.src[key];
  106. }
  107. }
  108. };
  109. Copy.prototype.override = Copy.prototype.toCover;
  110. /**
  111. * append another object to src
  112. * @param {Obj} obj
  113. * @return {Copy}
  114. */
  115. Copy.prototype.and = function (obj) {
  116. var src = {};
  117. this.to(src);
  118. this.src = obj;
  119. this.to(src);
  120. this.src = src;
  121. return this;
  122. };
  123. /**
  124. * check obj[key] if not defiend
  125. * @param {Object} obj
  126. * @param {String} key
  127. * @return {Boolean}
  128. */
  129. function notDefined(obj, key) {
  130. return obj[key] === undefined
  131. && obj.__lookupGetter__(key) === undefined
  132. && obj.__lookupSetter__(key) === undefined;
  133. }