Array destructuring - unexpected behavior - javascript

const [a, b] = [1, 2]
// expected to be equal to
// const a = 1
// const b = 2
const [c, d] = [3, 4]
// expected to be equal to
// const c = 3
// const d = 4
[a, b] = [b, a]
// expected Assignment to constant variable error
console.log(a, b, c, d)
// => 1, 2, 2, 1
Can someone explain what is wrong with this code? What happened to variables c and d?

You're not using semi-colons and ASI doesn't always work the way you would like.
Your code is equivalent to this:
const [a, b] = [1, 2];
const [c, d] = [3, 4][a, b] = [b, a];
console.log(a, b, c, d);
[3, 4][a, b] in this case evaluates as [3,4][2] since the second comma is just the comma operator and b === 2. That makes the assignment equivalent to [3,4][2] = [b,a] which results in a temporary array [3,4,[2,1]] being created and the result of the assignment expression [2,1] is then assigned to [c,d].
Try adding semi-colons and you will get the expected results:
const [a, b] = [1, 2];
// expected to be equal to
// const a = 1
// const b = 2
const [c, d] = [3, 4];
// expected to be equal to
// const c = 3
// const d = 4
[a, b] = [b, a];
// expected Assignment to constant variable error
console.log(a, b, c, d);

It's basically a problem with not terminating commands properly with a semi-colon (;). If you add them to the end of each command you will get the proper result.. and also run into the problem where you cannot reassign a and b as they're declared as const.

Instead of:
const [a, b] = [1, 2];
Try:
const a = 1, b = 2;
const c = 3, d = 4;
To swap the values, try something like:
var temp;
temp = a; a = b; b = temp;

Related

Return multiple values from function in an assigment

If I want to return a multiple values from a function, in an assigment, do I need to use an intermediate array to receive those values?
How am I used to do it in JavaScript:
let f = () => return [1, 2, 3];
let a, b, c, arr;
arr = f();
a = arr[0]; b = arr[1]; c = arr[2]
Is JavaScript like C, returning assignment to the first lhand operator, or is it possible to do something more flexible, like in this example from Ruby (without using loop):
def f
return 1, 2, 3
end
a, b, c = f
My motivation is simply lack of readability in the JavaScript method.
Issues
return not needed in simple arrow function
destructure assignment syntax
let f = () => [1, 2, 3];
let [a, b, c] = f();
console.log(a, b, c)
You can get values from an array either using index or using destructuring . If there are multiple values then you can easily destructure and store it in different variables in a single statement.
let f = () => [1, 2, 3];
//Using Destructuring
const [a, b, c] = f();
console.log(a, b, c);
// Accessing using index
const arr = f();
const m = arr[0];
const n = arr[1];
const o = arr[2];
console.log(m, n, o);
Since you are using an array to return multiple values then you can use either implicitly return in a function of you can explicitly return an array from it
1) Explicitly return
let f = () => {
return [1, 2, 3];
};
const [a, b, c] = f();
console.log(a, b, c);
2) Implicitly return
let f = () => [1, 2, 3];
const [a, b, c] = f();
console.log(a, b, c);

js destructuring assignment not work in while loop

[a,b] = [b, a+b] here not work , a b always 0 and 1.
If use a temp variable to swap the value ,that works.
function fibonacciSequence() {
let [a, b, arr] = [0, 1, []]
while (a <= 255) {
arr.concat(a)
[a, b] = [b, a + b]
console.log(a, b) // always 0 1
}
}
console.log(fibonacciSequence())
The problem is that Automatic Semicolon Insertion isn't doing what you expect. It's not adding a semicolon between
arr.concat(a)
and
[a, b] = [b, a + b]
so it's being treated as if you wrote
arr.concat(a)[a, b] = [b, a + b]
Add all the semicolons explicitly and you get a correct result.
function fibonacciSequence() {
let [a, b, arr] = [0, 1, []];
while (a <= 255) {
arr.concat(a);
[a, b] = [b, a + b];
console.log(a, b); // always 0 1
}
}
console.log(fibonacciSequence())
You can use the below function as well:
function fibonacciSequence() {
let [a, b] = [0, 1];
while (a <= 255) {
b = a + b;
a = b - a;
console.log(a,b);
}
}
fibonacciSequence();

javascript array.slice().push() not working as expected

The following code produces (in Chrome javascript console)
a: (3) [1, 2, 3] b: (4) [1, 2, 3, 99] c: 4
I expected c to look like b. Why doesn't it?
function snafu(){
var a = [1,2,3];
var b = a.slice();
var c = a.slice().push(99);
b.push(99);
console.log("a:",a," b:",b," c:",c);
}
Array.push() gives you value of Array.length and not array itself
var a = [];
var b = a.push(8); /* returns length of array after pushing value into array */
console.log('a = ', a, ', b = ', b);
Well, remember Array.slice() will return you new Array. So while pushing it on slice(), it'll return you length of the array.
function snafu(){
var a = [1,2,3];
var b = a.slice();
var c = a.slice();
c.push(99);
b.push(99);
console.log("a:",a," b:",b," c:",c);
}
snafu();
variable c will give you new Array so you can do whatever you want with c.
That's it. Easy!!!!

