2 * Dictionary implementation relying on an object or if supported on a Map to hold key => value data.
4 * If you're looking for a dictionary with object keys, please see `WoltLabSuite/Core/ObjectMap`.
6 * @author Tim Duesterhus, Alexander Ebert
7 * @copyright 2001-2018 WoltLab GmbH
8 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
9 * @module WoltLabSuite/Core/Dictionary
11 define(['Core'], function(Core
) {
14 var _hasMap
= objOwns(window
, 'Map') && typeof window
.Map
=== 'function';
19 function Dictionary() {
20 this._dictionary
= (_hasMap
) ? new Map() : {};
22 Dictionary
.prototype = {
24 * Sets a new key with given value, will overwrite an existing key.
26 * @param {(number|string)} key key
27 * @param {?} value value
29 set: function(key
, value
) {
30 if (typeof key
=== 'number') key
= key
.toString();
32 if (typeof key
!== "string") {
33 throw new TypeError("Only strings can be used as keys, rejected '" + key
+ "' (" + typeof key
+ ").");
36 if (_hasMap
) this._dictionary
.set(key
, value
);
37 else this._dictionary
[key
] = value
;
41 * Removes a key from the dictionary.
43 * @param {(number|string)} key key
45 'delete': function(key
) {
46 if (typeof key
=== 'number') key
= key
.toString();
48 if (_hasMap
) this._dictionary
['delete'](key
);
49 else this._dictionary
[key
] = undefined;
53 * Returns true if dictionary contains a value for given key and is not undefined.
55 * @param {(number|string)} key key
56 * @return {boolean} true if key exists and value is not undefined
59 if (typeof key
=== 'number') key
= key
.toString();
61 if (_hasMap
) return this._dictionary
.has(key
);
63 return (objOwns(this._dictionary
, key
) && typeof this._dictionary
[key
] !== "undefined");
68 * Retrieves a value by key, returns undefined if there is no match.
70 * @param {(number|string)} key key
74 if (typeof key
=== 'number') key
= key
.toString();
77 if (_hasMap
) return this._dictionary
.get(key
);
78 else return this._dictionary
[key
];
85 * Iterates over the dictionary keys and values, callback function should expect the
86 * value as first parameter and the key name second.
88 * @param {function<*, string>} callback callback for each iteration
90 forEach: function(callback
) {
91 if (typeof callback
!== "function") {
92 throw new TypeError("forEach() expects a callback as first parameter.");
96 this._dictionary
.forEach(callback
);
99 var keys
= Object
.keys(this._dictionary
);
100 for (var i
= 0, length
= keys
.length
; i
< length
; i
++) {
101 callback(this._dictionary
[keys
[i
]], keys
[i
]);
107 * Merges one or more Dictionary instances into this one.
109 * @param {...Dictionary} var_args one or more Dictionary instances
112 for (var i
= 0, length
= arguments
.length
; i
< length
; i
++) {
113 var dictionary
= arguments
[i
];
114 if (!(dictionary
instanceof Dictionary
)) {
115 throw new TypeError("Expected an object of type Dictionary, but argument " + i
+ " is not.");
118 dictionary
.forEach((function(value
, key
) {
119 this.set(key
, value
);
125 * Returns the object representation of the dictionary.
127 * @return {object} dictionary's object representation
129 toObject: function() {
130 if (!_hasMap
) return Core
.clone(this._dictionary
);
133 this._dictionary
.forEach(function(value
, key
) {
142 * Creates a new Dictionary based on the given object.
143 * All properties that are owned by the object will be added
144 * as keys to the resulting Dictionary.
146 * @param {object} object
147 * @return {Dictionary}
149 Dictionary
.fromObject = function(object
) {
150 var result
= new Dictionary();
152 for (var key
in object
) {
153 if (objOwns(object
, key
)) {
154 result
.set(key
, object
[key
]);
161 Object
.defineProperty(Dictionary
.prototype, 'size', {
166 return this._dictionary
.size
;
169 return Object
.keys(this._dictionary
).length
;