Gibt es eine Möglichkeit, "unbegrenzte" Variablen für eine Funktion in JavaScript zuzulassen?
Beispiel:
load(var1, var2, var3, var4, var5, etc...)
load(var1)
Gibt es eine Möglichkeit, "unbegrenzte" Variablen für eine Funktion in JavaScript zuzulassen?
Beispiel:
load(var1, var2, var3, var4, var5, etc...)
load(var1)
Antworten:
Sicher, benutze einfach das arguments
Objekt.
function foo() {
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
arguments
ist ein spezielles "Array-ähnliches" Objekt, dh es hat eine Länge, aber keine anderen Array-Funktionen. Weitere Informationen finden Sie unter developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… und diese Antwort: stackoverflow.com/a/13145228/1766230
length
Eigenschaft funktionieren . Dies schließt das arguments
Objekt ein. Dies und das wissen die Methodeconcat
wir eine Kopie des aufgerufenen 'Arrays' zurückgibt , können wir das arguments
Objekt leicht in ein reales Array wie das folgende konvertieren : var args = [].concat.call(arguments)
. Einige Leute bevorzugen es Array.prototype.concat.call
stattdessen zu verwenden , aber ich mag das []
, sie sind kurz und süß!
[...arguments].join()
In (den meisten) neuesten Browsern können Sie eine variable Anzahl von Argumenten mit folgender Syntax akzeptieren:
function my_log(...args) {
// args is an Array
console.log(args);
// You can pass this array as parameters to another function
console.log(...args);
}
Hier ist ein kleines Beispiel:
function foo(x, ...args) {
console.log(x, args, ...args, arguments);
}
foo('a', 'b', 'c', z='d')
=>
a
Array(3) [ "b", "c", "d" ]
b c d
Arguments
0: "a"
1: "b"
2: "c"
3: "d"
length: 4
Dokumentation und weitere Beispiele hier: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters
Eine andere Möglichkeit besteht darin, Ihre Argumente in einem Kontextobjekt zu übergeben.
function load(context)
{
// do whatever with context.name, context.address, etc
}
und benutze es so
load({name:'Ken',address:'secret',unused:true})
Dies hat den Vorteil, dass Sie so viele benannte Argumente hinzufügen können, wie Sie möchten, und die Funktion kann sie nach Belieben verwenden (oder nicht).
context
Argument mit Code erstellen und weitergeben, bevor es verwendet wird.
Ich stimme Kens Antwort als die dynamischste zu und gehe noch einen Schritt weiter. Wenn es sich um eine Funktion handelt, die Sie mehrmals mit unterschiedlichen Argumenten aufrufen, verwende ich Kens Design, füge dann aber Standardwerte hinzu:
function load(context) {
var defaults = {
parameter1: defaultValue1,
parameter2: defaultValue2,
...
};
var context = extend(defaults, context);
// do stuff
}
Auf diese Weise können Sie, wenn Sie viele Parameter haben, diese aber nicht unbedingt bei jedem Aufruf der Funktion festlegen müssen, einfach die Nicht-Standardwerte angeben. Für die Extend-Methode können Sie die Extend-Methode ( $.extend()
) von jQuery verwenden , Ihre eigene erstellen oder Folgendes verwenden:
function extend() {
for (var i = 1; i < arguments.length; i++)
for (var key in arguments[i])
if (arguments[i].hasOwnProperty(key))
arguments[0][key] = arguments[i][key];
return arguments[0];
}
Dadurch wird das Kontextobjekt mit den Standardeinstellungen zusammengeführt und alle undefinierten Werte in Ihrem Objekt mit den Standardeinstellungen gefüllt.
_.defaults()
Methode von Underscore ist eine sehr schöne Alternative zum Zusammenführen angegebener und Standardargumente.
Es ist vorzuziehen, die Restparametersyntax zu verwenden, wie Ramast hervorhob.
function (a, b, ...args) {}
Ich möchte nur eine nette Eigenschaft des Arguments ... args hinzufügen
- Es ist ein Array und kein Objekt wie Argumente. Auf diese Weise können Sie Funktionen wie Map oder Sort direkt anwenden.
- Es enthält nicht alle Parameter, sondern nur den von ihm weitergegebenen. ZB Funktion (a, b, ... args) in diesem Fall enthält args das Argument 3 bis argument.length
Wie bereits erwähnt, können Sie die verwenden arguments
Objekt eine variable Anzahl von Funktionsparametern abrufen.
Wenn Sie eine andere Funktion mit denselben Argumenten aufrufen möchten, verwenden Sie apply
. Sie können sogar Argumente hinzufügen oder entfernen, indem Sie sie arguments
in ein Array konvertieren . Diese Funktion fügt beispielsweise Text ein, bevor Sie sich an der Konsole anmelden:
log() {
let args = Array.prototype.slice.call(arguments);
args = ['MyObjectName', this.id_].concat(args);
console.log.apply(console, args);
}
Obwohl ich im Allgemeinen der Meinung bin, dass der Ansatz der benannten Argumente nützlich und flexibel ist (es sei denn, Sie interessieren sich für die Reihenfolge, in welchem Fall Argumente am einfachsten sind), habe ich Bedenken hinsichtlich der Kosten des mbeasley-Ansatzes (unter Verwendung von Standardeinstellungen und Erweiterungen). Dies ist ein extrem hoher Kostenaufwand für das Abrufen von Standardwerten. Zunächst werden die Standardeinstellungen innerhalb der Funktion definiert, sodass sie bei jedem Aufruf neu gefüllt werden. Zweitens können Sie die benannten Werte leicht auslesen und gleichzeitig die Standardeinstellungen mit || festlegen. Es ist nicht erforderlich, ein weiteres neues Objekt zu erstellen und zusammenzuführen, um diese Informationen abzurufen.
function load(context) {
var parameter1 = context.parameter1 || defaultValue1,
parameter2 = context.parameter2 || defaultValue2;
// do stuff
}
Dies ist ungefähr die gleiche Menge an Code (möglicherweise etwas mehr), sollte aber einen Bruchteil der Laufzeitkosten ausmachen.
(parameter1=context.parameter1)===undefined && (parameter1=defaultValue1)
oder für weniger Codevolumen function def(providedValue, default) {return providedValue !== undefined ? providedValue : defaultValue;} var parameter1 = def(context.parameter1, defaultValue1)
bietet eine kleine Hilfsfunktion Folgendes an: Bereitstellung alternativer Muster. Mein Punkt bleibt jedoch bestehen: Das Erstellen zusätzlicher Objekte für jeden Funktionsaufruf und das Ausführen teurer Schleifen zum Festlegen einiger Standardwerte ist ein verrückter Aufwand.
Während @roufamatic die Verwendung des Argument-Schlüsselworts zeigte und @Ken ein großartiges Beispiel für ein zu verwendendes Objekt zeigte, habe ich das Gefühl, dass weder wirklich angesprochen wurde, was in diesem Fall vor sich geht, noch zukünftige Leser verwirren oder eine schlechte Praxis einflößen könnte, wenn keine Funktion explizit angegeben wird / method soll eine variable Anzahl von Argumenten / Parametern annehmen.
function varyArg () {
return arguments[0] + arguments[1];
}
Wenn ein anderer Entwickler Ihren Code durchsucht, ist es sehr einfach anzunehmen, dass diese Funktion keine Parameter akzeptiert. Insbesondere, wenn dieser Entwickler nicht mit dem Argument- Schlüsselwort vertraut ist. Aus diesem Grund ist es eine gute Idee, eine Stilrichtlinie zu befolgen und konsequent zu sein. Ich werde Google für alle Beispiele verwenden.
Lassen Sie uns explizit angeben, dass dieselbe Funktion variable Parameter hat:
function varyArg (var_args) {
return arguments[0] + arguments[1];
}
Es kann vorkommen, dass ein Objekt benötigt wird, da es die einzige genehmigte und als Best-Practice-Methode angesehene Methode einer Datenkarte ist. Assoziative Arrays werden verpönt und entmutigt.
SIDENOTE: Das Argument-Schlüsselwort gibt tatsächlich ein Objekt zurück, wobei Zahlen als Schlüssel verwendet werden. Die prototypische Vererbung ist auch die Objektfamilie. Informationen zur ordnungsgemäßen Verwendung des Arrays in JS finden Sie am Ende der Antwort
In diesem Fall können wir dies auch explizit angeben. Hinweis: Diese Namenskonvention wird nicht von Google bereitgestellt, sondern ist ein Beispiel für die explizite Deklaration des Parametertyps. Dies ist wichtig, wenn Sie ein strengeres typisiertes Muster in Ihrem Code erstellen möchten.
function varyArg (args_obj) {
return args_obj.name+" "+args_obj.weight;
}
varyArg({name: "Brian", weight: 150});
Dies hängt von den Anforderungen Ihrer Funktion und Ihres Programms ab. Wenn Sie beispielsweise einfach eine Wertebasis für einen iterativen Prozess über alle übergebenen Argumente zurückgeben möchten, bleiben Sie mit Sicherheit beim Schlüsselwort argument . Wenn Sie eine Definition Ihrer Argumente und eine Zuordnung der Daten benötigen, ist die Objektmethode der richtige Weg. Schauen wir uns zwei Beispiele an und dann sind wir fertig!
function sumOfAll (var_args) {
return arguments.reduce(function(a, b) {
return a + b;
}, 0);
}
sumOfAll(1,2,3); // returns 6
function myObjArgs(args_obj) {
// MAKE SURE ARGUMENT IS AN OBJECT OR ELSE RETURN
if (typeof args_obj !== "object") {
return "Arguments passed must be in object form!";
}
return "Hello "+args_obj.name+" I see you're "+args_obj.age+" years old.";
}
myObjArgs({name: "Brian", age: 31}); // returns 'Hello Brian I see you're 31 years old
Wie oben in der Antwort erwähnt, gibt das Argument- Schlüsselwort tatsächlich ein Objekt zurück. Aus diesem Grund muss jede Methode aufgerufen werden, die Sie für ein Array verwenden möchten. Ein Beispiel dafür:
Array.prototype.map.call(arguments, function (val, idx, arr) {});
Um dies zu vermeiden, verwenden Sie den Rest-Parameter:
function varyArgArr (...var_args) {
return var_args.sort();
}
varyArgArr(5,1,3); // returns 1, 3, 5
Verwenden Sie das arguments
Objekt innerhalb der Funktion, um Zugriff auf alle übergebenen Argumente zu erhalten.
Beachten Sie, dass das Übergeben eines Objekts mit benannten Eigenschaften, wie von Ken vorgeschlagen, die Kosten für das Zuweisen und Freigeben des temporären Objekts für jeden Aufruf erhöht. Das Übergeben normaler Argumente als Wert oder Referenz ist im Allgemeinen am effizientesten. Für viele Anwendungen ist die Leistung zwar nicht kritisch, für einige jedoch.