Javascript:执行具有不同执行上下文的函数

时间:2016-06-04 18:43:51

标签: javascript function scope executioncontext

有没有办法在执行时手动更改Javascript函数的执行上下文?

谈论将this引用更改为指向其他对象 - 我知道可以使用Function.prototype.call()/apply()完成此操作。

我所说的是更改函数可访问的变量,或者更具体地说,是允许访问定义函数范围之外的变量。

示例:

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能够在调用test时访问callFunciton中定义的变量callFunction。但是由于范围和执行上下文在Javascript中的工作方式,它不会那样工作。

我正在寻找testcallee()调用的执行上下文中插入名为function callback { alert(user.name); alert(number); }; var callbackParams = [ {name : 'user', type : User}, {name : 'number', type : Number} ]; defineCallback('event', callback, callbackParams); 的变量的方法。

在这个最小的例子中,当然可以将test作为参数添加到func()。

然而,我的用例是一个带有插件基础结构的框架,其中插件可以指定回调以及它们采用的参数以及参数类型。然后,框架负责将请求的数据转换为请求的类型,并将它们提供给回调。这应该对插件完全透明。

伪代码:

插件

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

框架

this.paramname

到目前为止,我找到了解决这个问题的三种解决方案,我也不喜欢:

  • 在回调中定义参数,并且只在callbackParams中定义它们的类型,在函数声明中按顺序索引。缺点:必须在两个地方声明参数。
  • 在回调中使用paramname而不仅仅是.call()/.apply(),并在`handleEvent()中使用handler.callback()。缺点:对插件不透明。
  • handleEvent()中调用 declare @query1 nvarchar(max) set @query1 =(Select AccessColumns from TemplateAccess where TemplateName=@TemplateName) DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX) select @cols = STUFF((SELECT ',' + QUOTENAME(AccessColumns) from TemplateAccess group by AccessColumns order by AccessColumns FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'') set @query = N'SELECT ' + @cols + N' from ReportDetail rd inner join [dbo].[Report_DatesDetail] rdd on rd.CRIMS_ParentId =rdd.CRIMS_ParentId and rd.CRIMS_ChildId = rdd.CRIMS_ChildId inner join Mas_Application on [Application] = ApplicationName' exec sp_executesql @query 之前将变量分配到全局范围,然后再删除它们。缺点:非常难看的解决方法。

想法?

1 个答案:

答案 0 :(得分:1)

您可以使用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);