如何编写接受可变数量参数的Javascript函数,并将所有这些参数转发给其他匿名函数?

例如,考虑一个触发事件的方法的场景:

function fireStartedEvent(a,b,c,d,e,f,g,...) {
    for(var i = 0; i < startedListeners.length; i++) {
        startedListeners[i](a,b,c,d,e,f,g,...);
    }
}

特别是因为我有一个生成这些fire方法的事件工厂,所以这些方法无需知道给定事件或其处理程序消耗了多少参数。所以我现在在7点硬连线(a到g)。如果它没有,没问题。如果它已经存在,它们会被切断。我怎样才能捕获并传递所有参数?

感谢。

(在这里使用jQuery或任何其他Javascript框架不是一个选项。)

有帮助吗?

解决方案

解决这个问题需要了解两个JavaScript概念。

第一个是特殊的 arguments 局部变量,可用于在不知道其名称的情况下访问函数参数,它的工作方式类似于Array。但是, arguments 不是 Array ,而是“array like” - 具有名为 0..n-1 的属性,其中 n 是函数的参数个数和 length 属性 - 对象。一个简单的演示用法可能是:

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 将调用具有特定上下文的函数(调用时为 this ),其参数来自“数组”的扩展。宾语。 但请参阅 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 链接的警告:

  

注意:大多数浏览器,包括 Chrome 14 Internet Explorer 9 ,仍然不接受类似对象的数组,并会抛出异常[如果是非传递数组对象]。 [FireFox已在版本4中修复。]

值得庆幸的是,有一个相对简单的习惯用法来转换“数组”之类的“将对象转换为 Array (这是具有讽刺意味的,因为 Array.slice 通常使用像“对象”这样的数组:

var args = Array.prototype.slice.call(arguments);

(然后 args 可以普遍用于 Function.apply 。)

其他提示

我认为“适用”和“论据”这里有两个JavaScript概念:

function fireStartedEvent() {
  for (var i = 0; i < startedListeners.length; i++) {
    startedListeners[i].apply(startedListeners[i], arguments);
  }
}

这是我的Firebug控制台中的一些代码,我试过这个代码:

a = function(foo) { alert('a: ' + foo); };
b = function(foo, bar) { alert('b: ' + foo + ', ' + bar); };

startedListeners = [a, b];

function fireStartedEvent() {
  for (var i = 0; i < startedListeners.length; i++) {
    startedListeners[i].apply(startedListeners[i], arguments);
  }
}


fireStartedEvent('one', 'two');
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top