What does it mean when variable value in round brackets in js?
For example,
let a = (1,2,3);
What does it mean and why console.log(a) output is 3?
What is usage of comma operator in round brackets in variable initialization?
The parentheses are needed for grouping. In a let statement, commas are normally used to separate multiple variables that are being declared, e.g.
let a = 1, b = 2, c;
which is short for
let a = 1;
let b = 2;
let c;
If you write
let a = 1, 2, 3;
you'll get a syntax error, because after the comma it expects another variable declaration; it's equivalent to:
let a = 1;
let 2;
let 3;
The second and third declarations are clearly wrong, as 2 and 3 are not variable names.
The parentheses indicate that the whole expression 1, 2, 3 is being used to initialize one variable.
The expression 1, 2, 3 uses the Comma operator, which executes each of its subexpressions and returns the last one as its value. It's pretty useless when the subexpressions are all constants, so I assume your code was just a simplified example. Because the way it's written, it's really just equivalent to:
let a = 3;
What you have encountered is the comma operator.
Quoting the docs
The comma operator evaluates each of its operands (from left to right) and returns the value of the last operand.
Therefore in your case 1, 2 and 3 is evaluated and 3 is returned and thus assigned to the variable a.
This is not variable declaration-specific thing. You can write (1,2,3) anywhere in your JS code and it will always evaluate to 3. The thing is, JavaScript (like many other programming languages, e.g. C) has comma operator, which simply returns last element. The expression (1,2,3) basically looks just like (1+2+3) to JavaScript, except for comma operator is applied instead of addition.
It's call the comma operator:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator
It's a very handy thing to use in JavaScript, because it allows you to run multiple statements as a single value for an arrow function.
Here is an example of a 10x10 identity matrix generated with one line of code. The last comma value is returned as the value.
const m = new Array(9).fill('000000000').map((v,i)=> (v=[...v],v[i]='1',v.join()));
console.log(m);
The same above code as a blocked function would take a lot more lines.
const m = new Array(9).fill('000000000').map((v,i)=> {
v = [...v];
v[i] = '1';
return v.join()
});
console.log(m);
Related
Recently I found out that a simple arrow function, for example callback in this map
[1, 2, 3, 4, 5, 6].map(item => {
console.log(item) // or anything else
return item - 1;
})
I can re-write to one line command like this
[1, 2, 3, 4, 5, 6].map(item => (console.log(item), item - 1))
I can use as much statements I want to devided by , and last argument will always be a return value. It looks kind of cool to me, but cant find anything about this syntax in arrow function documentation. Can anyone explain this syntax or just point to place where I found a docs?
Essentially it allows you to do multiple operations in a single statement. It's used commonly in for loops and to assign multiple variables in a single statment, eg.: var a = 1, b = 2;.
Just because it works though, doesn't mean it's a good idea. It makes your code less readable and harder to debug.
See the MDN docs on the Comma Operator.
The comma operator (,) evaluates each of its operands (from left to right) and returns the value of the last operand. This lets you create a compound expression in which multiple expressions are evaluated, with the compound expression's final value being the value of the rightmost of its member expressions. This is commonly used to provide multiple parameters to a for loop.
You are using the comma operator to evaluate multiple expressions:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator
This could be a very naive dumb question, but what is the difference in the output of the following 2 condition:
for (var p=0; p<3; p++) {console.log(p)}
//outputs:
0
1
2
for (var p=0; p<3; ++p) {console.log(p)}
//outputs:
0
1
2
'p' result into same output regardless whether I increment the value first and then print it or vice vera. also I do understand the diff between (p++) and (++p), but in this case I'm unable to understand whether at this point in looping will it make it any difference if I were I do either of 2 or if it does make difference how would that impact my program.
Can someone please explain.
Thank
If you dont use the values, after using pre- and post-fix, there is absolutely no difference at all. (exept from performance)
Doing something like this would behave differently, as you can see:
var a = 0;
var b = 0;
var arr = [0,1,2];
console.log(arr[++b]);
console.log(arr[b++]);
console.log(arr[b]);
In this case there is no difference whatsoever as you are not using the value of the expression.
Since you're not assigning the expression to anything, there's no difference apart from a slight performance gain in the pre-incrementer (because a temporary variable is created in order to store the multiple values of p with the post-incrementer). JSBEN.CH.
Just so you know the difference between them:
let var1 = 3;
let var2 = 4;
console.log(var1++); //Outputs the value of var1, then increments it
console.log(++var2); //Increments the value of var2, then outputs it
The += syntax is actually better in this case, because it is easier to read, and it is just a compaction of p = p + 1 - literally no difference, performance-wise or otherwise. This means it's actually faster.
If you put the two plus in front or after the variable/number only makes a different for evaluating it.
Because it is only inportant that the counter is incremented after leaving the block. If this is done before or after doesnt matter. At the end of the call the number is incremented equally.
++p first it will count +1 and then return the result
p++ it will return the value and then add +1
p value will be different at the end of each turn in those 2 cases.
In your example there is no difference.
However if you use the increment ++ or decrement -- operators inside a function the positioning is significant. To quote the article
JavaScript Increment ++ and Decrement --
If the operand is after the variable console.log displays a then it is incremented
let a = 1;
console.log(a++); // 1
console.log(a); // 2
If the operand is before the variable a it is incremented then console.log displays it
let a = 1;
console.log(++a); // 2
console.log(a); // 2
Several other languages such as C and C++ have the same behaviour.
However these operators need to be used with care. See the following stackoverflow answer (albeit it refers to JavaScript, but also applies to C etc)
Why avoid increment (“++”) and decrement (“--”) operators in JavaScript?
In this case there is no difference in pre and post increment.
However in some cases like this can be significant:
here n and i are first evaluated and then incremented
var n=0
var i
for(i=0;n<5;n=i++){}
after the loop n and i look like this: n=5, i=6
here n and i are evaluated first, but i is incremented before entering the cycle
var n=0
var i
for(i=0;n<5;n=++i){}
after the loop n and i look like this: n=5, i=5
For example, in the following JavaScript code, why do we not get errors when using variables, but when a number literal is used, I get an error (running on node v6.9.5)?
let x = 2;
console.log(x++); //2
let y = 2;
console.log(++y); //3
console.log(2++); //ReferenceError: Invalid left-hand side expression in postfix operation
console.log(++2); //ReferenceError: Invalid left-hand side expression in prefix operation
My understanding is that this doesn’t work because you can’t mutate the literal 2. In the previous example, you returned x or y (either before or after incrementing), so it was now equal to +1 its previous value (so x/ y now pointed to 3, rather than 2). However, you can’t increment 2 to be +1 its previous value and then have it point to the literal 3. 2 will always be 2, 2 will never point to 3.
Am I correct in my reasoning?
Literals are constants, and increment/decrement would try to change its argument respectively. But constant values cannot be changed.
It would be the same like coding something like
2 = 2 + 1;
The argument of a increment/decrement operator must be a lvalue -- essentially, it has to be an expression that you could assign a value to. This can be either a variable, or certain types of simple structured expressions (like array[0]++ or object.foo++).
Constants aren't lvalues. You can't assign a value to them (3 = abc), nor can you mutate their values with the increment or decrement operators.
I know that var some = []; creates a new array and var someother = {} creates a new object. So what does the () do?
Specifically, in the following code :
var someVar = (1,2,3); //someVar equals 3
and
typeof (1,2,3) //returns "number"
So what does the () do in the above code?
See precedences of operators.
(1,2,3)
is just
3
because the comma operator returns the last value.
The parenthesis in
typeof (1,2,3)
just prevent it to be interpreted as
(typeof 1),2,3
because the typeof operator has a higher precedence than the comma operator.
That is a grouping operator.
It causes the contents to be evaluated as an expression in their own right. Effectively it changes precedence since otherwise the someVar = 1 would be evaluated first (instead of the result of (1,2,3) being evaluated and the result used in the someVar = ... expression.
That expression 1,2,3 uses a comma operator which evaluates as the right hand side, so it is 3.
Regarding
p = 0;
(p+1)++;
> ReferenceError: Invalid left-hand side expression in postfix operation
and
p = 0;
++(p+4);
> ReferenceError: Invalid left-hand side expression in prefix operation
I just got a bit of a surprise, as I expected postfix/prefix operators to be ok with working on the resolution of the expression (brackets have the highest operator precedence).
Could someone give me with a line or three to explain what is happening here?
Thanks
EDIT: Thanks for the quick responses, first answer marked as the answer. I feel I should also point people to the indepth answer from #thefourtheye below
++ increments the value of a variable, so it is larger than before. Eg:
var x = 3;
x++;
alert(x); // will show 4
For there to be any point for this, the expression to the left of ++ must be accessible and mutable, otherwise the increment would be possible. Eg:
3++
doesn't make any sense, as 3 is a constant and can't be incremented. We don't want this to be possible:
3++;
alert(3); // outputs 4???
This is why your expression doesn't work. Ie:
var p = 2;
(p + 1)++;
has the same problem as above. (p + 1) will evaluate to 3, and ++ can't change the value of the constant 3.
You are trying to increment (), the increment/decrement operator can be apply on variable, try the sample code
(p++) + 1
OR
(++p) + 1
Remember that when you write p++, that actually gets translated to p = p + 1. The operators ++ and -- are convenience notation for incrementing/decrementing a variable for future use. But how is (p+1)++ or ++(p+4) supposed to be translated? Those sort of imply that 1 or 4 are being incremented/decremented for future use, which doesn't make sense.
When you have an expression like this
(expr)++;
These are the operations JavaScript will do internally
Resolve the actual object referenced by expr.
This step is important, because you can even do something like this
var a = {b: 1};
++a.b;
a.b++;
console.log(a.b);
# 3
Now, JavaScript has to resolve the actual object to be incremented. In this case, it will be b in a.
Get the value at the reference and convert that value to a Number.
This step is also very important, because you may even have values like this
var a = {b: '1'};
console.log(++a.b);
# 2
JavaScript will try its best to get a number value, instead of failing immediately.
Increment the number.
Store the new vale in expr. This is step where your expression is failing.
In your case expr is p + 1, when it is resolved the value would be just a numeral, whose value can never be changed. (You can never change the value of 1 to something else). So, after the incrementing part, when the new value has to be stored back, JavaScript doesn't find a valid reference to store it. That is why it throws this error.
ReferenceError: Invalid left-hand side expression in postfix operation
This error message is actually thrown from internal PutValue method. The very first step goes like this
If Type(V) is not Reference, throw a ReferenceError exception.
Reference: ECMA Script 5.1 Standard Specification for Prefix Increment Operator