2013-05-22 3 views
2

Je suis un novice de Javascript alors s'il vous plaît excusez la question fondamentale. Je travaille sur "Javascript professionnel pour les développeurs Web" et dans le chapitre 3, section "Comprendre les arguments", il traite de l'accès aux arguments de la fonction avec le mot clé arguments [].Javascript: arguments de fonction et arguments []

Un des exemples montre que vous pouvez modifier les valeurs des arguments []:

function twoNums(num1, num2) { 
    arguments[1] = 10; 
    console.log(arguments[0] + num2); 
} 

twoNums(4,8); output = 14 

Mais il poursuit en disant que « Cet effet est à sens unique: changer l'argument nommé ne donne pas lieu un changement à la valeur correspondante dans les arguments. "

Cependant, la modification du code pour:

function twoNums(num1, num2) { 
    num2 = 10; 
    console.log(arguments[0] + arguments[1]); 
} 

twoNums(4,8); output = 14 

résultats dans la même sortie de sorte que la valeur dans 'arguments [1]' est en train de changer définitivement.

Est-ce:

  • une erreur dans le livre?
  • une erreur dans ma compréhension?
  • Quelque chose qui a changé en Javascript depuis l'écriture du livre?

Merci,

Neil

RÉPONDU: Une combinaison de réponses a résolu mon problème. Merci tout le monde.

+0

sonne comme un vieux livre. – dandavis

+0

Est-ce le livre? http://www.amazon.com/Professional-JavaScript-Developers-Wrox-Guides/dp/0764579088 Il semble un peu vieux pour dev web 2005 ... Ou est-ce une édition ultérieure? Dans tous les cas, votre exemple est de savoir comment cela devrait fonctionner. – elclanrs

+1

Il est écrit "troisième édition, 2012" dans la préface. – neilbaldwin

Répondre

1

Il y a une erreur dans le livre, par l'apparence des choses: si vous réaffectez l'un des arguments passés, l'objet arguments changera (les deux font référence à la même valeur).
Peut-être, cependant, ce qui voulait dire dans le livre était le suivant:

function f(n1, n2) 
{ 
    arguments[0] = 2; 
    console.log(arguments[0] + arguments[1]); 
} 
f(1, 2);//logs 4 
f(1234,2);//logs 4 

Mais, honnêtement, il ne devrait pas vraiment d'importance. L'objet arguments doit être traité comme un objet en lecture seule. C'est une bonne idée de maintenir le mantra "Ne changez pas d'objets que vous ne possédez pas" dans JS. C'est une mauvaise idée d'essayer de changer le Object.prototype, car il n'est pas le meilleur des idées pour changer le comportement de n'importe quel objet (console, window ...) en supprimant et en ajoutant des méthodes au hasard.

Si vous voulez obtenir plus de détails sur arguments, ou toute autre chose MDN is there to help. Je n'ai pas regardé tous les exemples de code là-bas, mais AFAIKT il n'y a pas de code qui effectivement change l'objet arguments.
Il ya quelque temps je pense avoir lu un article de mon Douglas Crockford sur le sujet, où il a donné un exemple de comment changer l'objet conduit réellement à un comportement inattendu (arguments échangeant des lieux et tout ça).

Edit:
j'avais pensé que je passe pas en mode strict, mais comme la réponse de bfavaretto a souligné: mode strict fait ne faire l'objet arguments un objet en lecture seule. C'est une excellente nouvelle, et maintenant j'ai d'autant plus de raisons d'aimer la façon dont JS va. ES6 va introduire la définition de bloc et probablement rendre l'objet arguments en lecture seule tout le temps (du moins, j'espère que ce sera le cas).

+0

:) Absolument. Je n'avais aucune intention de jamais modifier les paramètres de fonction dans le sens de cet exemple. Je voulais juste de qualifier ce qui a été dit dans le texte du livre dans le cas où il y avait un autre aspect sous-jacent que je manqué ou ne comprenais pas ce que l'auteur met en avant. – neilbaldwin

