如果性能不是很关键(例如,键的数量相对较小),并且你不想用额外的字段(如_hash, _id等)污染你的(或可能不是你的)对象,那么你可以利用Array.prototype.indexOf采用严格相等的事实。下面是一个简单的实现:
var Dict = (function(){
// Internet Explorer 8 and earlier does not have any Array.prototype.indexOf
function indexOfPolyfill(val) {
for (var i = 0, l = this.length; i < l; ++i) {
if (this[i] === val) {
return i;
}
}
return -1;
}
function Dict(){
this.keys = [];
this.values = [];
if (!this.keys.indexOf) {
this.keys.indexOf = indexOfPolyfill;
}
};
Dict.prototype.has = function(key){
return this.keys.indexOf(key) != -1;
};
Dict.prototype.get = function(key, defaultValue){
var index = this.keys.indexOf(key);
return index == -1 ? defaultValue : this.values[index];
};
Dict.prototype.set = function(key, value){
var index = this.keys.indexOf(key);
if (index == -1) {
this.keys.push(key);
this.values.push(value);
} else {
var prevValue = this.values[index];
this.values[index] = value;
return prevValue;
}
};
Dict.prototype.delete = function(key){
var index = this.keys.indexOf(key);
if (index != -1) {
this.keys.splice(index, 1);
return this.values.splice(index, 1)[0];
}
};
Dict.prototype.clear = function(){
this.keys.splice(0, this.keys.length);
this.values.splice(0, this.values.length);
};
return Dict;
})();
用法示例:
var a = {}, b = {},
c = { toString: function(){ return '1'; } },
d = 1, s = '1', u = undefined, n = null,
dict = new Dict();
// Keys and values can be anything
dict.set(a, 'a');
dict.set(b, 'b');
dict.set(c, 'c');
dict.set(d, 'd');
dict.set(s, 's');
dict.set(u, 'u');
dict.set(n, 'n');
dict.get(a); // 'a'
dict.get(b); // 'b'
dict.get(s); // 's'
dict.get(u); // 'u'
dict.get(n); // 'n'
// etc.
与ECMAScript 6 WeakMap相比,它有两个问题:O(n)搜索时间和非弱(即如果不使用delete或clear释放键会导致内存泄漏)。