Unusual javascript syntax - javascript

could someone please explain to me what is going on in the second line here ? :
var foo = function(){alert("hello?")};
(0,foo)();

The infamous comma expression a,b evaluates both arguments and returns the value of the right-hand expression.
Hence in this case it's exactly the same as foo();.
Here's a better example that will help you understand what's going on:
function foo() {
print("foo called");
return 123;
}
function bar() {
print("bar called");
return 456;
}
var result = (foo(), bar());
print("result:", result);
Output:
foo called
bar called
result: 456
Also the comma expression may be confused with the comma delimiting function arguments. Not the same! Notice the difference:
print("result:", foo(), bar() ); // 3 arguments, no comma operator
print("result:", (foo(), bar()) ); // 2 arguments, comma operator

It's evaluating both expressions in the first parenthesis and executing the second one (in this case - a function).
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Comma_Operator

Since the Comma operator in javascript evaluates multiple operands and returns the last one. MDN:
The comma operator evaluates both of its operands (from left to right) and returns the value of the second operand.
Your expression (0,foo)
returns foo which then is invoked by the paranthesis, put after it.

the comma will evaluate operands and return the last one
the second line will return foo

Related

nest if./else if statement default to last else even if parameters above are true [duplicate]

I have a twofold question which involves something I would consider to be incorrect Javascript code.
How is the following statement interpreted in Javascript, and why?
(1,2,3,4)
Why is there a difference between these two invocations:
var a = (1,2,3,4);
a();
which leads to a being equal to 4 and Uncaught TypeError: a is not a function being thrown, and
(1,2,3,4)();
which leads to Uncaught TypeError: (((1 , 2) , 3) , 4) is not a function?
How is the following statement interpreted in Javascript, and why?
(1,2,3,4)
That's a comma operator expression (actually, a chain of them) wrapped in grouping parentheses. The comma operator is quite unusual: It evalutes both of its operands, then takes the value of the second one as its value, throwing away the value of the first one. You have a chain of them there, so the value of 1 is evaluated, then 2, then 3, then 4, and the result of the comma operator chain is the value 4; the result of the grouped parentheses expression is therefore 4.
Why is there a difference between these two invocations:
var a = (1,2,3,4);
a();
Because of the syntax of the language. In the first case, it's clearly not a function call, as there's no value prior to the first ( to call. The parsing rules for a complex language like JavaScript are just that: Complex. The parser is context-sensitive, and knows how to differentiate between grouping parentheses and function-call parentheses.
which leads to a being equal to 4 and Uncaught TypeError: a is not a function being thrown, and
(1,2,3,4)();
which leads to Uncaught TypeError: (((1 , 2) , 3) , 4) is not a function?
In both cases, the error message is quoting the expression that yielded the result it then tried to call as a function.
There is an operator in JS (among other languages) called the comma operator. It simply takes two operands, and returns the rightmost one.
a = 1, 2; // a now equals 2
It is, however, not the same comma as the function parameter separator. It is an operator.
The comma operator evaluates each of its operands (from left to right) and returns the value of the last operand.
So, the statement (1,2,3,4); returns 4, so var a = (1,2,3,4); means that a is equal to 4 which, is not a function, thus the error.
Likewise, (1,2,3,4) is just a grouping of comma operators and not a function, thus the second error.

Why does a list of arguments wrapped in braces return the last argument?

I'm correcting some basic Javascript assignments and a student has stumped me with this particular line in a constructor:
this.c = (255, 255, 255);
I'd like to explain to them (and to myself) why this statement, or any like it, will evaluate to the last 'argument' given.
console.log( ("foo", 42, {}, NaN) ) --> NaN
console.log( ("foo", 42, {}) ) --> Object
console.log( ("foo", 42) ) --> Number
console.log( ("foo") ) --> String
console.log( () ) --> SyntaxError // no longer the same thing
In the case of their assignment, they use that property as an RGB value, yet only stick to monochrome and thus their code still functions as intended. I'd like to know what that statement is called (if it has a name?) and what's happening in terms of the JS spec that has it behaving like so.
Thanks in advance.
It's the comma operator. It's an unusual operator: It evaluates its left-hand operand, throws that value away, evaluates its right-hand operand, and uses the result as its result value. You sometimes see it used where evaluating the first operand has a side-effect:
const a = (console.log("foo"), 42);
console.log(a);
The MDN page linked above is slightly inaccurate, suggesting that the comma operator accepts more than two operands. It doesn't, it's a binary operator (it accepts two operands); it's just that it's left-to-right associative, so
const a = (1, 2, 3);
is the same as
const a = ((1, 2), 3);

Behaviour of commas within parentheses in Javascript

I have a twofold question which involves something I would consider to be incorrect Javascript code.
How is the following statement interpreted in Javascript, and why?
(1,2,3,4)
Why is there a difference between these two invocations:
var a = (1,2,3,4);
a();
which leads to a being equal to 4 and Uncaught TypeError: a is not a function being thrown, and
(1,2,3,4)();
which leads to Uncaught TypeError: (((1 , 2) , 3) , 4) is not a function?
How is the following statement interpreted in Javascript, and why?
(1,2,3,4)
That's a comma operator expression (actually, a chain of them) wrapped in grouping parentheses. The comma operator is quite unusual: It evalutes both of its operands, then takes the value of the second one as its value, throwing away the value of the first one. You have a chain of them there, so the value of 1 is evaluated, then 2, then 3, then 4, and the result of the comma operator chain is the value 4; the result of the grouped parentheses expression is therefore 4.
Why is there a difference between these two invocations:
var a = (1,2,3,4);
a();
Because of the syntax of the language. In the first case, it's clearly not a function call, as there's no value prior to the first ( to call. The parsing rules for a complex language like JavaScript are just that: Complex. The parser is context-sensitive, and knows how to differentiate between grouping parentheses and function-call parentheses.
which leads to a being equal to 4 and Uncaught TypeError: a is not a function being thrown, and
(1,2,3,4)();
which leads to Uncaught TypeError: (((1 , 2) , 3) , 4) is not a function?
In both cases, the error message is quoting the expression that yielded the result it then tried to call as a function.
There is an operator in JS (among other languages) called the comma operator. It simply takes two operands, and returns the rightmost one.
a = 1, 2; // a now equals 2
It is, however, not the same comma as the function parameter separator. It is an operator.
The comma operator evaluates each of its operands (from left to right) and returns the value of the last operand.
So, the statement (1,2,3,4); returns 4, so var a = (1,2,3,4); means that a is equal to 4 which, is not a function, thus the error.
Likewise, (1,2,3,4) is just a grouping of comma operators and not a function, thus the second error.

Operators before the function call

Today I figured out that it is possible to use operations before the parenthesis of a function call.
E.g.
console.log|('Hello world!');
or
console.log>>(33);
Why is this possible and what happens?
Like in most "algol-like" languages, parentheses have multiple meanings in javascript:
grouping operator, as in 2 * (3 + 4)
function call operator, as in console.log(5)
part of function declaration syntax: function(x) {}
When you insert an operator between a function name and a function call parenthesis, this one becomes the grouping operator. It's not a function call anymore. So func(args) turns into func op (args), which is syntactically a valid expression, because functions are "first-class citizens" in javascript and can be used in expressions like any other value. Whether it makes sense is another question though, because, apart from +, operators don't produce anything meaningful when applied to functions.
Simply put: because an operator works on operands, and functions are, in JS at least, first class objects (meaning they can be passed around, and returned, and operated on).
To do so, you'll of course need to use operators. A simple, not too far fetched example:
function foo()
{
return foo.bar;//. is an operator
}
console.log(foo());//logs undefined
foo.bar = '123';//again, the . operator
console.log(foo());//logs 123
What happens in your case, however, is JS will evaluate both operands (the expressions on either side of the operator):
console.log (LOperand)
| (operator)
('hello world') (ROperand, to be evaluated further still because of the grouping operator ())
And attempt to evaluate them to compatible types for the operator to do its work. console.log is an object, a function instance in fact. hello world is a string constant inside a the grouping operator.
How these types will be coerced and evaluated is specified in the ECMAScript standard (google it), but bottom line, the function (console.log) could well be coerced to a string (as if you'd call console.log.toString(), which gives "function log() { [native code] }" on chromium). The upshot is that the code behaves the same as:
"function log() { [native code] }"|"Hello world"
which yields 0
Actually, you are not executing the function, you are just evaluating an expression (that makes no sense at all)
The console.log|('Hello world!'), will be evaluated as:
[native function] | 'Hello world!'
Which makes no sense, since "|" is a bitwise operator. Same as the other example that you gave.
So, you are not placing the operator between the function call. You are separating the values, and no longer performing the expected action (funcion call).
It is possible to use operations before the parenthesis of a function call.
Not quite so,
console.log|('Hello world!');
is equivalent to
console.log | 'Hello world!';
which has a different meaning than you intended :)
('Hello world!') is the same as 'Hello world!' and | is the bitwise OR operator in JavaScript (left | right will match the left operand with the right operand bit by bit).
In your example, console.log without parenthesis returns the function itself (as opposed to console.log() which returns undefined), so you are basically [Function] | 'Hello world!'.

Javascript "tuple" notation: what is its point?

At wtfjs, I found that the following is legal javascript.
",,," == Array((null,'cool',false,NaN,4)); // true
The argument (null,'cool',false,NaN,4) looks like a tuple to me, but javascript does not have tuples!
Some quick tests in my javascript console yields the following.
var t = (null,'cool',false,NaN,4); // t = 4
(null,'cool',false,NaN,4) === 4; // true
(alert('hello'), 42); // shows the alert and returns 42
It appears to behave exactly like a semicolon ; separated list of statements, simply returning the value of the last statement.
Is there a reference somewhere that describes this syntax and its semantics? Why does it exist, i.e. when should it be used?
You are seeing the effect of the comma operator.
The comma operator evaluates both of its operands (from left to right) and returns the value of the second operand.
The resultant value when a,b,c,...,n is evaluated will always be the value of the rightmost expression, however all expressions in the chain are still evaluated (from left to right).
As already explained this behaviour is caused by , operator. Due to this the expression (null,'cool',false,NaN,4) will always evaluate to 4. So we have
",,," == Array(4)
Array(4) - creates new array with allocated 4 elements. At the time of comparison with the string this array is converted to string like it would be with Array(4).toString(). For arrays toString acts like join(',') method called on this array. So for the empty array of 4 elements join will produce the string ",,,".
Try this alert((null,'cool',false,NaN,4)) and then you can see.
demo
The reason is because the comma operator evaluates all the statements and return the last one.
Think of this line: a = 1, b = 2, c = 3; it will run each expression so in essence it will set the variables to what you want and return the last value (in this case 3)

Categories

Resources