assignez plusieurs variables à la même valeur en Javascript


177

J'ai initialisé plusieurs variables de la portée globale dans un fichier JavaScript:

var moveUp, moveDown, moveLeft, moveRight;
var mouseDown, touchDown;

Je dois définir toutes ces variables sur false, c'est le code que j'ai actuellement:

moveUp    = false;
moveDown  = false;
moveLeft  = false;
moveRight = false
mouseDown = false;
touchDown = false;

Existe-t-il un moyen de définir toutes ces variables sur la même valeur dans une ligne de code, ou le code que j'ai actuellement est-il le meilleur moyen de le faire?


8
Tous les lecteurs: veuillez consulter la deuxième réponse ci-dessous avant de décider d'intégrer la première réponse dans votre code. Paix.
Govind Rai

N'essayez pas de faire cela, car en mémoire il n'y aura qu'une seule variable et les autres seront une copie ou une référence pour celle-là, alors si vous changez la valeur d'une, toutes seront affectées
Lucas Matos

@LucasMatos Pas pour les primitives.
Dave Newton

Réponses:


290

Rien ne t'empêche de faire

moveUp = moveDown = moveLeft = moveRight = mouseDown = touchDown = false;

Vérifiez cet exemple

var a, b, c;
a = b = c = 10;
console.log(a + b + c)


13
Vous voudrez peut-être commenter en quoi le comportement diffère des types primitifs et des types de référence lors de l'attribution de valeurs comme vous le suggérez.
Steven Wexler

26
Oui, si vous faites cela avec un objet, toutes les variables seront des alias de l'objet. IE function MyObj(){this.x=1} var a,b; a = b = new MyObj(); ++a.xincrémentera également la b.xpropriété.
AlexMorley-Finch


4
Je dirais de ne pas utiliser cette approche si vous ne cadrez pas globalement toutes les variables à gauche de l'affectation
citoyen conn

2
Comme @doublejosh l'a dit, il y a des problèmes de portée que vous n'avez pas résolus.
kstratis

90

Rien ne vous empêche de faire ce qui précède, mais attendez!

Il y a des pièges. L'affectation en Javascript se fait de droite à gauche, donc lorsque vous écrivez:

var moveUp = moveDown = moveLeft = moveRight = mouseDown = touchDown = false;

cela se traduit effectivement par:

var moveUp = (moveDown = (moveLeft = (moveRight = (mouseDown = (touchDown = false)))));

ce qui se traduit effectivement par:

var moveUp = (window.moveDown = (window.moveLeft = (window.moveRight = (window.mouseDown = (window.touchDown = false)))));

Par inadvertance, vous venez de créer 5 variables globales - ce que je suis sûr que vous ne vouliez pas faire.

Remarque: mon exemple ci-dessus suppose que vous exécutez votre code dans le navigateur, par conséquent window. Si vous deviez être dans un environnement différent, ces variables s'attacheraient à quel que soit le contexte global se trouve être pour cet environnement (c'est-à-dire, dans Node.js, il s'attacherait à globalquel est le contexte global pour cet environnement).

Maintenant, vous pouvez d'abord déclarer toutes vos variables, puis les affecter à la même valeur et vous pouvez éviter le problème.

var moveUp, moveDown, moveLeft, moveRight, mouseDown, touchDown;
moveUp = moveDown = moveLeft = moveRight = mouseDown = touchDown = false;

En bref, les deux méthodes fonctionneraient très bien, mais la première méthode pourrait potentiellement introduire des bogues pernicieux dans votre code. Ne commettez pas le péché de joncher l'espace de noms global avec des variables locales si ce n'est absolument nécessaire.


Note de bas de page: Comme indiqué dans les commentaires (et ce n'est pas seulement dans le cas de cette question), si la valeur copiée en question n'était pas une valeur primitive mais plutôt un objet, vous feriez mieux de connaître la copie par valeur vs la copie par référence. À chaque affectation d'objets, la référence à l'objet est copiée à la place de l'objet réel. Toutes les variables pointeront toujours vers le même objet, donc tout changement dans une variable sera reflété dans les autres variables et vous causera un mal de tête majeur si votre intention était de copier les valeurs de l'objet et non la référence.


2
et si nous faisions la même chose avec let?
P-RAD

En plus de moveUpdevenir un bloc, cela ne ferait aucune différence. 5 variables globales seraient toujours déclarées.
Govind Rai

1
@GovindRai var a, b, c; a = b = c = 10;est très différent de var a = b = c = 10;. Donc, la réponse acceptée est correcte. Vous vous adressez à un problème sans rapport avec la réponse acceptée.
Elis Byberi

1
@ElisByberi Merci pour votre commentaire. Vous n'avez pas tort. Le but de ma réponse était d'aborder la première phrase de la réponse acceptée. J'ai fourni plus de clarté dans ma réponse à ce sujet.
Govind Rai

1
@ P-RAD Seule la première variable déclarée avec let existera dans la portée englobante.
Uday Hiwarale le

10

Il existe une autre option qui n'introduit pas de pièges globaux lors de la tentative d'initialisation de plusieurs variables avec la même valeur. Que ce soit préférable ou non au long chemin est une question de jugement. Il sera probablement plus lent et peut ou non être plus lisible. Dans votre cas particulier, je pense que le long chemin est probablement plus lisible et maintenable en plus d'être plus rapide.

L' autre façon utilise l' affectation de Destructuration .

let [moveUp, moveDown,
     moveLeft, moveRight,
     mouseDown, touchDown] = Array(6).fill(false);

console.log(JSON.stringify({
    moveUp, moveDown,
    moveLeft, moveRight,
    mouseDown, touchDown
}, null, '  '));

// NOTE: If you want to do this with objects, you would be safer doing this
let [obj1, obj2, obj3] = Array(3).fill(null).map(() => ({}));
console.log(JSON.stringify({
    obj1, obj2, obj3
}, null, '  '));
// So that each array element is a unique object

// Or another cool trick would be to use an infinite generator
let [a, b, c, d] = (function*() { while (true) yield {x: 0, y: 0} })();
console.log(JSON.stringify({
    a, b, c, d
}, null, '  '));

// Or generic fixed generator function
function* nTimes(n, f) {
    for(let i = 0; i < n; i++) {
        yield f();
    }
}
let [p1, p2, p3] = [...nTimes(3, () => ({ x: 0, y: 0 }))];
console.log(JSON.stringify({
    p1, p2, p3
}, null, '  '));

Cela vous permet d'initialiser un ensemble de var, letou de constvariables à la même valeur sur une seule ligne, toutes avec la même portée attendue.

Références:


1
Attention cependant. Si vous attribuez des objets, des fonctions ou des tableaux à plusieurs variables à l'aide de cette méthode, chaque variable sera un alias de l' sameobjet. Les modifications apportées à l'une affecteront les autres ...
Doug Coburn

0

Les variables d'origine que vous avez répertoriées peuvent être déclarées et affectées à la même valeur dans une courte ligne de code à l'aide d'une affectation de déstructuration. Les mots let- clés , constet varpeuvent tous être utilisés pour ce type d'affectation.

let [moveUp, moveDown, moveLeft, moveRight, mouseDown, touchDown] = Array(6).fill(false);

-6

Placez la variable dans un tableau et utilisez une boucle for pour affecter la même valeur à plusieurs variables.

  myArray[moveUP, moveDown, moveLeft];

    for(var i = 0; i < myArray.length; i++){

        myArray[i] = true;

    }

3
C'est très faux. La première instruction n'a pas de sens syntaxique et la boucle for affecte simplement des valeurs aux index myArray.
undefinederror
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.