MDN explique :
les arguments sont un objet de type tableau. Représente la liste de paramètres transmise à une fonction.
Utilisons d'abord un exemple pour comprendre intuitivement à quoi ressemblent les arguments en JavaScript.
function printArgs() { console.log(arguments); } printArgs("A", "a", 0, { foo: "Hello, arguments" });
Le résultat de l'exécution est :
["A", "a", 0, Object]
À première vue, le résultat est un tableau, mais ce n'est pas un vrai tableau, donc les arguments sont un objet de type tableau ( si vous voulez connaître le vrai (la différence entre les tableaux et les objets de type tableau peut être lue jusqu'à la fin).
Regardez le contenu représenté par les arguments, qui représentent tous les paramètres passés dans la fonction lorsque la fonction est exécutée. Dans l'exemple ci-dessus, il représente les quatre paramètres passés dans la fonction printArgs
Vous pouvez utiliser arguments[0]
, arguments[1]
... pour obtenir un seul paramètre.
arguments est un objet de type tableau, qui contient un attribut length
Vous pouvez utiliser arguments.length
pour obtenir le. paramètres passés dans la fonction.
function func() { console.log("The number of parameters is " + arguments.length); } func(); func(1, 2); func(1, 2, 3);
Le résultat de l'exécution est le suivant :
The number of parameters is 0 The number of parameters is 2 The number of parameters is 3
Utilisez généralement la méthode suivante pour convertir les arguments en tableau :
Array.prototype.slice.call(arguments);
Il existe également une manière d'écrire plus courte :
[].slice.call(arguments);
Ici, la méthode slice du tableau vide est simplement appelée, sans l'appeler depuis le niveau prototype d'Array.
Pourquoi les deux méthodes ci-dessus peuvent-elles être converties ?
Tout d'abord, le résultat obtenu par la méthode slice est un tableau, et le paramètre est des arguments. En fait, les objets qui remplissent certaines conditions peuvent être convertis en tableaux par la méthode slice. Prenons un exemple :
const obj = { 0: "A", 1: "B", length: 2 }; const result = [].slice.call(obj); console.log(Array.isArray(result), result);
Le résultat de l'exécution est :
true ["A", "B"]
Comme le montre l'exemple ci-dessus, les conditions sont : 1) Les attributs sont 0, 1, 2 ...; 2) With length attribut;
De plus, une chose à noter est que les arguments de la fonction ne peuvent pas être divulgués ou transmis. Qu'est-ce que ça veut dire? Regardez les exemples suivants de fuites d'arguments :
// Leaking arguments example1: function getArgs() { return arguments; } // Leaking arguments example2: function getArgs() { const args = [].slice.call(arguments); return args; } // Leaking arguments example3: function getArgs() { const args = arguments; return function() { return args; }; }
L'approche ci-dessus divulgue directement l'objet arguments de la fonction. Le résultat final est que le moteur V8 ignorera l'optimisation, ce qui entraînera une perte de performances considérable.
Vous pouvez faire ceci :
function getArgs() { const args = new Array(arguments.length); for(let i = 0; i < args.length; ++i) { args[i] = arguments[i]; } return args; }
C'est très curieux Chaque fois que nous utilisons des arguments, la première étape est généralement de les convertir en tableau. En même temps, une utilisation inappropriée de. les arguments peuvent facilement entraîner une perte de performances, alors pourquoi ne pas concevoir des arguments directement sous forme d'objets de tableau ?
Cela doit commencer depuis le début de cette langue. Les arguments ont été introduits au début du langage, lorsque l'objet Array disposait de quatre méthodes : toString, join, reverse et sort. La principale raison pour laquelle les arguments héritent d'Object est que ces quatre méthodes ne sont pas nécessaires. Désormais, Array a ajouté de nombreuses méthodes puissantes, telles que forEach, map, filter, etc. Alors pourquoi ne pas laisser les arguments réhériter d'Array dans la nouvelle version ? En fait, cela a été inclus dans le projet ES5, mais pour des raisons de compatibilité ascendante, il a finalement été rejeté par le comité.
En mode strict et en mode non strict, les résultats de la modification des valeurs des paramètres de fonction sont différents. Regardez les deux exemples ci-dessous :
function foo(a) { "use strict"; console.log(a, arguments[0]); a = 10; console.log(a, arguments[0]); arguments[0] = 20; console.log(a, arguments[0]); } foo(1);
Sortie :
1 1 10 1 10 20
Un autre exemple de mode non strict :
function foo(a) { console.log(a, arguments[0]); a = 10; console.log(a, arguments[0]); arguments[0] = 20; console.log(a, arguments[0]); } foo(1);
La sortie est :
1 1 10 10 20 20
Comme le montrent les deux exemples ci-dessus, en mode strict, les paramètres de la fonction n'ont aucun lien avec l'objet arguments, et la modification d'une valeur ne changera pas l'autre valeur. En mode non strict, les deux s'influenceront mutuellement.
Ce qui suit est la pratique recommandée pour passer des paramètres d'une fonction à une autre.
function foo() { bar.apply(this, arguments); } function bar(a, b, c) { // logic }
La surcharge est disponible dans de nombreuses langues, mais pas en JavaScript. Regardons d'abord un exemple :
function add(num1, num2) { console.log("Method one"); return num1 + num2; } function add(num1, num2, num3) { console.log("Method two"); return num1 + num2 + num3; } add(1, 2); add(1, 2, 3);
Le résultat de l'exécution est :
Method two Method two
Ainsi, en JavaScript, les fonctions n'effectuent pas d'appels différents en fonction de différents paramètres.
N'y a-t-il pas de surcharge en JavaScript ? Non, nous pouvons utiliser des arguments pour simuler une surcharge. Toujours l'exemple ci-dessus.
function add(num1, num2, num3) { if (arguments.length === 2) { console.log("Result is " + (num1 + num2)); } else if (arguments.length === 3) { console.log("Result is " + (num1 + num2 + num3)); } } add(1, 2); add(1, 2, 3)
Le résultat de l'exécution est le suivant :
Result is 3 Result is 6
Directement au châtaignier :
function func() { console.log(...arguments); } func(1, 2, 3);
Le résultat de l'exécution est :
1 2 3
Succinctement parlant, l'opérateur d'expansion peut développer des arguments en paramètres indépendants.
Toujours le meilleur :
function func(firstArg, ...restArgs) { console.log(Array.isArray(restArgs)); console.log(firstArg, restArgs); } func(1, 2, 3);
Le résultat de l'exécution est :
true 1 [2, 3]
Comme le montrent les résultats ci-dessus , Les paramètres de repos représentent l'ensemble de paramètres restant, à l'exception de ceux explicitement spécifiés, et le type est Array.
Chestnut :
function func(firstArg = 0, secondArg = 1) { console.log(arguments[0], arguments[1]); console.log(firstArg, secondArg); } func(99);
Le résultat de l'exécution est :
99 undefined 99 1
On voit que les paramètres par défaut n'ont pas effet sur les arguments, les arguments sont toujours Représente simplement tous les paramètres transmis lors de l'appel de la fonction.
Array.from()
est une méthode très recommandée, qui peut convertir tous les objets de type tableau en tableaux.
Les tableaux ont une fonctionnalité de base : l'index. C’est quelque chose que les objets ordinaires n’ont pas.
const obj = { 0: "a", 1: "b" }; const arr = [ "a", "b" ];
我们利用 obj[0]
、arr[0]
都能取得自己想要的数据,但取得数据的方式确实不同的。obj[0]
是利用对象的键值对存取数据,而arr[0]
却是利用数组的索引。事实上,Object 与 Array 的唯一区别就是 Object 的属性是 string,而 Array 的索引是 number。
下面看看类数组对象。
伪数组的特性就是长得像数组,包含一组数据以及拥有一个 length 属性,但是没有任何 Array 的方法。再具体的说,length 属性是个非负整数,上限是 JavaScript 中能精确表达的最大数字;另外,类数组对象的 length 值无法自动改变。
如何自己创建一个类数组对象?
function Foo() {} Foo.prototype = Object.create(Array.prototype); const foo = new Foo(); foo.push('A'); console.log(foo, foo.length); console.log("foo is an array? " + Array.isArray(foo));
执行结果是:
["A"] 1 foo is an array? false
也就是说 Foo 的示例拥有 Array 的所有方法,但类型不是 Array。
如果不需要 Array 的所有方法,只需要部分怎么办呢?
function Bar() {} Bar.prototype.push = Array.prototype.push; const bar = new Bar(); bar.push('A'); bar.push('B'); console.log(bar);
执行结果是:
Bar {0: "A", 1: "B", length: 2}
以上就是JavaScript arguments 对象详解的内容,更多相关内容请关注PHP中文网(www.php.cn)!