Передача массива в качестве параметра функции в JavaScript

292

Я хотел бы вызвать функцию, используя массив в качестве параметров:

const x = ['p0', 'p1', 'p2'];
call_me(x[0], x[1], x[2]); // I don't like it

function call_me (param0, param1, param2 ) {
  // ...
}

Есть ли лучший способ передачи содержимого xв call_me()?

Роберт
источник

Ответы:

422
const args = ['p0', 'p1', 'p2'];
call_me.apply(this, args);

Смотрите MDN документы для Function.prototype.apply().


Если среда поддерживает ECMAScript 6, вы можете использовать вместо этого аргумент распространения :

call_me(...args);
KaptajnKold
источник
9
В качестве примечания: если кто-то захочет вместо этого передать ассоциативный массив (именованные ключи), используйте объект. Исходя из PHP (и всегда приводил к этой теме Google), мне понадобилось время, чтобы выяснить. Тогда вы можете передать весь объект в качестве параметра. w3schools.com/js/js_objects.asp
timhc22
Спасибо за указание на аргумент «распространения»! Не знал об этом.
Томас Ан
@timhc - ваш комментарий к заметке интригует, но я не могу разобрать его (я нуб-яваскрипт, работающий через пару уроков). В JS ассоциативный массив - это объект согласно нескольким учебникам.
NateT
@ timhc22, и при использовании объекта json для передачи в качестве параметра функции не забывайте уничтожение параметров для лучшей читаемости
Мухаммед Омер Аслам
113

Почему бы вам не передать весь массив и не обработать его как нужно внутри функции?

var x = [ 'p0', 'p1', 'p2' ]; 
call_me(x);

function call_me(params) {
  for (i=0; i<params.length; i++) {
    alert(params[i])
  }
}
Карл Йохан
источник
37
Это потому, что я не могу изменить call_me (). Он определен в какой-то другой библиотеке, и с API невозможно связываться.
Роберт
62
+1, потому что, хотя он и не отвечает на первоначальный вопрос, это, вероятно, то, что искали пользователи из 100 000+, которые просматривали эту страницу.
Исикава
Может кто-нибудь объяснить, что делает строка call_me (x)? Кажется как это имя функции без ключевого слова function? Что именно он делает?
плавал
1
@swam Это вызов call_meфункции. Ему просто не хватает точки с запятой в конце.
SantiBailors
@swam запускает объявленную функцию call_me (params).
Хулио Родригес
43

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

var x = ['p0', 'p1', 'p2'];
call_me.apply(null, x);
plexer
источник
41

В стандарте ES6 есть новый оператор распространения, ... который делает именно это.

call_me(...x)

Он поддерживается всеми основными браузерами, кроме IE.

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

BoltKey
источник
1
новая ссылка: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Тим Мортон
7

Как ответил @KaptajnKold

var x = [ 'p0', 'p1', 'p2' ];
call_me.apply(this, x);

И вам не нужно определять все параметры для функции call_me. Вы можете просто использоватьarguments

function call_me () {
    // arguments is a array consisting of params.
    // arguments[0] == 'p0',
    // arguments[1] == 'p1',
    // arguments[2] == 'p2'
}
徐 竟 峰
источник
4
Это плохая практика ... вы не сможете увидеть, что нужно функции, и каждый параметр не является обязательным, если вы посмотрите на функцию.
Робин
3

Обратите внимание на это

function FollowMouse() {
    for(var i=0; i< arguments.length; i++) {
        arguments[i].style.top = event.clientY+"px";
        arguments[i].style.left = event.clientX+"px";
    }

};

// ---------------------------

HTML-страница

<body onmousemove="FollowMouse(d1,d2,d3)">

<p><div id="d1" style="position: absolute;">Follow1</div></p>
<div id="d2" style="position: absolute;"><p>Follow2</p></div>
<div id="d3" style="position: absolute;"><p>Follow3</p></div>


</body>

может вызывать функцию с любым аргументом

<body onmousemove="FollowMouse(d1,d2)">

или

<body onmousemove="FollowMouse(d1)">
ali.by
источник
Это явно часть ответа. Аргументы «безусловно» необходимы для возврата массива после вызова. Спасибо!
FlorianB
2

Аргументы функции также могут быть массивами:

function foo([a,b,c], d){
  console.log(a,b,c,d);
}

foo([1,2,3], 4)

Конечно, можно также использовать спред :

function foo(a, b, c, d){
  console.log(a, b, c, d);
}

foo(...[1, 2, 3], 4)

VSync
источник
2

При использовании оператора распространения мы должны отметить, что это должен быть последний или единственный переданный параметр. Иначе это не удастся.

function callMe(...arr){ //valid arguments
    alert(arr);
}

function callMe(name, ...arr){ //valid arguments
    alert(arr);
}

function callMe(...arr, name){ //invalid arguments
    alert(arr);
}

Если вам нужно передать массив в качестве начального аргумента, вы можете сделать:

function callMe(arr, name){
    let newArr = [...arr];
    alert(newArr);
}
Naba
источник
1

Вы можете использовать оператор распространения в более простой форме

[].concat(...array)

в случае функций, которые возвращают массивы, но ожидают передачи в качестве аргументов

Пример:

function expectArguments(...args){
  return [].concat(...args);
}

JSON.stringify(expectArguments(1,2,3)) === JSON.stringify(expectArguments([1,2,3]))
RMAN
источник
0

Ответ уже дан, но я просто хочу дать свой кусок пирога. То, чего вы хотите достичь, называется method borrowingв контексте JS, когда мы берем метод из объекта и вызываем его в контексте другого объекта. Весьма распространено брать методы массива и применять их к аргументам. Позвольте привести пример.

Итак, у нас есть «супер» хеш-функция, которая принимает два числа в качестве аргумента и возвращает «супер-безопасную» хэшированную строку:

function hash() {
  return arguments[0]+','+arguments[1];
}

hash(1,2); // "1,2" whoaa

Пока все хорошо, но у нас небольшая проблема с вышеуказанным подходом, он ограничен, работает только с двумя числами, который не является динамическим, давайте сделаем так, чтобы он работал с любым числом, и плюс вам не нужно передавать массив (вы можете если вы все еще настаиваете). Хорошо, хватит говорить, давай драться!

Естественным решением было бы использовать arr.joinметод:

function hash() {
  return arguments.join();
}

hash(1,2,4,..); //  Error: arguments.join is not a function

О чувак. К сожалению, это не сработает. Поскольку мы вызываем хеш (аргументы) и аргументы, объект является итеративным и похожим на массив, но не реальным массивом. Как насчет подхода ниже?

function hash() {
  return [].join.call(arguments);
}

hash(1,2,3,4); // "1,2,3,4" whoaa

Трюк называется method borrowing.

Мы заимствуем joinметод из обычного массива [].join.и используем его [].join.callдля запуска в контексте arguments.

Почему это работает?

Это потому, что внутренний алгоритм нативного метода arr.join(glue) очень прост.

Взято из спецификации почти «как есть»:

Let glue be the first argument or, if no arguments, then a comma ",".
Let result be an empty string.
Append this[0] to result.
Append glue and this[1].
Append glue and this[2].
Do so until this.length items are glued.
Return result.

Итак, технически он берет это и соединяет это [0], это [1] ... и т.д. вместе. Он намеренно написан так, что допускает любой массив, подобный этому (не случайно, многие методы следуют этой практике). Вот почему это также работает сthis=arguments.

Хумоюн Ахмад
источник