例如,考虑触发事件的方法的场景:
function fireStartedEvent(a,b,c,d,e,f,g,...) { for(var i = 0; i < startedListeners.length; i++) { startedListeners[i](a,...); } }
特别是因为我有一个生成这些消防方法的事件工厂,所以这些方法无需知道给定事件或其处理程序消耗了多少参数.所以我现在在7点硬连线(a到g).如果它没有,没问题.如果它已经存在,它们会被切断.我怎样才能捕获并传递所有参数?
谢谢.
(在这里使用jQuery或任何其他Javascript框架不是一个选项.)
解决方法
第一个是特殊的arguments
局部变量,可用于访问函数参数而不知道它们的名称,它就像一个数组.但是,参数不是数组,而是“数组类似” – 具有名为0..n-1的属性,其中n是函数的参数数量和长度属性 – 对象.一个简单的演示用法可能是:
function f (a) { // can include names still,if desired // arguments instanceof Array -> false (exceptions to this?) var firstArg = arguments[0] // a === firstArg -> always true // iterate all arguments,just as if it were an Array: for (var i = 0; i < arguments.length; i++) { alert(i + " : " + arguments[i]) } } f("a","b","c")
第二个特性是Function.apply
,它将调用具有特定上下文的函数(在调用它时),其参数是由“数组类似”对象的扩展产生的.但是看1.
因此,把它放在一起:
function fireStartedEvent() { for(var i = 0; i < startedListeners.length; i++) { // jQuery will often pass in "cute" things,such as a element clicked // as the context. here we just pass through the current context,`this`,// as well as the arguments we received. var arg = Array.prototype.slice.call(arguments) startedListeners[i].apply(this,args) } }
1虽然ECMAScript规范只调用“数组类似”对象,但Function.apply并不普遍使用“数组类似”对象,并且许多常见实现需要适当的Array对象. Function.apply链接的警告:
Note: Most browsers,including Chrome 14 and Internet Explorer 9,still do not accept array like objects and will throw an exception [if a non-Array object is passed]. [FireFox was fixed in version 4.]
值得庆幸的是,有一个相对简单的习惯用法将“数组类似”对象转换为数组(这很具有讽刺意味,因为Array.slice通常使用“数组类似”对象):
var args = Array.prototype.slice.call(arguments);
(然后args可以普遍用于Function.apply.)