有没有办法在执行时手动更改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中的工作方式,它不会那样工作。
我正在寻找test
在callee()
调用的执行上下文中插入名为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
到目前为止,我找到了解决这个问题的三种解决方案,我也不喜欢:
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
之前将变量分配到全局范围,然后再删除它们。缺点:非常难看的解决方法。想法?
答案 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);