259

I have initialized several variables in the global scope in a JavaScript file:

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

I need to set all of these variables to false. This is the code I currently have:

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

Is there any way that I can set all of these variables to the same value in one line of code, or is the code I currently have the best way to do this?

Lerner Zhang
  • 6,184
  • 2
  • 49
  • 66
  • 21
    All readers: please view second answer below before you decided to implement the top answer into your code. Peace. – Govind Rai Aug 14 '17 at 02:39
  • Don't try to do this, because in memory will be only one variable and the others will be a copy or reference for that one, then if you change the value from one all will be impacted – Lucas Matos Feb 26 '19 at 19:36
  • @LucasMatos Not for primitives. – Dave Newton Apr 18 '20 at 02:47
  • i know it's not the answer, but i would use ONE variable "direction" and instead of setting a variable to false, i use the triple = to compare it to true if(moveLeft === true), that way you don't need to set the initial value at all – Martijn Scheffer Oct 15 '20 at 19:15

8 Answers8

389

Nothing stops you from doing

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

Check this example

var a, b, c;
a = b = c = 10;
console.log(a + b + c)
SpoonMeiser
  • 19,918
  • 8
  • 50
  • 68
karthikr
  • 97,368
  • 26
  • 197
  • 188
  • 21
    You may want to comment how the behavior will differ primitive types and reference types when assigning values the way you suggest. – Steven Wexler Jun 07 '13 at 04:31
  • 35
    Yeah, if doing this with an object, all the variables will be aliases of the object. I.E `function MyObj(){this.x=1} var a,b; a = b = new MyObj(); ++a.x` will also increment the `b.x` property. – AlexMorley-Finch Mar 10 '14 at 09:33
  • 35
    Scoping problems! http://stackoverflow.com/questions/1758576/multiple-left-hand-assignment-with-javascript – doublejosh May 13 '14 at 19:36
  • 6
    I would say do not use this approach if you are not globally scoping all the variables to the left of the assignment – citizen conn Feb 09 '15 at 15:05
  • 4
    As @doublejosh said, there are scoping problems you didn't address. – stratis Oct 04 '15 at 07:56
  • why does var a, b = 2; not give both a and b the value of 2? – spex5 Nov 30 '15 at 20:15
  • This will give a "not defined" error in strict mode for everything between the first and last `=`. You could do `var moveUp, moveDown, moveLeft, moveRight, mouseDown, touchDown = false;` instead. – Dirk Diggler Apr 19 '16 at 14:28
  • @zooted, that's not going to work either. In that example, `moveUp, moveDown, moveLeft, moveRight, mouseDown` will all have values of `undefined` and only `touchDown` will be `false`. You'd have to combine both answers, and as folks mentioned, it may have different meaning. – Louis St-Amour Aug 10 '16 at 14:04
  • @kstratis, scoping problems! – Maxim Mazurok Aug 23 '16 at 19:56
  • are there not issues with this approach ?? – oldboy Jan 11 '20 at 21:02
181

Nothing stops you from doing the above, but hold up!

There are some gotchas. Assignment in Javascript is from right to left so when you write:

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

it effectively translates to:

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

which effectively translates to:

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

Inadvertently, you just created 5 global variables--something I'm pretty sure you didn't want to do.

Note: My above example assumes you are running your code in the browser, hence window. If you were to be in a different environment these variables would attach to whatever the global context happens to be for that environment (i.e., in Node.js, it would attach to global which is the global context for that environment).

Now you could first declare all your variables and then assign them to the same value and you could avoid the problem.

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

Long story short, both ways would work just fine, but the first way could potentially introduce some pernicious bugs in your code. Don't commit the sin of littering the global namespace with local variables if not absolutely necessary.


Sidenote: As pointed out in the comments (and this is not just in the case of this question), if the copied value in question was not a primitive value but instead an object, you better know about copy by value vs copy by reference. Whenever assigning objects, the reference to the object is copied instead of the actual object. All variables will still point to the same object so any change in one variable will be reflected in the other variables and will cause you a major headache if your intention was to copy the object values and not the reference.

