Why does 1|0,2|0 equal 2 in JavaScript? - javascript

If you evaluate 1|0,2|0 in JavaScript, you'll get 2.
If you evaluate 1|0+','+2|0, you'll get 1.
I cannot make sense of this.

The binary bitwise operators (including |) bind less tightly than the addition operator +. Thus
1|0+','+2|0
is really
1|(0+','+2)|0
which is
1|('0,2')|0
which is
1|0|0
which is 1. (The string "0,2" is converted to an integer; as a number it's NaN, but because NaN is a floating-point concept it turns into 0 when forced to be an integer.)
edit — as to the first expression, 1|0,2|0, that involves the JavaScript comma operator. The comma operator allows a list of separate, essentially independent (other than through side-effects) expressions to be "glued together" into something the parser will recognize as a single expression. When evaluated, each expression will be computed as it normally would be, but the value of the overall expression is just the value of the last one in the list. Thus, 1|0,2|0 will first cause 1|0 to be evaluated, but that result is thrown away and the overall value is just that of 2|0.
The comma operator is common to many languages that derive their expression syntax from C. (For all I know, C got it from somewhere else; it's hardly a revolutionary concept.) Because such languages allow for an expression — just one expression — to appear in several interesting grammatical situations, and because expressions can (and often do) have side effects, it's sometimes handy to be able to jam several separate expressions into a spot where the language really wants only one. That said, there are often cleaner and better ways to do things. In JavaScript, I would personally prefer to use an immediately-invoked function. It's more typing and probably a little worse for performance reasons, but I think it's a lot cleaner because it allows for an isolated namespace for temporary variables and more involved logic.

You need to look at an operator precedence table to make sense of this.
The expression 1|0,2|0 has bitwise-or at a higher precedence than the comma operator, so it's equivalent to (1|0), (2|0). The comma operator evaluates both operands and returns the second one, so you get the value of (2|0). That value is 2.
The expression 1|0+','+2|0 has addition at a higher precedence than bitwise-or, so it's equivalent to 1|(0+','+2)|0. The result of 0+','+2 is "0,2", which is not numerical, so it evaluates to NaN in numerical operations. It is coerced to 0 in bitwise-or, so that leaves 1|0|0, and the result of that is 1.

From MDN:
The comma operator evaluates both of its operands (from left to right)
and returns the value of the second operand.
Thus, in 1|0,2|0, first the two expressions 1|0 and 2|0 are evaluated from left to right and then the result of the last expression (2|0) is returned. 1|0 === 1 and 2|0 === 2, so the result of the last expression is 2 and that's returned.
In 1|0+','+2|0, the comma appears in a string literal which is concatenated with 0 and 2. The whole thing is evaluated as followed:
( 1 | ( (0+',')+2 ) ) | 0
( 1 | ( '0,'+2 ) ) ) | 0 (number + string = string concatenation)
( 1 | '0,2' ) | 0 (string + number = string concatenation)
( 1 | NaN ) | 0 (bitwise OR needs number operands. 0,2 fails to be converted, giving NaN instead)
1 | 0 (bitwise OR only deals with integers, so the floating-point NaN is cast to 0)
1

Related

How does type conversion happens in JavaScript?

(1) console.log(8*null)
// output to 0 ( null changes to 0)
(2) console.log("5"-1)
//output to 4 ("5" changes to 5)
(3) console.log("5"+1)
//output to "51" (1 changes to "1")
As if you see the above lines of code , some times type conversion happens on left hand side and some times it happens on right hand side of the binary operator.
So my question is how does JavaScript decides which operand type needs to be changed, does it happens internally (without in the knowledge of user) or is there any precedence of data type is there??
Because * is a multiplicative operator, it calls the specification's ToNumber abstract operation on both of its operands (first the left one, then the right one). The result of ToNumber(null) is 0 (see the link for a table), so 8 * 0 is 0.
Because - is a subtraction operator, it also calls ToNumber on its operands. So you get 5 - 1 which is 4.
The + operator has two meanings: Mathematical addition, and string concatenation. If either operand is a string, you get concatenation, not addition. More formally: It first converts its operands to primitives via the spec's abstract ToPrimitive operation, and then determines whether either operand's primitive value is a string, and does concatenation if so. In the case of +, it doesn't matter which operand (the left or right) is a string, it can be either and that makes it concatenation rather than addition.
So my question is how does JavaScript decides which operand type needs to be changed, does it happens internally (without in the knowledge of user) or is there any precedence of data type is there??
It's spelled out in very, very thorough detail in the specification, so if you have any doubts in a particular situation, that's where to look.

What is this asm style "x | 0" some javascript programmers are now using?

I've seen some performance critical javascript code, like the one on this project that makes extensive use of bitwise OR operations with 0. Ex:
GameBoyAdvanceCPU.prototype.write8 = function (address, data) {
address = address | 0;
data = data | 0;
this.memory.memoryWrite8(address | 0, data | 0);
I know about the use case of flooring numbers with "|0", but that isn't the case here, as these are always int's. It looks a bit like asm.js, is this to tell the js engine that we are working with integers, allowing some optimizations? If so, which browsers will make those optimizations?
Any pointers to how this works would be appretiated.
According to JavaScript Performance for Madmen
Wrapping integer arithmetic expressions in ( ) | 0 allows the runtime to be sure that you're doing integer arithmetic instead of floating-point arithmetic. This allows it to avoid checking for overflow and produce faster code in many cases.
and according to the page, it's true for "most" Javascript runtimes, but doesn't say which.
As a second source, Writing Fast JavaScript For Games & Interactive Applications states
To tell JavaScript engine we want to store integer values [...] we could use bitwise or operator:
and a third source from Microsoft's Writing efficient JavaScript page:
[...] explicitly tell the JavaScript runtime to use integer arithmetic [...] use the bitwise or operator
Also, apart from in comments, none of the pages above mention asm.js, so I suspect such optimizations apply in code not explicitly marked as asm/in browsers that don't explicitly recognize it.
Referencing the Ecmascript 5 spec: 11.10 Binary Bitwise Operators, namely
The production A : A # B, where # is one of the bitwise operators in
the productions above (&; ^; |), is evaluated as follows:
Let lref be the result of evaluating A.
Let lval be GetValue(lref).
Let rref be the result of evaluating B.
Let rval be GetValue(rref).
Let lnum be ToInt32(lval).
Let rnum be ToInt32(rval).
Return the result of applying the bitwise operator# to lnum and rnum. The result is a signed 32 bit integer.
And noting that ToInt32() is defined as
Let number be the result of calling ToNumber on the input argument.
If number is NaN, +0, −0, +∞, or −∞, return +0.
Let posInt be sign(number) * floor(abs(number)).
Let int32bit be posInt modulo 2^32; that is, a finite integer value k of Number type with positive sign and less than 2^32 in magnitude such that the mathematical difference of posInt and k is mathematically an integer multiple of 2^32.
If int32bit is greater than or equal to 2^31, return int32bit − 2^32, otherwise return int32bit.
It then logically follows (which you can confirm in your own console) that for example
((Math.pow(2, 32)) + 2) | 0 === 2
(Math.pow(2, 31)) | 0 === -2147483648 === -(Math.pow(2, 31))
And so forth.
Shortly put, the operation turns the number to a 32-bit integer (which has its knacks, see the second example above and the ToInt32() definition for an explanation) and then does a logical or with zero which doesn't change the output beyond the first conversion.
Essentially it's a very cost-efficient way to turn a number into a 32-bit integer because 1) it relies on browser's built-in ToInt32(); and 2) ToInt32(0) short-circuits to 0 (see the spec above) and therefore adds practically no additional overhead.
What it actually does can be seen in this fiddle
It's probing the variable against integer type in this case and either "flooring" or set it to 0 if not an integer.
Thus, there's a tremendous differnece to a = a || 0 which would leave a value of 3.2 untouched.
| operator is bitwise OR. It's used to do a bit by bit OR operation on two integers.
The usage here is a shortcut very similar to logical OR || operator to provide default value, with the exception that the result is integer only (as opposed to string...etc)
address = address | 0;
means "if address is a number, let's use it; otherwise, set it to 0".

JavaScript concating with number as string

Why does x = "1"- -"1" work and set the value of x to 2?
Why doesn't x = "1"--"1" works?
This expression...
"1"- -"1"
... is processed as ...
"1"- (-"1")
... that is, substract result of unary minus operation applied to "1" from "1". Now, both unary and binary minus operations make sense to be applied for Numbers only - so JS converts its operands to Numbers first. So that'll essentially becomes:
Number("1") - (-(Number("1"))
... that'll eventually becomes evaluated to 2, as Number("1"), as you probably expect, evaluates to 1.
When trying to understand "1"--"1" expression, JS parser attempts to consume as many characters as possible. That's why this expression "1"-- is processed first.
But it makes no sense, as auto-increment/decrement operations are not defined for literals. Both ++ and -- (both in postfix and prefix forms) should change the value of some assignable ('left-value') expression - variable name, object property etc.
In this case, however, there's nothing to change: "1" literal is always "1". )
Actually, I got a bit different errors (for x = "1"--"1") both in Firefox:
SyntaxError: invalid decrement operand
... and Chrome Canary:
ReferenceError: Invalid left-hand side expression in postfix operation
And I think these messages actually show the reason of that error quite clearly. )
Because -- is an operator in JavaScript.
When you separate the - characters in the first expression, it's unambiguous what you mean. When you put them together, JavaScript interprets them as one operator, and the following "1" as an unexpected string. (Or maybe it's the preceding "1"? I'm honestly not sure.)
"-1" = -1 (unary minus converts it to int)
So. "1" - (-1)
now, "+" is thje concatenation operator. not -. so JS returns the result 2 (instead of string concat).
also, "1"--"1" => here "--" is the decrement operator, for which the syntax is wrong as strings will not get converted automatically in this case.
because -- is an operator for decrement and cannot be applied on constant values.

Unexpected result from expression using &

Here if
document.write(eval("(2 == 2)"));
it prints true
And
document.write(eval("(2 == 2)&(5<10)"));
it prints 1
Why not it always returns true or false.If conditions increases in string it gives 0 or 1.What is the way to get same type of result.
Because & isn't a logical operator, it's a bitwise (numeric) operator. You probably meant &&, the logical AND operator.
Note that there's no reason for using eval in your code examples. (There's almost never any reason to use eval, there's almost always a better alternative — in this case, you don't even need an alternative.) Removing it would have exactly the same result.
It prints 1 because you used the bitwise and operator (&) instead of the logical and operator (&&).
And because JavaScript is loosely typed it will treat the boolean value true as an int value of 1, which you can check by invoking
document.write(eval("(2 == 2)+(5<10)"));
the result will be
2
& is a bitwise operator and returns a number. Try "(2 == 2)&&(5<10)"

