Mat*_*ins 33 javascript function node.js
在一些Javascript代码(具体是node.js)中,我需要使用一组未知的参数调用函数而不更改上下文.例如:
function fn() {
var args = Array.prototype.slice.call(arguments);
otherFn.apply(this, args);
}
Run Code Online (Sandbox Code Playgroud)
上面的问题是,当我调用时apply,我通过传递this第一个参数来改变上下文.我想传递args给被调用的函数而不改变被调用函数的上下文.我基本上想要这样做:
function fn() {
var args = Array.prototype.slice.call(arguments);
otherFn.apply(<otherFn's original context>, args);
}
Run Code Online (Sandbox Code Playgroud)
编辑:添加有关我特定问题的更多详细信息.我正在创建一个Client类,其中包含一个socket(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]
Run Code Online (Sandbox Code Playgroud)
请注意,这clientListenerId是一个自定义唯一标识符属性,与此处的答案基本相同.
' this' 是对函数上下文的引用.这才是真正的重点.
如果你的意思是在这样的不同对象的上下文中调用它:
otherObj.otherFn(args)
Run Code Online (Sandbox Code Playgroud)
然后简单地将该对象替换为上下文:
otherObj.otherFn.apply(otherObj, args);
Run Code Online (Sandbox Code Playgroud)
那应该是它.
如果我理解正确的话:
changes context
| n | y |
accepts array n | func() | func.call() |
of arguments y | ???????? | func.apply() |
Run Code Online (Sandbox Code Playgroud)
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 + ');');
}
Run Code Online (Sandbox Code Playgroud)
是的我知道.没有人喜欢eval().这是缓慢而危险的.但是,在这种情况下,您可能不必担心跨站点脚本,至少,因为所有变量都包含在函数中.实际上,JavaScript没有本机功能太糟糕了,但我想这就是我们拥有的这种情况eval.
证明它有效:
function showArgs() {
for (x in arguments) {console.log(arguments[x]);}
}
showArgs.invoke(['foo',/bar/g]);
showArgs.invoke([window,[1,2,3]]);
Run Code Online (Sandbox Code Playgroud)
Firefox控制台输出:
--
[12:31:05.778] "foo"
[12:31:05.778] [object RegExp]
[12:31:05.778] [object Window]
[12:31:05.778] [object Array]
Run Code Online (Sandbox Code Playgroud)
简单地说,只需将其指定为您想要的,即otherFn:
function fn() {
var args = Array.prototype.slice.call(arguments);
otherFn.apply(otherFn, args);
}
Run Code Online (Sandbox Code Playgroud)
小智 5
如果将函数绑定到对象,并且在任何地方都使用绑定函数,则可以使用 null 调用 apply,但仍然可以获得正确的上下文
var Person = function(name){
this.name = name;
}
Person.prototype.printName = function(){
console.log("Name: " + this.name);
}
var bob = new Person("Bob");
bob.printName.apply(null); //window.name
bob.printName.bind(bob).apply(null); //"Bob"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10065 次 |
| 最近记录: |