Wie bekomme ich ein Stück aus "Argumenten"?

80

Alles, was Sie wissen, argumentsist ein spezielles Objekt, das alle an die Funktion übergebenen Argumente enthält.

Und solange es sich nicht um ein Array handelt, können Sie so etwas nicht verwenden arguments.slice(1).

Also die Frage - wie schneidet man alles außer dem ersten Element ab arguments?

UPD :

Es scheint, als gäbe es keinen Weg, ohne es in ein Array mit zu konvertieren

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

Wenn jemand eine andere Lösung veröffentlicht, wäre es großartig, wenn nicht - ich werde die erste mit der obigen Zeile als Antwort überprüfen.

zerkms
quelle
+ zerkms es gibt in der Tat einen besseren Weg als es zu nehmen argumentsund in ein Array usw. umzuwandeln. Bitte siehe meine Antwort unten.
Umur Karagöz

Antworten:

20

Das Einmischen in Array-Funktionen ist eigentlich nicht notwendig.

Die Verwendung der Restparametersyntax ...rest ist sauberer und bequemer.

Beispiel

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");

...Sich ausruhen

Umur Karagöz
quelle
Ja, ich stimme zu, dass es heutzutage bequemer ist. Ich habe Sie positiv bewertet, aber ich werde die überprüfte 5 Jahre alte Antwort nicht nachträglich ändern.
Zerkms
2
Jetzt, nach einem weiteren Jahr, denke ich, ist es an der Zeit, auf die neuen ES-Standards
umzusteigen
dieses Gefühl, wenn Sie +15 Punkte für eine einjährige Antwort erhalten :-D
zerkms
133

Frage: Wie schneide ich alles außer dem ersten Element ab arguments?

Im Folgenden wird ein Array zurückgegeben, das alle Argumente außer dem ersten enthält:

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

Sie müssen nicht argumentszuerst in ein Array konvertieren , sondern alles in einem Schritt erledigen.

nnnnnn
quelle
Ich glaube, das hat einen Nachteil. Wenn es nur ein zusätzliches Argument gibt (außer dem ersten), wird nichts zurückgegeben.
Trevor
@Trevor - Nein, es wird ein Array mit einem Element zurückgegeben, das das zweite Argument ist. (Warum sollte es nichts zurückgeben?)
nnnnnn
4
Die Empfehlung hier besagt, dass Sie Slice nicht für Argumente verwenden sollten, da dies die Optimierung der JavaScript-Engine verhindert.
Jonathan Lin
1
Eine ausführlichere Erklärung finden Sie hier
David Chase
4
@ David - Der „im Detail“ Link sagt noch nicht zu verwenden , .slice()auf arguments, aber der einzige Grund ist , da es JS - Engine Optimierung der Funktion verhindert. Es ist also nicht so, dass es fehlschlägt, es könnte nur langsamer sein. Ich werde keinen Code schreiben, um die Optimierung in der JS-Engine des Tages zu berücksichtigen, nicht, wenn die Engine von morgen das Optimierungsproblem gelöst haben könnte, und auf jeden Fall wird der Unterschied für den Benutzer wahrscheinlich in den meisten Fällen nicht wahrnehmbar sein Fälle. Es ist besser, zuerst klaren und einfach zu wartenden Code zu schreiben und dann nur dann zurückzukehren und zu optimieren, wenn ein messbares Leistungsproblem auftritt.
nnnnnn
11

Sie können "schneiden, ohne zu schneiden", indem Sie das Argumentobjekt prozedural durchlaufen:

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]
Paul Rosania
quelle
2
Ja, es macht die Arbeit aber macht keinen Sinn , für den Fall , wir haben ein .slice();-)
zerkms
Natürlich ist es einfacher zu bedienen Array.prototype.slice, aber Ihre Frage war, ob es einen anderen Weg gibt.
Paul Rosania
ja, danke dafür ;-) (obwohl ich offensichtlich weiß über for:-P)
zerkms
Haha, ich hoffe ich klang nicht banal. Manchmal sind es nützliche Informationen zu SO!
Paul Rosania
3
+1 Dies scheint die einzig richtige Lösung für V8 zu sein. Schauen Sie sich das Optimierungs-Benchmarking hier an: jsperf.com/leaky-args
Tom Auger
11

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

Sie sollten nicht auf Argumente verzichten, da dies Optimierungen in JavaScript-Engines (z. B. V8) verhindert. Versuchen Sie stattdessen, ein neues Array zu erstellen, indem Sie das Argumentobjekt durchlaufen.

Die obige Antwort von Paul Rosiana ist also richtig

Bluescrubbie
quelle
4
Vielleicht so. Aber ich sehe nicht, wie Optimierungs-Engines den Einzeiler der akzeptierten Antwort nicht so behandeln und optimieren können, wie sie es wünschen. Auf lange Sicht ist es immer ein Ärgernis, wenn wir anfangen, für die Optimierer (des Tages) zu codieren - ich persönlich bevorzuge die Klarheit des Codes.
Akauppi
2
'Slice' ändert sich nicht. Es wird eine flache Kopie der Elemente aus dem ursprünglichen Array zurückgegeben. Elemente des ursprünglichen Arrays werden in das zurückgegebene Array kopiert. Daher kann ich nicht verstehen, was der Unterschied zwischen manuellem Kopieren in ein neues Array und Slice ist.
Maxim
Ab 2018 ist die Warnung nicht mehr da. Wir sollten in Sicherheit sein, denke ich.
GBF_Gabriel
9

Dies kann ein Weg sein:

var args = Array.from(arguments).slice(1);
Di Tran
quelle
In diesen Tagen ist es überhaupt nicht notwendig:function foo(...args)
Zerkms
@zerkms Ich wollte Ihren Vorschlag aus Leistungsgründen ablehnen, aber mein Test zeigt Ruheparameter als die schnellste Lösung! gist.github.com/18d590d12aef1e90d2ed262f4fab0c96
Cody Allan Taylor
@ CodAllanTaylor-Implementierungen verbessern sich. Wenn Sie keinen wirklich, wirklich, wirklich wichtigen Grund haben, dies nicht zu
tun
0

Sie können die Methode verwenden [].slice.call(arguments, 1)

[] .slice gibt Ihnen das Slice-Funktionsobjekt zurück und Sie können es als argumentsund 1die Parameter aufrufen

Thierryk
quelle
Haben Sie Änderungen vorgenommen, bevor Sie Ihre Antworten veröffentlicht haben? Die identische (und sogar etwas bessere, da sie kein Wegwerfarray zuweist) Antwort wurde bereits veröffentlicht und überprüft.
Zerkms
0

Sie können ... rest innerhalb der Funktion verwenden, um das erste und den Rest der Argumente zu trennen:

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)

ntarlapan
quelle
Ja, die Zukunft ist endlich da :-D
zerkms