pseudomap.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. var hasOwnProperty = Object.prototype.hasOwnProperty
  2. module.exports = PseudoMap
  3. function PseudoMap (set) {
  4. if (!(this instanceof PseudoMap)) // whyyyyyyy
  5. throw new TypeError("Constructor PseudoMap requires 'new'")
  6. this.clear()
  7. if (set) {
  8. if ((set instanceof PseudoMap) ||
  9. (typeof Map === 'function' && set instanceof Map))
  10. set.forEach(function (value, key) {
  11. this.set(key, value)
  12. }, this)
  13. else if (Array.isArray(set))
  14. set.forEach(function (kv) {
  15. this.set(kv[0], kv[1])
  16. }, this)
  17. else
  18. throw new TypeError('invalid argument')
  19. }
  20. }
  21. PseudoMap.prototype.forEach = function (fn, thisp) {
  22. thisp = thisp || this
  23. Object.keys(this._data).forEach(function (k) {
  24. if (k !== 'size')
  25. fn.call(thisp, this._data[k].value, this._data[k].key)
  26. }, this)
  27. }
  28. PseudoMap.prototype.has = function (k) {
  29. return !!find(this._data, k)
  30. }
  31. PseudoMap.prototype.get = function (k) {
  32. var res = find(this._data, k)
  33. return res && res.value
  34. }
  35. PseudoMap.prototype.set = function (k, v) {
  36. set(this._data, k, v)
  37. }
  38. PseudoMap.prototype.delete = function (k) {
  39. var res = find(this._data, k)
  40. if (res) {
  41. delete this._data[res._index]
  42. this._data.size--
  43. }
  44. }
  45. PseudoMap.prototype.clear = function () {
  46. var data = Object.create(null)
  47. data.size = 0
  48. Object.defineProperty(this, '_data', {
  49. value: data,
  50. enumerable: false,
  51. configurable: true,
  52. writable: false
  53. })
  54. }
  55. Object.defineProperty(PseudoMap.prototype, 'size', {
  56. get: function () {
  57. return this._data.size
  58. },
  59. set: function (n) {},
  60. enumerable: true,
  61. configurable: true
  62. })
  63. PseudoMap.prototype.values =
  64. PseudoMap.prototype.keys =
  65. PseudoMap.prototype.entries = function () {
  66. throw new Error('iterators are not implemented in this version')
  67. }
  68. // Either identical, or both NaN
  69. function same (a, b) {
  70. return a === b || a !== a && b !== b
  71. }
  72. function Entry (k, v, i) {
  73. this.key = k
  74. this.value = v
  75. this._index = i
  76. }
  77. function find (data, k) {
  78. for (var i = 0, s = '_' + k, key = s;
  79. hasOwnProperty.call(data, key);
  80. key = s + i++) {
  81. if (same(data[key].key, k))
  82. return data[key]
  83. }
  84. }
  85. function set (data, k, v) {
  86. for (var i = 0, s = '_' + k, key = s;
  87. hasOwnProperty.call(data, key);
  88. key = s + i++) {
  89. if (same(data[key].key, k)) {
  90. data[key].value = v
  91. return
  92. }
  93. }
  94. data.size++
  95. data[key] = new Entry(k, v, key)
  96. }