Как получить кусочек от «аргументов»

80

Все, что вы знаете, arguments- это специальный объект, который содержит все аргументы, переданные функции.

И пока это не массив - вы не можете использовать что-то вроде arguments.slice(1).

Итак, вопрос - как вырезать все, кроме первого элемента arguments?

UPD :

похоже, что нет способа без преобразования его в массив с

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

Если кто-то опубликует другое решение, было бы здорово, если нет - я проверю первое со строкой выше в качестве ответа.

Зеркмс
источник
+ zerkms действительно есть способ лучше, чем argumentsпреобразование его в массив и т. д. См. мой ответ ниже.
Karagöz

Ответы:

20

На самом деле нет необходимости вмешиваться в функции массива.

Использование синтаксиса параметра rest ...rest более чистое и удобное.

пример

function argumentTest(first, ...rest) {
  console.log("First arg:" + first);

  // loop through the rest of the parameters
  for (let arg of rest) {
    console.log("- " + arg);
  }
}

// call your function with any number of arguments
argumentTest("first arg", "#2", "more arguments", "this is not an argument but a contradiction");

...Остаток

Умур Карагёз
источник
Да, согласен, сейчас так удобнее. Я проголосовал за вас, но я не буду ретроспективно менять проверенный 5-летний ответ.
zerkms
2
Теперь, по прошествии еще одного года, я думаю, что пора перейти на новые стандарты ES :-)
zerkms
это чувство, когда ты получаешь +15 баллов за ответ годовалого :-D
zerkms
133

В. Как вырезать все, кроме первого элемента arguments?

Следующее вернет массив, содержащий все аргументы, кроме первого:

var slicedArgs = Array.prototype.slice.call(arguments, 1);

Вам не нужно argumentsсначала преобразовывать в массив, сделайте все за один шаг.

ннннн
источник
Я считаю, что у этого есть обратная сторона. Если есть только один дополнительный аргумент (помимо первого), ничего не возвращается.
Trevor
@Trevor - Нет, он возвращает массив с одним элементом, который является вторым аргументом. (Почему он ничего не возвращает?)
nnnnnn
4
Рекомендация здесь гласит, что вы не должны использовать срез для аргументов, потому что это препятствует оптимизации движка JavaScript.
Джонатан Лин
1
более подробное объяснение можно найти здесь
Дэвид Чейз
4
@David - The «подробно» ссылка все еще говорит , что не использовать .slice()на arguments, но единственная причина , учитывая то , что это предотвращает JS двигателя оптимизации функции. Так что это не значит, что он не работает, просто он может быть медленнее. Я не собираюсь писать код для оптимизации в движке JS дня, не тогда, когда движок завтрашнего дня мог бы решить проблему оптимизации, и в любом случае разница, вероятно, не будет заметна пользователю в большинстве случаев. случаи. Лучше сначала написать ясный и простой в обслуживании код, а затем возвращаться и оптимизировать, только если возникает измеримая проблема с производительностью.
nnnnnn
11

Вы можете «нарезать без нарезки» процедурным обходом объекта arguments:

function fun() {
  var args = [];

  for (var i = 1; i < arguments.length; i++) {
    args.push(arguments[i]);
  }

  return args;
}

fun(1, 2, 3, 4, 5); //=> [2, 3, 4, 5]
Пол Росания
источник
2
Да, это работает, но не имеет смысла, если у нас есть .slice();-)
zerkms 01
Конечно, проще в использовании Array.prototype.slice, но ваш вопрос был в том, есть ли другой способ.
Пол Розания 01
да, спасибо за это ;-) (хотя, очевидно, я знаю про for:-P)
zerkms 01
Ха-ха, надеюсь, я не звучал банально. Иногда это полезная информация о SO!
Пол Розания 02
3
+1 Кажется, это единственно правильное решение для V8. Взгляните на тесты оптимизации здесь: jsperf.com/leaky-args
Том
11

Из https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments :

Вы не должны нарезать аргументы, потому что это предотвращает оптимизацию в движках JavaScript (например, V8). Вместо этого попробуйте создать новый массив, перебирая объект arguments.

Итак, ответ Пола Розианы выше правильный

блюскрабби
источник
4
Может быть и так. Но я не понимаю, как движки оптимизации не могли обработать однострочник принятого ответа и оптимизировать его так, как они хотят. Если мы начнем писать код для оптимизаторов (сегодняшнего дня), то в долгосрочной перспективе всегда будет неприятно - лично я предпочитаю ясность кода.
akauppi
2
'slice' не изменяется. Он возвращает мелкую копию элементов из исходного массива. Элементы исходного массива копируются в возвращаемый массив. Поэтому я не могу понять, в чем разница между ручным копированием в новый массив и срез.
Максим
По состоянию на 2018 год предупреждения больше нет. Думаю, мы должны быть в безопасности.
GBF_Gabriel
9

Это может быть способ:

var args = Array.from(arguments).slice(1);
Ди Тран
источник
В наши дни в этом нет необходимости:function foo(...args)
zerkms
@zerkms Я собирался отклонить ваше предложение по соображениям производительности, но мой тест показывает параметры отдыха как самое быстрое решение! gist.github.com/18d590d12aef1e90d2ed262f4fab0c96
Коди Аллан Тейлор
Реализации @CodyAllanTaylor улучшаются. Если у вас нет действительно-очень-очень важной причины не делать этого, я бы придерживался более удобочитаемого синтаксиса
zerkms
0

Вы можете использовать метод [].slice.call(arguments, 1)

[] .slice вернет вам объект функции ломтика , и вы можете назвать это как argumentsи 1те параметры

Тьеррик
источник
Какие изменения вы проверили в опубликованных ответах, прежде чем публиковать свои? Точно такой же (и даже немного лучше, поскольку он не выделяет одноразовый массив) ответ уже опубликован и проверен.
zerkms 01
0

Вы можете использовать ... rest внутри функции для разделения первого и остальных аргументов:

function foo(arr) {
  const [first, ...rest] = arguments;
  console.log(`first = ${first}`);
  console.log(`rest = ${rest}`);
}
//Then calling the function with 3 arguments:
foo(1,2,3)

Нтарлапан
источник
Ура, будущее наконец-то
наступило