Как написать JS-функцию, которая принимает и “пересылает” переменное количество параметров?

StackOverflow https://stackoverflow.com/questions/1619850

Вопрос

Как мне написать функцию 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 локальная переменная, которую можно использовать для доступа к аргументам функции, не зная их имени, и она работает как массив.Однако, arguments является не ан Array, но является "подобным массиву" - имеющим свойства с именами 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 Ссылка:

Примечание: Большинство браузеров, включая Хром 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