Передача аргументов в другую функцию JavaScript

386

Я попробовал следующее безуспешно:

function a(args){
    b(arguments);
}

function b(args){
    // arguments are lost?
}

a(1,2,3);

В функции a я могу использовать ключевое слово arguments для доступа к массиву аргументов, в функции b они потеряны. Есть ли способ передачи аргументов в другую функцию JavaScript, как я пытаюсь сделать?

Андерс Нюгаард
источник
3
@ BobStein-VisiBone Согласен. Кроме того , обратите внимание , что argumentsэто не на самом деле массив (а скорее объект , который реализует массив типа семантики ) и поэтому не совсем понятно , на первый взгляд , может ли он использоваться таким же образом , как реальный массив может.
Жюль
@Jules все еще голосуют, чтобы снова открыться после всех этих лет. Какой знак для сжигания чужой ценной работы? Много тех, чтобы обойти.
Боб Стейн

Ответы:

542

Используйте, .apply()чтобы иметь такой же доступ к argumentsфункции b, как это:

function a(){
    b.apply(null, arguments);
}
function b(){
   alert(arguments); //arguments[0] = 1, etc
}
a(1,2,3);​

Вы можете проверить это здесь .

Ник Крейвер
источник
21
@Brett - Вы можете скопировать его в массив, а затем манипулировать им перед передачей, например:var copy = [].slice.call(arguments); <remove what you want> myFunc.apply(this, copy);
Ник Крейвер
18
но использование applyэтого может привести к искажению области видимости b(например, если это какая-то внутренняя функция объекта)
vsync
3
@vsync хорошая мысль, но проблему легко решить: передайте объект в качестве первого аргумента для применения.
Тэд Лиспи
11
не имеет смысла использовать «аргументы» и «аргументы» вместе ...
чувак
3
Но тогда «это» может быть изменено на что-то отличное от оригинального слова «это».
trusktr
223

Оператор спреда

Оператор распространения позволяет развернуть выражение в местах, где ожидаются несколько аргументов (для вызовов функций) или несколько элементов (для литералов массива).

В ECMAScript ES6 добавлен новый оператор, который позволяет вам сделать это более практичным способом: ... Spread Operator .

Пример без использования applyметода:

function a(...args){
  b(...args);
  b(6, ...args, 8) // You can even add more elements
}
function b(){
  console.log(arguments)
}

a(1, 2, 3)

Note Этот фрагмент возвращает синтаксическую ошибку, если ваш браузер все еще использует ES5.

Примечание редактора: так как фрагмент использует console.log(), вы должны открыть консоль JS вашего браузера, чтобы увидеть результат - на странице не будет никакого результата.

Это покажет этот результат:

Изображение примера аргументов оператора Spread

Короче говоря, оператор распространения может использоваться для разных целей, если вы используете массивы, поэтому его также можно использовать для аргументов функций, вы можете увидеть похожий пример, объясненный в официальных документах: Параметры отдыха

Уолтер Чапилликен - wZVanG
источник
6
Это очень хороший оператор, и я с нетерпением жду его использования. Однако этого пока не произойдет. Единственный браузер, который уже поддерживает оператор распространения, - это FF на данный момент. См. Таблицу совместимости для получения полных и актуальных данных: kangax.github.io/compat-table/es6/#spread_%28...%29_operator
TMG
10
Почему бы его не использовать? Это довольно легко переносить с помощью babel, вы получаете все новые функции и гораздо больше совместимости со старыми браузерами.
adgelbfish
Это лучше, чем первое решение, потому что оно работает в функции, определенной с помощью оператора стрелки.
Сарфата
Вам не нужно ...argsв aфункции. Вы можете просто создать функцию без аргументов и передать их с bпомощью...arguments
cronoklee
1
Для любого, кто читает этот ответ: В отличие от комментария @ cronoklee, явное указание в ...argsкачестве aввода может быть важным, если у вас есть вложенные функции.
Arshia001
81

Объяснение, которое не дает ни один из других ответов, состоит в том, что исходные аргументы все еще доступны, но не в исходной позиции в argumentsобъекте.

argumentsОбъект содержит один элемент для каждого фактического параметра , предоставленного функцией. При вызове aвы поставляете три аргумента: числа 1, 2, и, 3. Итак, argumentsсодержит [1, 2, 3].

function a(args){
    console.log(arguments) // [1, 2, 3]
    b(arguments);
}

Когда вы звоните b, однако, вы передаете точно один аргумент: a«s argumentsобъект. Таким образом , argumentsсодержит [[1, 2, 3]](т.е. один элемент, который является a«s argumentsобъект, который имеет свойство , содержащее исходные аргументы a).

function b(args){
    // arguments are lost?
    console.log(arguments) // [[1, 2, 3]]
}

a(1,2,3);

Как продемонстрировал @Nick, вы можете использовать applyдля предоставления argumentsобъекта set в вызове.

Следующее достигает того же результата:

function a(args){
    b(arguments[0], arguments[1], arguments[2]); // three arguments
}

Но applyэто правильное решение в общем случае.

Wayne
источник
Вы должны всегда переходить thisк apply?
Flimm
1
@ Flimm - да, поскольку аргументы являются вторым аргументом, для первого аргумента должно быть что-то (может быть нулевым ).
RobG
0

попробуй это

function global_func(...args){
  for(let i of args){
    console.log(i)
  }
}


global_func('task_name', 'action', [{x: 'x'},{x: 'x'}], {x: 'x'}, ['x1','x2'], 1, null, undefined, false, true)




//task_name
//action
//(2) [{...},
//    {...}]
//    {
//        x:"x"
//    }
//(2) [
//        "x1",
//        "x2"
//    ]
//1
//null
//undefined
//false
//true
//func
Джабер Альшами
источник