简体   繁体   English

Javascript:具有不同执行上下文的执行功能

[英]Javascript: Execute function with different execution context

Is there a way to change the execution context of a Javascript function manually at execution time? 有没有办法在执行时手动更改Javascript函数的执行上下文?

I am not talking about changing the this reference to point to a different object - I know this can be done with Function.prototype.call()/apply() . 不是在谈论更改this引用以指向另一个对象-我知道可以通过Function.prototype.call()/apply()来完成。

I am talking about changing variables accessible to the function, or to be more specific, granting access to variables that are outside of the scope the function is defined in. 我正在谈论更改函数可以访问的变量,或者更具体地说,是要授予对定义函数范围之外的变量的访问权限。

Example: 例:

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);

In this example, I'd love the function func to be able to access the variable test defined in callFunciton when it is called. 在此示例中,我希望函数func能够在被调用时访问在callFunciton定义的变量test However due to how scope and execution contexts work in Javascript, it doesn't work that way. 但是,由于范围和执行上下文在Javascript中是如何工作的,因此它不是那样工作的。

I am looking for a way for callFunction to insert a variable called test in the execution context of the callee() call. 我正在为callFunction寻找一种在callee()调用的执行上下文中插入称为test的变量的方法。


In this minimal example, it is of course possible to just add test as a parameter to func(). 在这个最小的示例中,当然可以仅将test作为参数添加到func()。

My use-case however is a framework with a plugin infrastructure, where plugins can specify callbacks and what parameters they take - along with parameter types. 但是,我的用例是一个具有插件基础结构的框架,插件可以在其中指定回调及其所使用的参数-以及参数类型。 The framework then takes care of converting requested data into the requested types and provide them to the callback. 然后,框架负责将请求的数据转换为请求的类型,并将其提供给回调。 This should happen completely transparent to the plugin. 这应该对插件完全透明。

Pseudocode: 伪代码:

Plugin 插入

function callback {
    alert(user.name);
    alert(number);
};
var callbackParams = [
    {name : 'user', type : User},
    {name : 'number', type : Number}
];
defineCallback('event', callback, callbackParams);

Framework 构架

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();
    });
}

So far, I found three solutions to this problem, and I like neither: 到目前为止,我找到了解决此问题的三种解决方案,但我都不喜欢:

  • define parameters in callback, and only define their types in callbackParams, indexed by their order in the function declaration. 在回调中定义参数,并且仅在callbackParams中定义其类型,并按其在函数声明中的顺序进行索引。 Disadvantage: parameters have to be declared in two places. 缺点:必须在两个地方声明参数。
  • use this.paramname instead of just paramname in callback, and use .call()/.apply() in `handleEvent(). 在回调中使用this.paramname而不是paramname ,在`handleEvent()中使用.call()/.apply() ()。 Disadvantage: not transparent to plugins. 缺点:对插件不透明。
  • assign the variables to global scope before calling handler.callback() in handleEvent() and delete them again afterwards. handleEvent()调用handler.callback()之前,将变量分配给全局范围,然后再删除它们。 Disadvantage: very ugly workaround. 缺点:非常难看的解决方法。

Ideas? 有想法吗?

You can use a with statement. 您可以使用with语句。 Be aware it's slow and forbidden in strict mode. 请注意,它在严格模式下是缓慢且禁止的。

 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); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM