我有一个GeneralWrapper
对象,可以调用Library1
和Library2
对象中的静态定义函数。
目的是通过致电GeneralWrapper.someFunc()
,这也会调用Library1.someFunc()
和Library2.someFunc()
,而我无需在名为GeneralWrapper
的{{1}}中明确创建一个功能
我尝试在下面的someFunc
方法中实现此功能:
__preamble
出于某种原因,对var GeneralWrapper = {
__modespopulated: false,
__validmodes: { // All 3 of these
spoonFunc: 1, // functions exist
knifeFunc: 1, // in Library1 and
forkFunc: 1 // Library2
},
__switchMode: function(funcname){
if (funcname in GeneralWrapper.__validmodes){
console.log("calling function", funcname)
GeneralWrapper.__preamble()
Library1[ funcname ](); // Call mode in Library1
Library2[ funcname ](); // Call mode in Library2
}
},
/* Attach valid modes to General Wrapper at runtime */
__preamble: function(){
if (!GeneralWrapper.__modespopulated)
{
for (var mode in GeneralWrapper.__validmodes)
{
GeneralWrapper[mode] = function(){
GeneralWrapper.__switchMode(mode)
};
}
GeneralWrapper.__modespopulated = true
}
GeneralWrapper.__otherprestuff();
},
__otherprestuff: function(){
// Stuff
},
funcThatAlwaysGetsCalled: function(){
GeneralWrapper.__switchMode("forkFunc");
}
}
var Library1 = {
forkFunc(){console.log("Lib1","fork")},
spoonFunc(){console.log("Lib1","spoon")},
knifeFunc(){console.log("Lib1","knife")}
}
var Library2 = {
forkFunc(){console.log("Lib2","FORK")},
spoonFunc(){console.log("Lib2","SPOON")},
knifeFunc(){console.log("Lib2","KNIFE")}
}
// Okay, let's initialise the object
GeneralWrapper.funcThatAlwaysGetsCalled();
和GeneralWrapper.spoonFunc()
的调用始终遵循Fork输出。
我认为问题源于GeneralWrapper.knifeFunc()
行上的匿名函数赋值,JS每次都将它视为相同的函数,但我不知道如何解决这个问题。
请告知。
答案 0 :(得分:1)
更改此行:
for (var mode in GeneralWrapper.__validmodes)
进入这个:
for (let mode in GeneralWrapper.__validmodes)
您的代码中发生的事情(在__preamble
循环中绑定函数时)是您创建一个匿名函数,这是完全正常的。问题是,你的anon函数已经收到mode
作为对局部变量的引用,因此它的值不会被自动克隆,而是在运行时被访问。主要问题是您使用了var
关键字,这意味着"提升变量" (它被声明在内部定义的函数的顶部,即使它位于函数代码中间的某个位置)。在这种情况下,您需要一个"块范围的"变量,它将分别绑定到每个循环迭代。
您可以在MDN上阅读有关变量托管的更多信息:
var
at MDN
let
at MDN
您必须了解的一件事 - let
已在ES2015中引入,因此,如果您担心与旧版浏览器的向后兼容性,则必须使用Function.prototype.bind
或IIFE
答案 1 :(得分:1)
这里的一个潜在问题是你在循环中创建函数会导致一些性能问题或意外行为。
我替换:
for (var mode in GeneralWrapper.__validmodes)
{
GeneralWrapper[mode] = function(){
GeneralWrapper.__switchMode(mode)
};
}
使用:
for (var mode in GeneralWrapper.__validmodes)
{
GeneralWrapper[mode] = GeneralWrapper.__switchMode.bind(this, mode);
}
哪个应该可以解决手头的问题。