ES6 Array destructuring weirdness

Can anyone explain, why the following happens with ES6 array destructuring?
let a, b, c
[a, b] = ['A', 'B']
[b, c] = ['BB', 'C']
console.log(`a=${a} b=${b} c=${c}`)
// expected: a=A b=BB c=C
// actual: a=BB b=C c=undefined
http://codepen.io/ronkot/pen/WxRqXg?editors=0011
As others have said, you're missing semicolons. But…
Can anyone explain?
There are no semicolons automatically inserted between your lines to separate the "two" statements, because it is valid as a single statement. It is parsed (and evaluated) as
let a = undefined, b = undefined, c = undefined;
[a, b] = (['A', 'B']
[(b, c)] = ['BB', 'C']);
console.log(`a=${a} b=${b} c=${c}`);
wherein
[a, b] = …; is a destructuring assignment as expected
(… = ['BB', 'C']) is an assignment expression assigning the array to the left hand side, and evaluating to the array
['A', 'B'][…] is a property reference on an array literal
(b, c) is using the comma operator, evaluating to c (which is undefined)
If you want to omit semicolons and let them be automatically inserted where ever possible needed, you will need to put one at the start of every line that begins with (, [, /, +, - or `.
You've fallen into a trap of line wrapping and automatic semicolon insertion rules in JavaScript.
Take this example:
let x = [1, 2]
[2, 1]
It's the interpreted as:
let x = [1, 2][2, 1] // === [1, 2][(2, 1)] === [1, 2][1] === 2
That weird [(2, 1)] thing above is related to how Comma Operator works.
Thus, your example:
let a, b, c
[a, b] = ['A', 'B']
[b, c] = ['BB', 'C']
console.log(`a=${a} b=${b} c=${c}`)
Is interpreted as:
let a, b, c
[a, b] = ['A', 'B'][b, c] = ['BB', 'C']
console.log(`a=${a} b=${b} c=${c}`)
Now, if you insert a semicolon, it will work as you intended:
let a, b, c
[a, b] = ['A', 'B']; // note a semicolon here
[b, c] = ['BB', 'C']
console.log(`a=${a} b=${b} c=${c}`)
Also, it's a good idea to check your code by pasting it into Babel repl to see the generated output:
'use strict';
var a = void 0,
b = void 0,
c = void 0;
var _ref = ['A', 'B'][(b, c)] = ['BB', 'C'];
a = _ref[0];
b = _ref[1];
console.log('a=' + a + ' b=' + b + ' c=' + c);
I believe you have forgotten the line breaks ';'. Below is the corrected code. Please try:
let a,b,c
[a, b] = ['A', 'B'];
[b, c] = ['BB', 'C'];
console.log(`a=${a} b=${b} c=${c}`)
let a, b, c
[a, b] = ['A', 'B']***;***
[b, c] = ['BB', 'C']
console.log(`a=${a} b=${b} c=${c}`)
console: a=A b=BB c=C

Variable containing an operator in Javascript

I'm trying to make a change to a variable using a custom operator (I will explain it clearlier now).
I have an array of numbers, and I have to reduce() it. First 2 numbers will be added, then in the second reducing they will be substracted, then multiplied, divided and exponentiated. Basically:
[1,2,3,4,5] -> 0
1+2=3
3-3=0
0*4=0
0/5=0 -> 0
So I saw an implementation like this:
f => f.reduce((a,b,c) => [a + b, a - b, a * b, a / b, a ** b][c % 5])
And wondered, can I make an array of operators in some way, and implement it like this?
f => f.reduce((a,b,c) => a [+,-,*,/,**][c%5] b)
Clearly this syntax is incorrect, but in the terms of an idea, does something like this exist?
You can use eval() method
var f = [1, 2, 3, 4, 5];
console.log(
f.reduce((a, b, c) => eval(a + ['+', '-', '*', '/'][c-1] + b))
);
Also I don't prefer to use eval(), refer : Don't use eval needlessly!
UPDATE :
Also as #NinaScholz said, you can reduce the code by using string instead of string array. Both string and array have same effect in this case.
var f = [1, 2, 3, 4, 5];
console.log(
f.reduce((a, b, c) => eval(a + '+-*/'[c - 1] + b))
);
You can try something like this
var add = function(a, b) {
return a + b;
},
sub = function(a, b) {
return a - b;
},
mul = function(a, b) {
return a * b;
},
div = function(a, b) {
return a / b;
};
var operations = [add, sub, mul, div];
var output = [1, 2, 3, 4, 5].reduce(function(p, c, i) {
return operations[i - 1](p, c)
});
console.log(output);
You can add more functions (custom operators) and decide the order of operations.
You could use an array for the operators.
var array = [1, 2, 3, 4, 5],
op = [
(a, b) => a + b,
(a, b) => a - b,
(a, b) => a * b,
(a, b) => a / b,
];
console.log(array.reduce((r, a, i) => op[(i - 1) % 4](r, a)));

Categories