Govind Rai
  • 14,406
  • 9
  • 72
  • 83
  • 8
    what if we do this same with let ? – P-RAD Jul 04 '18 at 23:20
  • Besides `moveUp` becoming block-scoped, it would make no difference. 5 global variables would still be declared. – Govind Rai Jul 05 '18 at 15:08
  • 2
    @GovindRai `var a, b, c; a = b = c = 10;` is very different from `var a = b = c = 10;`. So, the accepted answer is correct. You are addressing a problem not related to the accepted answer. – Elis Byberi Aug 16 '18 at 17:16
  • 3
    @ElisByberi Thanks for your comment. You're not wrong. The goal of my answer was to address the first sentence in the accepted answer. I have provided further clarity in my answer in regards to that. – Govind Rai Aug 16 '18 at 21:51
  • The question already states that the variables are declared, but it was still a good idea to add this answer. – David Callanan Aug 14 '19 at 14:09
  • 4
    @P-RAD Only the first variable declared using let will exist in the enclosing scope. – Uday Hiwarale Jul 14 '20 at 08:31
  • Noting that `window` assumes a browser environment. – Dave Newton Mar 31 '22 at 16:33
22

There is another option that does not introduce global gotchas when trying to initialize multiple variables to the same value. Whether or not it is preferable to the long way is a judgement call. It will likely be slower and may or may not be more readable. In your specific case, I think that the long way is probably more readable and maintainable as well as being faster.

The other way utilizes Destructuring assignment.

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

This allows you to initialize a set of var, let, or const variables to the same value on a single line all with the same expected scope.

References:

Doug Coburn
  • 2,485
  • 27
  • 24
  • 2
    Beware, however. If assigning Objects, functions, or arrays to multiple variables using this method, each variable will be an alias to the `same` object. Modifications to one will affect the others... – Doug Coburn Oct 09 '17 at 15:21
  • creating an array to assign a value, please don't – Martijn Scheffer Oct 13 '20 at 17:06
  • 1
    @MartijnScheffer why? If the JavaScript engine compiling the code actually creates and discards an extra array than it would have from compiling a series of direct assignments, it would be implementation specific and fixable. – Doug Coburn Oct 13 '20 at 17:20
  • Yes, once the code is compiled the array is still created, making this method a LOT slower than simply assigning the values. That’s not fixable, don’t allocate memory if u don’t have to. Just do a simple test, write a loot with both versions of the code. – Martijn Scheffer Oct 14 '20 at 18:11
  • i did a quick test, your method is 46 times slower (V8/Node) – Martijn Scheffer Oct 14 '20 at 18:18
  • @MartijnScheffer if you read my answer you can note that I already mentioned that this approach _may_ be slower and may or may not be more readable. If it _is_ slower, it's the fault of the engine, not the syntax... (see: https://2ality.com/2015/01/es6-destructuring.html). The engine can be updated in the future to optimize for this case. – Doug Coburn Oct 14 '20 at 18:19
  • no, it's the fault of the approach, the engine cannot optimize that, it doesn't know what the fill method is doing, and will never know, that is not how code optimisation works, fill is a native method, it's not written in javascript. you could imagine that if it was and the optimizer was VERY smart it would be able to do so, but no optimizer can do this, not even GNU – Martijn Scheffer Oct 15 '20 at 19:07
  • that benchmark is NOT using fill so it could theoreticaly be optimized, i doubt that would ever be a priority of the V8 team (that i know), as this is totally wrong anyway. what would be nice is a syntax that allows to do this, but is it really worth it ? in what case do you want to assign false to this many variables ? – Martijn Scheffer Oct 15 '20 at 19:10
  • @MartijnScheffer I am responding to the criticism `creating an array to assign a value, please don't`. Of course the generators, iterators, and `Array.fill` parts of this answer are slower. If you are claiming that using `Array.fill()` on the rhs of the assignment will likely remain slower than direct assignment -- no argument here. But 1) performance isn't the only consideration. 2) 46x slower may not even be noticeable if it only happens once at startup. – Doug Coburn Oct 15 '20 at 20:46
  • 3
    ""Write idiomatic JavaScript, and let us worry about the low level bits of the JavaScript performance instead"" -- Benedikt Meurer, V8 performance expert. – Doug Coburn Oct 15 '20 at 20:48
  • yes, (i know him, i met him, he interviewed me), he says this for plain scripts, that doesn't apply to calling native functions that can't be optimised. V8 doesn't and will never optimise that code (the version you posted here), the version on the benchmark can theoreticaly be optimized. of course if you only do this once it doesn't matter, and your solution is elegant, i would just not use it in a function that can be called repeatedly, especialy if the rest of the code doesn't allocate any memory. – Martijn Scheffer Oct 16 '20 at 21:15
  • maybe we should ask him :) https://twitter.com/bmeurer (he doesn't work in that team anymore, but might have an answer anyway :) – Martijn Scheffer Oct 16 '20 at 21:22
  • I think we are talking past each other. I agree that it would be difficult, even impossible, for V8 or any engine to optimize `Array(4).fill(false)` to `[false, false, false, false]`. _This_ is precisely why I said `"It will likely be slower and may or may not be more readable."` in my answer. – Doug Coburn Oct 16 '20 at 21:33
  • ok, in that case i agree, but still, please don't tell people to allocate memory to do an allocation, its in another dimension !!, it's like going from 0 to n, or worse – Martijn Scheffer Oct 16 '20 at 21:36
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/223185/discussion-between-doug-coburn-and-martijn-scheffer). – Doug Coburn Oct 16 '20 at 21:36
11

