有没有办法在执行时手动更改 Javascript 函数的执行上下文?
我不是谈论更改this
引用以指向不同的对象 - 我知道这可以通过Function.prototype.call()来完成/应用()
。
我说的是更改函数可访问的变量,或者更具体地说,授予对函数定义范围之外的变量的访问权限。
示例:
var func;
(function () {
func = function () {
alert(test); // no variable called "test" defined, it will
// result in a ReferenceError when func() is called
}
})();
function callFunction (callee) {
var test ='foobar';
callee(); // callee does not have access to "test"
}
callFunction(func);
在此示例中,我希望函数 func
能够在调用时访问 callFunciton
中定义的变量 test
。然而,由于作用域和执行上下文在 Javascript 中的工作方式,它并不是这样工作的。
我正在寻找一种方法,让 callFunction
在 callee()
调用的执行上下文中插入一个名为 test
的变量。
在这个最小的示例中,当然可以将 test 作为参数添加到 func()。
然而,我的用例是一个带有插件基础设施的框架,其中插件可以指定回调以及它们采用的参数以及参数类型。然后,框架负责将请求的数据转换为请求的类型并将它们提供给回调。这对于插件来说应该是完全透明的。
伪代码:
插件
function callback {
alert(user.name);
alert(number);
};
var callbackParams = [
{name : 'user', type : User},
{name : 'number', type : Number}
];
defineCallback('event', callback, callbackParams);
框架
var on = {
event : [];
}
var User = function (name) {
this.name = name;
}
function defineCallback (event, callback, params) {
on[event].push({
callback : callback;
params : params;
});
}
function handleEvent(event) {
on[event].forEach(function (handler) {
for (param of handler.params) {
// 1) gather data
// 2) create Object of correct type as specified in
// param.type
// 3) insert variable called param.name into
// execution context of handler.callback
}
handler.callback();
});
}
到目前为止,我找到了解决这个问题的三种解决方案,但我都不喜欢:
- 在回调中定义参数,并且仅在callbackParams中定义它们的类型,并按它们在函数声明中的顺序进行索引。缺点:必须在两个地方声明参数。
- 在回调中使用
this.paramname
而不是仅使用paramname
,并在 `handleEvent() 中使用.call()/.apply()
)。缺点:对插件不透明。 - 在
handleEvent()
中调用handler.callback()
之前将变量分配到全局范围,然后再次删除它们。缺点:非常丑陋的解决方法。
想法?
最佳答案
您可以使用 with
语句。请注意,它很慢并且在严格模式下被禁止。
var func;
(function () {
func = function func() {
with(func.variables) {
console.log(test);
}
}
})();
function callFunction (callee) {
callee.variables = {test: "foobar"};
callee();
callee.variables = null;
}
callFunction(func);
关于Javascript:使用不同的执行上下文执行函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37633775/