+0

Je doute que ES6 le rende en lecture seule tout le temps; Malheureusement, ils ont tendance à éviter les changements rétrocompatibles. – bfavaretto

+1

@bfavaretto: Un homme peut rêver, n'est-ce pas? D'autant plus que, dans le passé, MS était la plus favorable à la compatibilité. Mais maintenant, ils rompent avec la tradition, et pas très bien représentés sur les nouveaux marchés (tablettes, smartphones) ils ne sont pas aussi dominants qu'ils l'étaient autrefois ... –

2

Il est censé fonctionner de cette façon, à moins en mode strict:

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

// output: 
// 1 1 
// 10 1 
// 10 20 

Les adresses de spécification ES5 que sur section 10.6:

NOTE 1 Pour les fonctions de mode non strictes du tableau index (défini en 15.4) propriétés de données nommées d'un objet arguments dont les valeurs de nom numérique sont inférieures au nombre de paramètres formels de l'objet fonction correspondant partagent initialement leurs valeurs avec les liaisons d'argument correspondantes dans la fonction s contexte d'exécution. Cela signifie que la modification de la propriété modifie la valeur correspondante de la liaison d'argument et vice-versa. Cette correspondance est rompue si une telle propriété est supprimée puis redéfinie ou si la propriété est modifiée en propriété accesseur. Pour les fonctions de mode strict, les valeurs des propriétés de l'objet arguments sont simplement une copie des arguments passés à la fonction et il n'y a pas de liaison dynamique entre les valeurs de propriétés et les valeurs de paramètres formels.

Peut-être cela a fonctionné différemment ES3 (la version précédente), mais je doute (car ils ont dû ajouter un cas particulier pour le mode strict).

Fait intéressant: la présence d'un appel eval dans la fonction peut influencer le comportement de l'objet arguments dans certains navigateurs, ce qui est extrêmement bizarre. L'utilisation de la référence non standard functionName.arguments a également un impact. Voir Why does an unexecuted eval have an effect on behavior in some browsers?, et ma réponse à cela.

1

il fonctionnera de cette façon que dans le mode strict ..

"use strict" 

L'objet Arguments a une caractéristique très inhabituelle. En mode non strict, lorsqu'une fonction a des paramètres nommés, les éléments de tableau de l'objet Arguments sont des alias pour les paramètres qui contiennent les arguments de la fonction . Les éléments numérotés de l'objet Arguments et les noms des paramètres sont semblables à deux noms différents pour la même variable. La modification de la valeur d'un argument avec un nom d'argument modifie la valeur récupérée via le tableau arguments []. Inversement, en changeant la valeur d'un argument à travers le tableau arguments [ change la valeur qui est récupérée par le nom de l'argument. Voici un exemple qui clarifie ceci:

fonction f (x) { console.log (x); // Affiche la valeur initiale de l'argument arguments [0] = null; // Changer l'élément du tableau change aussi x! console.log (x); // Affiche maintenant "null"} Ce n'est absolument pas le comportement que vous verriez si l'objet Arguments était un tableau ordinaire.Dans ce cas, les arguments [0] et x pourraient renvoyer initialement à la même valeur, mais un changement à un n'aurait aucun effet sur l'autre.

Ce comportement spécial de l'objet Arguments a été supprimé dans le mode strict d'ECMAScript 5. Il existe également d'autres différences de mode strict . Dans les fonctions non strictes, les arguments sont juste un identifiant. En mode strict, il s'agit effectivement d'un mot réservé. fonctions strictes en mode ne peut pas utiliser des arguments comme un nom de paramètre ou comme nom de variable locale, et ils ne peuvent pas attribuer des valeurs aux arguments.

est ici un grand (et récent) article sur ce sujet: https://www.inkling.com/read/javascript-definitive-guide-david-flanagan-6th/chapter-8/function-arguments-and

Je vous conseille de l'utiliser :)