The original variables you listed can be declared and assigned to the same value in a short line of code using destructuring assignment. The keywords let, const, and var can all be used for this type of assignment.

let [moveUp, moveDown, moveLeft, moveRight, mouseDown, touchDown] = Array(6).fill(false);
Stalkov
  • 119
  • 1
  • 3
  • 1
    nice, but it's still totally wrong to allocate memory just to do an assignment. – Martijn Scheffer Oct 14 '20 at 18:22
  • Using array destructuring is a nice approach. You can also declare an array and explicitly put your values there, being them all equal or all different. `let [moveUp, moveDown, moveLeft, ..., touchDown] = [1, False,..., True] ` – Joel Carneiro Dec 22 '20 at 20:38
3

I personally try to avoid var at all times, and use let and const always, I learned it from bugs that occur and most best practices recommendations, so below is mentioned in comments but to be more precise:

function good() {  
    let a;
    let b;
    let c;
    let d;        
    a = b = c = d = 'hello';    
    console.log(d);    
}

function bad() {
    //only the first variable is declared as local
    let a = b = c = d = 'bye';
    console.log(d)
}

let a;
let d;

good();
bad();

//expected undefined
console.log(a);

//expected bye 
console.log(d);
0

If you want to declare multiple const variables you can do that by

const [a, b, c, d] = [[], [], [], []]

assign empty objects or any values at the same time.

-2

Assign multiple variables to the same value in Javascript?

let a=10
let b=10
let c=10
let d=10
let e=10
console.log(a,b,c,d,e)
-15

Put the varible in an array and Use a for Loop to assign the same value to multiple variables.

  myArray[moveUP, moveDown, moveLeft];

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

        myArray[i] = true;

    }
  • 12
    This is very wrong.The first statement doesn't make syntactical sense and the for loop is just assigning values to the myArray indices. – undefinederror Mar 14 '19 at 14:04
  • Ignoring the syntaxes, they simply wanted cool stuff with different vars, not a bad stuff with a list. – The Myth Dec 12 '22 at 11:45