【发布时间】:2014-06-05 16:58:44
【问题描述】:
我打算创建一个在调用回调之前调用的“预处理”函数。换句话说,调用回调应该遵循以下模式:预处理函数 -> 回调。为了“插入”这样一个预处理函数,我可以简单地创建一个闭包,在闭包内重写回调,以便调用预处理函数,然后在重写回调结束时调用原始回调。
var end = function(init) {
/*
In here, init is processed.
Init contains multiple callbacks.
One callback is chosen to be invoked.
*/
init.callback();
};
var closure = function(init) {
var old = init.callback;
init.callback = function() {
/*
Do the preprocessual stuff
*/
console.log("The preprocessual functionality has now taken place.");
return old.apply(this, Array.prototype.slice.call(arguments));
};
return end.apply(this, Array.prototype.slice.call(arguments));
};
closure({
/*among other properties*/
callback: function() {
console.log("The preprocessual callback must have been invoked when 'end' invokes me.");
}
});
但是,我有多个回调,而我只有一个预处理函数。每次调用这些回调之前都应该调用相同的预处理函数。为了不必为每个单独的可能回调编写预处理回调,我在闭包中创建了一个循环,将变量 old 分配给下一个回调,然后使用 Function 构造函数重写回调。
一切仍然有效。但是,我不再能够在它最初可以访问的回调函数中使用非全局变量。以下崩溃,声称未定义variable(根据https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function)。
(function() {
var end = function(init) {
/*
In here, init is processed.
Init contains multiple callbacks.
One callback is chosen to be invoked.
*/
init.callback();
};
var closure = function(init) {
var old = init.callback;
init.callback = new Function(
"\
/*\
Do the preprocessual stuff\
*/\
console.log(\"The preprocessual functionality has now taken place.\");\
return " + old + ".apply(this, Array.prototype.slice.call(arguments));\
"
);
return end.apply(this, Array.prototype.slice.call(arguments));
};
var variable = "value";
closure({
/*among other properties*/
callback: function() {
console.log("The preprocessual callback must have been invoked when 'end' invokes me.");
console.log(variable);
}
});
})();
然后我想,让我们尝试bind 我在回调函数中需要的变量。然后我遇到了一个很奇怪的问题。出于某种原因,将范围/参数绑定到回调函数(与 Function 构造函数无关)会导致奇怪的错误。此类错误的一个小例子:
这行得通
var callback = function() {
console.log(arguments);
};
callback = new Function(
"\
return " + callback + ".apply(this, Array.prototype.slice.call(arguments));\
"
);
callback(1, 2, 3);
这不起作用
var callback = function() {
console.log(arguments);
}.bind(this);
callback = new Function(
"\
return " + callback + ".apply(this, Array.prototype.slice.call(arguments));\
"
);
callback(1, 2, 3);
如果我将回调分配给另一个变量(例如 old)并在 Function 构造函数中使用 old 并在 Function 构造函数中使用完全不同的绑定函数也没关系构造函数。任何绑定函数(无论是否使用变量引用)都会给我错误:“SyntaxError: missing ] after element list”。
事实上,即使这样也失败了
callback = new Function(
"\
return " + (function() {}.bind(this)) + ".apply(this, Array.prototype.slice.call(arguments));\
"
);
callback(1, 2, 3);
我不明白为什么会这样。有用的帮助将不胜感激。
根据要求,实际用例:
var
ajax = function(init) {
for (var i = 0, callbacks = ["success", "error"]; i < callbacks.length; i++) {
if (init.hasOwnProperty(callbacks[i] + "Callback")) {
init[callbacks[i] + "Callback"] = new Function("responseText",
"\
/*\
Preprocessual callback takes place here (among other things, messages from the server are inserted in the document)\
*/\
\
return " + init[callbacks[i] + "Callback"] + ".apply(this, Array.prototype.slice.call(arguments));\
"
);
}
}
// This is the actual ajax function, which can operate independently of the project (in contrary, the preprocessual callback needs to know about where to insert messages in the document)
return cregora.ajax.apply(this, Array.prototype.slice.call(arguments));
}
;
(function() {
// some scope with variables..
ajax({
url: "url",
callbackThis: this,
successCallback: function(responseText) {
console.log("I need some variables available in this scope");
},
errorCallback: function() {
console.log("I need some variables available in this scope");
}
});
})();
【问题讨论】:
-
你能解释一下让你从“普通”函数到使用函数构造函数+函数体作为字符串的步骤吗?
-
@TheShellfishMeme 是的,我在 init 对象中有多个回调,所有这些回调之前都必须有相同的预处理回调。我不打算为它们中的每一个编写 99% 相同的代码,因为唯一的区别是在重写回调结束时要调用的原始回调的名称。不过,我在示例中省略了循环。
-
这就是我无法理解您的地方。他们都需要在不同的回调上使用相同的包装器。如果不使用
new Function,这样的事情绝对是可能的。这就是为什么我对问题的那一部分更好奇。看来,如果我们解决了这个问题,我们就解决了您的问题。因此,也许您还可以链接到使该更改成为必要的特定代码,我也许可以指出如何更改它。 -
@TheShellfishMeme 在帖子底部查看我的编辑
标签: javascript function binding constructor callback