Javascript: what's difference between | and ||?

I'm looking at some Javascript code that is:
if ( a>2 | b>4 ) { ... }
(ignore the ... above). What's the | doing? I assume it's logical OR, but all the references I could find online speak about ||, and I can't find anything mentioning just |. Thanks in advance
It's the bitwise or. || is logical or.
The bitwise or (|) coerces the values to 32 bit integers and returns the 32 bit integer with each bit set to 1 if either of the two bits in the corresponding locations is 1 and 0 if they are both 0.
Logical or (||) evaluates to the first value if it's not falsey, otherwise it evaluates to the second value.
You almost definitely want || instead of |.
The difference between || and | is already explained in the other answers.
However, in the above code, | has the same effect as || due to type conversion.
true and false are mapped to 1 and 0 and we have
0 | 0 = 0
1 | 0 = 1
0 | 1 = 1
1 | 1 = 1
The same goes into the other direction, 1 evaluates to true and 0 to false.
So in this example,
if ( a>2 | b>4 )
will have the same result as
if ( a>2 || b>4 )
Note: This really only works with the two values 0 and 1.
This could be some kind of micro-optimization.
Update:
However, a short test reveals that using the bitwise OR for this purpose is way slower (at least in Chrome 9):
http://jsperf.com/js-or-test
Conclusion: Don't use it instead of logical OR :) Mostly likely someone forgot the second | and is just lucky that the code produces the same result.
Use boolean operators for boolean operations and bitwise operators for fancy bit masking. This might be worth reading: MDC - Bitwise Operators.
Single | is a bitwise-OR while double (||) is a logical-OR.
Bitwise-OR takes the binary representation of the two source values and ORs them together so that if either of the values has a bit set, the resulting value's bit will also be set (repeat for all the bits in the two source values).
Logical-OR concerns itself with true and false values (where 0 maps to false and non-zero maps to true - that's simplified, JavaScript has more specific rules). If either source value is true then the result is true.
Looks like second pipe just got lost, otherwise it is a smelly hack. See what really happens:
if ( Boolean( Number(a>2) | Number(b>4) ) ) { ... }
(Number is special here because bitwise operators are working with 32-bit integers)
It works because Number(true) === 1 && Number(false) === 0.

Categories