gpt4 book ai didi

javascript - 绑定(bind)要在 Function 构造函数内使用的函数

转载 作者:行者123 更新时间:2023-11-28 01:21:38 25 4
gpt4 key购买 nike

我打算创建一个在调用回调之前调用的“预处理”函数。换句话说,调用回调应该遵循以下模式:预处理函数 -> 回调。为了“插入”这样的预处理函数,我可以简单地创建一个闭包,在闭包内重写回调,以便调用预处理函数,然后在重写的回调结束时,调用原始回调。

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)到回调函数。然后我遇到了一个非常奇怪的问题。由于某种原因,将范围/参数绑定(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 构造函数中使用了完全不同的绑定(bind)函数。任何绑定(bind)函数(无论是否使用变量引用)都会给我错误:“SyntaxError:元素列表后缺少 ]”。

事实上,即使这样也失败了

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

最佳答案

正如我所料,您实际上使问题有点过于复杂了。
您可以构建一个高阶函数,该函数返回适当的处理程序并自动包装该函数(如预处理器),而不是使用函数构造函数。

var callbackWrapper = function (callback) {
// Returns new anonymous function that acts as the handler
return function responseHandler (responseText) {
// Do your pre-processing
console.log(responseText);
callback.apply(this, Array.prototype.slice.call(arguments));
};
};

var ajax = function(init) {
for (var i = 0, callbacks = ["success", "error"]; i < callbacks.length; i++) {
var callbackName = callbacks[i] + "Callback";
if (init.hasOwnProperty(callbackName)) {
var callback = init[callbackName];
init[callbackName] = callbackWrapper(callback);
}
}

// This is the actual ajax function, which can operate in independent of the project (for example, 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");
}
});
})();

如果您愿意,您甚至可以更改callbackWrapper,使其每次都使用完全相同的预处理器函数:

var callbackWrapper = (function createCallbackWrapper () {
var preProcessor = function (responseText) {
console.log(responseText);
};

return function callbackWrapper (callback) {
// Returns new anonymous function that acts as the handler
return function responseHandler (responseText) {
var args = Array.prototype.slice.call(arguments);
preProcessor.apply(this, args);
callback.apply(this, args);
};
};
})();

现在绑定(bind)原始回调函数将不再有任何问题。

关于这个问题的更多解释:

当你使用fn + ".apply(...)"时,JS会将原函数转为字符串。这就是为什么您将很难访问闭包变量或任何不在您的 varclosure 函数范围或全局范围内的其他内容。

在您的情况下它也会失败,因为在函数上调用 .bind 后,其字符串表示形式变成 "function () { [native code] }"。这当然不是一个有效的函数体,并且会给你带来很多麻烦。

转换为字符串是实际问题,而且是一个不容易解决的问题。因此,使用 new Function 几乎从来都不是正确的解决方案,一旦您发现自己使用它,您应该假设您在推理中犯了错误。如果您没有这样做,并且 new Function 确实是唯一的解决方案,您就会知道。

关于javascript - 绑定(bind)要在 Function 构造函数内使用的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23200611/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com