您可以使用原始數據類型爲對象Map
和WeakMap
:
function isPrimitive(value) {
return Object(value) !== value;
}
var primStore = new Map;
var objStore = new WeakMap;
function bindArg(fn, arg) {
var store = isPrimitive(arg) ? primStore : objStore;
if (!store.has(arg)) store.set(arg, new WeakMap);
if (!store.get(arg).has(fn)) store.get(arg).set(fn, fn.bind(null, arg));
return store.get(arg).get(fn);
}
請注意,我們返回store.get(arg).get(fn)
而不是store.get(fn).get(arg)
。這個翻轉對bindArg
函數的實際語義沒有任何影響,但是當我們要區分基本數據類型和對象時,這是必要的。
編輯:或者,你可以在一個WeakMap
創建存儲在Map
和對象的原始值的新WeakMap2
數據結構如下:
var WeakMap2 = defclass({
constructor: function() {
this.map1 = new Map;
this.map2 = new WeakMap;
if (arguments.length > 0) {
for (var object in argument[0]) {
if (isPrimitive(object))
throw new TypeError("Iterator value " +
object + " is not an entry object");
else this.set(object[0], object[1]);
}
}
},
get: function (key) {
return (isPrimitive(key) ? this.map1 : this.map2).get(key);
},
set: function (key, value) {
return (isPrimitive(key) ? this.map1 : this.map2).set(key, value);
},
has: function (key) {
return (isPrimitive(key) ? this.map1 : this.map2).has(key);
},
delete: function (key) {
return (isPrimitive(key) ? this.map1 : this.map2).delete(key);
}
});
function defclass(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
function isPrimitive(value) {
return Object(value) !== value;
}
不過,我不會推薦因爲它增加了一層抽象,使你的代碼變慢。
我假設你試圖記憶綁定函數以避免'Function.prototype.bind'具有「壞」性能的聲譽? – naomik
不,這是爲了簡化平等檢查 –
這聽起來像一個[XY問題](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)。你實際上在做什麼代碼? – naomik