在一些 Javascript 代码(特别是 node.js)中,我需要在不更改上下文的情况下调用具有一组未知参数的函数。例如:
function fn() {
var args = Array.prototype.slice.call(arguments);
otherFn.apply(this, args);
}
上面的问题是,当我调用 apply
时,我通过传递 this
作为第一个参数来更改上下文。我想将 args
传递给被调用的函数 而不 更改被调用函数的上下文。我基本上想这样做:
function fn() {
var args = Array.prototype.slice.call(arguments);
otherFn.apply(<otherFn's original context>, args);
}
编辑:添加关于我的具体问题的更多细节。我正在创建一个客户端类,其中包含一个套接字(socket.io)对象以及与连接有关的其他信息。我正在通过客户端对象本身公开套接字的事件监听器。
class Client
constructor: (socket) ->
@socket = socket
@avatar = socket.handshake.avatar
@listeners = {}
addListener: (name, handler) ->
@listeners[name] ||= {}
@listeners[name][handler.clientListenerId] = wrapper = =>
# append client object as the first argument before passing to handler
args = Array.prototype.slice.call(arguments)
args.unshift(this)
handler.apply(this, args) # <---- HANDLER'S CONTEXT IS CHANGING HERE :(
@socket.addListener(name, wrapper)
removeListener: (name, handler) ->
try
obj = @listeners[name]
@socket.removeListener(obj[handler.clientListenerId])
delete obj[handler.clientListenerId]
请注意,clientListenerId
是一个自定义的唯一标识符属性,与 the answer found here 基本相同。 .
最佳答案
如果我理解正确的话:
changes context
| n | y |
accepts array n | func() | func.call() |
of arguments y | ???????? | func.apply() |
PHP 有一个函数,call_user_func_array
。不幸的是,JavaScript 在这方面缺乏。看起来您使用 eval()
模拟了这种行为。
Function.prototype.invoke = function(args) {
var i, code = 'this(';
for (i=0; i<args.length; i++) {
if (i) { code += ',' }
code += 'args[' + i + ']';
}
eval(code + ');');
}
是的,我知道。没有人喜欢 eval()
。它缓慢而危险。但是,在这种情况下,您可能不必担心跨站点脚本,至少,因为所有变量都包含在函数中。真的,JavaScript 没有用于此的 native 函数实在是太糟糕了,但我想我们有 eval
是针对这种情况的。
证明它有效:
function showArgs() {
for (x in arguments) {console.log(arguments[x]);}
}
showArgs.invoke(['foo',/bar/g]);
showArgs.invoke([window,[1,2,3]]);
Firefox 控制台输出:
--
[12:31:05.778] "foo"
[12:31:05.778] [object RegExp]
[12:31:05.778] [object Window]
[12:31:05.778] [object Array]
关于javascript - 是否可以在不更改上下文的情况下调用 function.apply?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12336044/