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