Як отримати фрагмент з “аргументів”


80

Все, що ви знаєте, arguments- це спеціальний об’єкт, який містить усі аргументи, передані функції.

І поки це не масив - ви не можете використовувати щось подібне arguments.slice(1).

Тож питання - як нарізати все, крім першого елемента arguments?

UPD :

здається, що неможливо без перетворення його в масив за допомогою

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

Якщо хтось опублікує інше рішення, було б чудово, якщо ні - я перевірю перше із рядком вище як відповідь.


+ zerkms дійсно є кращий спосіб, ніж взяти argumentsта перетворити його на масив тощо. Будь ласка, дивіться мою відповідь нижче.
Умур Караґоз,

Відповіді:


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 - Ні, він повертає масив з одним елементом, який є другим аргументом. (Чому це нічого не поверне?)
nnnnnn

4
Рекомендація тут йдеться , що ви не повинні використовувати скибочку на аргументи , оскільки він перешкоджає оптимізації двигуна JavaScript.
Джонатан Лін,

1
більш докладне пояснення можна знайти тут
Девід Чейз

4
@David - The «детально» посилання все ще говорить , що не використовувати .slice()на arguments, але єдина причина , з огляду на те , що це запобігає JS двигуна оптимізації функції. Отже, справа не в тому, що це не вдається, це може бути повільніше. Я не збираюся писати код для забезпечення оптимізації в JS-двигуні дня, ані тоді, коли механізм завтрашнього дня може вирішити проблему оптимізації, і в будь-якому випадку різниця, мабуть, не буде відчутною для користувача в більшості справ. Краще спочатку написати чіткий і простий у обслуговуванні код, а потім повернутися і оптимізувати лише у випадку, якщо виникає помірна проблема продуктивності.
nnnnnn

11

Ви можете "нарізати без нарізки", процедурно прогулявши об'єкт аргументів:

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

Звичайно, це простіше у використанні Array.prototype.slice, але ваше запитання було, чи був інший спосіб.
Paul Rosania

так, дякую за це ;-) (хоча, очевидно, я знаю про for:-P)
zerkms

Ха-ха, сподіваюся, я не прозвучав банально. Іноді це корисна інформація про SO!
Paul Rosania,

3
+1 Це, здається, єдино правильне рішення для V8. Подивіться на тести оптимізації тут: jsperf.com/leaky-args
Tom Auger

11

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

Не слід нарізати аргументи, оскільки це перешкоджає оптимізації в механізмах JavaScript (наприклад, V8). Натомість спробуйте побудувати новий масив, перебираючи об’єкт аргументів.

Тож відповідь Пола Розіани вище є правильною


4
Можливо так. Але я не бачу, як механізми оптимізації не могли поводитися з однокласниками прийнятої відповіді та оптимізувати їх як завгодно. Зрештою це завжди неприємність, якщо ми починаємо кодувати оптимізатори (дня) - особисто я віддаю перевагу чіткості коду.
akauppi

2
'зріз' не змінює. Він повертає дрібну копію елементів з вихідного масиву. Елементи вихідного масиву копіюються у повернутий масив. Тому я не можу зрозуміти, в чому різниця між ручним копіюванням на новий масив та зрізом.
Максим

Станом на 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

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)


Так, майбутнє вже, нарешті :-D
zerkms
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.