An operator issue in JS - javascript

code block 1:
var a = (1 + - + + + - + 1);
alert(a); //2
Why does a equal 2?
code block 2:
var a = (1+-+++-+1);
alert(a); //ReferenceError: Invalid left-hand side expression in prefix operation

When using spaces in your expression it is discarding the previous operator this is why code block two errors and code block one is basically doing:
var a = (1 + 1);

First, the other answer are correct as to the "weird" behavior in the first case. The reason you're getting the ReferenceError in the second case without the spaces is because two of those +s are being treated as the ++ increment command.
1+-+(+(+-1)) won't give you an error

Actually, it is just basic math. It gets grouped and evaluates like this
1 + (- (+ (+ (+ (- (+ 1))))))
It isn't discarding the previous operators. It's just using the basic law that - multiplied by + is -.
For example, the following is just being grouped like 1 - (+ 1) which is 1 - 1 which is 0
1 - + 1 // 0
Now, when you don't use space, the javascript interprets it as increment and decrement operators and hence the error.

Related

What does +a + +b mean in JavaScript?

There was an answer to a nested array problem on stack overflow that involved a return statement +a + +b. (no period) What is this? What does it do? It seems to add, but I'm not sure how it does that. How does it differ from a + b? The code is below, and it works:
var array= [1, 2, [3, 4], [], [5]];
var sum = array.toString().split(",").reduce(function(a, b) { return +a + +b;
});
console.log(sum);
The + before the variable is the unary + operator. You are probably familiar with the unary -, e.g. -x.
Both +x and -x convert x to a number, but -x also changes its sign. This is not the primary purpose of the existance of the unary +, but it is a nice sideeffect.
Therefore, the difference between a + b and +a + +b would be visible from this example:
x = '9'; // '9'
x = +'9'; // 9
x = '9' + '9'; // '99'
x = +'9' + +'9'; // 18
JavaScript is dynamically typed, but has no built-in operators for casting a value to ensure it is the right type for an operation. Consequently, various tricks are used when it's important that a value is treated as a number, or a string, etc.
In this case, the operator being used is the "unary +" which is the natural counterpart of the "unary -" that would be used to write a negative number: just as "-x" means "0 - x", "+x" means "0 + x". On a number, this has no effect, but other values will be converted to a number.
This is important because the "binary +" operator does different things depending on the type of its operands: if a was a string, a + b would mean "append two strings together" rather than "sum two numbers".
Given an imaginary cast_to_number function, the equation could be more readably written as return cast_to_number(a) + cast_to_number(b).
Assuming a or b were of type String, adding a + operator in front of it will coerce it to a number.
This ensures that ’1’ + ‘1’ will be 2 (addition of numbers) and not 11 (concatenation of strings).
javascript has a unary operator + and -, both of them converts the operand to a number type, but the - operator negate the result.
for example:
> -'20'
-20
> +'500' + +'600'
1100
The + unary operator is used for explicit coercion in JavaScript.
Even though some developers look down upon it, saying var num = 3 + +c; is rather ugly especially to people not aware of the coercion at hand, potentially even "error-like" looking piece of code.
The most common practical use of the + unary operator is probably to get a number timestamp of the date
var timestamp = +new Date(); // this works!
Perhaps a good piece of memorablia is the - unary operator, which for some reason our human brain seems much happier to interpret. Basically, if we see var x = -c; we presume the compiler:
Attempts to do a value to number coercion of the variable c
If it can return a number, flip the sign and return the negative number (-)
The + unary operator does the same thing, only without the sign flipping.

Using the "+" (plus) and the "," (comma) in javavascript prompt(), document.write() and console.log()

I am a bit confused as to how JavaScript is interpreted for the following:
1.
n = prompt("Please enter a number to calculate factorial " + "Now!", "Delete this first!" + " ...And this :(", "Hello");
I assume that the comma "," is used to separate the arguments sent to the function, and that prompt() takes either one(1) or two(2) arguments and discards the third one: "Hello" ?
2.
How are "," commas interpreted in the document.write() function and the console.log() function.
Are they used to separate arguments? Can these functions take an infinite number of arguments?
3.
In these examples:
console.log("1.) expression " , (1<2).toString() + 3>2);
console.log("2.) expression " , (3<2).toString() , 3>2);
console.log("3.) expression " + (3>2).toString() + 3>2);
console.log("4.) expression " , 3<2);
console.log("5.) expression " + 3<2);
console.log("6.) expression " + n + 3<2);
OUTPUTS:
1.) expression false
2.) expression false true
3.) false
4.) expression false
5.) false
6.) false
I'm guessing the "+" is treated as part of the expression and not to concatenate strings when it encounters another operator?
In the first expression, was (1<2).toString() added to 3? What kind of type and what value was it converted to? Why does it evaluate to false?
Can I assume that the document.write() and console.log() functions treat the "," (comma) differently than other functions?
Regarding prompt
I assume that the comma "," is used to separate the arguments sent to the function, and that prompt() takes either one(1) or two(2) arguments and discards the third one: "Hello" ?
prompt takes two arguments. Any extras are ignored as is the case of all functions in JavaScript that don't use the arguments object or rest parameters to change behaviour for a variable number of arguments.
function x ( a ) { return a; }
x( 'this', 'is', 'perfectly' ,'valid' );
Regarding document.write and console.log
Are they used to separate arguments? Can these functions take an infinite number of arguments?
Yes, a comma in a function call is always used to separate arguments. As far as I know both functions make use of a variable amount of arguments, but it is likely implementation specific.
I'll add some parenthesis to help you understand the output from those lines:
console.log("1.) expression " , ( (1<2).toString() + 3 ) > 2 );
console.log("2.) expression " , (3<2).toString() , 3>2);
console.log( ( "3.) expression " + (3>2).toString() + 3 ) > 2);
console.log("4.) expression " , 3<2);
console.log( ( "5.) expression " + 3 ) <2);
console.log( ( "6.) expression " + n + 3 ) <2);
Can I assume that the document.write() and console.log() functions treat the "," (comma) differently than other functions?
You would be wrong to assume that, but I won't try and stop you.
Disclaimer I am writing this from my understanding of Javascript and how it works. I was never formally taught Javascript, I did not study this language in college, and I've never looked this up. If it is wrong, please understand that this is my(working) knowledge of how Javascript works.
The Functions
There's quite a bit to talk about for your question. First and foremost is that each of those functions are different in what they require or will accept. Prompt() accepts only two arguments: the text it outputs and the "Default text" (the text that shows up in the prompt originally). You can put in more arguments, but the function isn't coded to do anything with them so nothing happens.
The console.log() function, much like the document.write() function take a variable (and theoretically infinite) number of arguments. Each argument is evaluated and passed to those functions. Console.log and document.write will both simply output those expressions to their respective locations (the Javascript Console or the document object)
The + Operator
This is the trickier part to answer, and is again written from entirely my own understanding of Javascript. The + operator in Javascript is dual function. It works as both the mathematical operation of addition and the non-integer concactenator.
What I mean by that long string of words is this: Javascript, when it encounters an expression with a + in it, does its best to guess as to what is expected of it. If both items are numbers (integers, floats, doubles, boolean) it decides that you want to add the two things together. If either one is not a number, then it decides you want to concat the two things together. This isn't always correct, and sometimes it baffles even the best of us.
Your console tests look a little like this in the world of behind-the-scenes javascript.
console.log("1.) expression ", (1 < 2).toString() + 3 > 2);
//gets evaluated to :
//"1.) expression ", "true"+3 > 2)
//= "1.) expression", "true3" > 2) <- can't compare these two logically, so we get false
//= "1.) expression", false <- is finally passed to function
console.log("2.) expression ", (3 < 2).toString(), 3 > 2);
//"2.) expression ", "false" , true
console.log("3.) expression " + (3 > 2).toString() + 3 > 2);
//"3.) expression " + "false" + 3 > 2
//="3.) expression false" + 3 > 2
//="3.) expression false3" > 2 <- same thing, can't logically compare, so false.
console.log("4.) expression ", 3 < 2);
//"4.) expression ", false
console.log("5.) expression " + 3 < 2);
//"5.) expression 3" < 2 <- can't logically compare
//false
console.log("6.) expression " + n + 3 < 2);
//Same thing as #4, but not with an extra variable that gets combined to the string.
I think of this like order of operations, prioritizing grouped expressions first and then going left to right.

What does JavaScript interpret `+ +i` as?

An interesting thing I've never seen before was posted in another question. They had something like:
var i = + +1;
They thought the extra + converted it to a string, but they were simply adding to a string which is what caused it to convert.
This, however, lead me to the question: what is going on here?
I would have actually expected that to be a compiler error, but JavaScript (at least in Chrome) is just fine with it... it just basically does nothing.
I created a little JSFiddle to demonstrate: Demo
var i = 5;
var j = + +i;
document.body.innerHTML = i === j ? 'Same' : 'Different';
Anyone know what's actually occurring and what JavaScript is doing with this process?
I thought maybe it would treat it like ++i, but i doesn't increment, and you can even do it with a value (e.g., + +5), which you can't do with ++ (e.g., ++5 is a reference error).
Spacing also doesn't affect it (e.g., + + 1 and + +1 are the same).
My best guess is it's essentially treating them as positive/negative signs and putting them together. It looks like 1 == - -1 and -1 == + -1, but that is just so weird.
Is this just a quirky behavior, or is it documented in a standard somewhere?
Putting your the statement through the AST Explorer, we can see that what we get here is two nested Unary Expressions, with the unary + operator.
It's a unary expression consisting of + and +i, and +i is itself a unary expression consisting of + and i.
The unary expression with the unary + operator, will convert the expression portion into a number. So you're essentially converting i to a number, then converting the result of that to a number, again (which is a no-op).
For the sake of completion, it works on as many levels as you add:
var i = 5;
console.log(+ + + + + +i); // 5
console.log(i); // still 5
It's in the specification.
Digging through, we can see from §14.6.2.2 that the increment and decrement operators are listed before (and should be preferred) over the unary operators. So precedence alone won't explain this.
Looking up the the punctuation table in §11.7, we can see that every single instance of ++ (the operator) in the spec shows the two together, without whitespace. That's not conclusive, until you check...
The whitespace rules in §11.2, specifically:
White space code points may occur within a StringLiteral, a RegularExpressionLiteral, a Template, or a TemplateSubstitutionTail where they are considered significant code points forming part of a literal value. They may also occur within a Comment, but cannot appear within any other kind of token.
JS does not allow arbitrary whitespace mid-operator.
The JS syntax in both PegJS and Esprima corroborate this, matching on the literal two-character string ++.
For me it's very clear;
var a = +3;
var b = +a; // same as a, could be -a, for instance
var c = + +a; // same as above, same as +(+a)
If you do ++variable the javascript interpreter sees it as the increment operator.
If you do + +variable the javascript interpreter sees it as Unary plus, coercing the value to a number, twice.
So
var a = 1;
var b = +a;
var c = +b;
console.log(c);// still 1
is the same as
var c = + +1;
So the simple answer is that two plus signs can not be separated by a space to be interpreted as incrementation, the space makes it so the interpreter sees two seperate spaces, which is what it really is
The + operators converts into a number, two + operators with a space in between does nothing additional.
Even though it might look very similar, + + and ++ are not at all the same thing for an AST interpreter. The same applies to token separation: varfoo is not the same as var foo.
In the expression + + +i, each + is considered as distinct unary operator, which simply convert your variable to a number. For the incrementation operation, which is ++, no spaces are allowed, neither between the + and the variable token. In the example below, the last line is not valid:
var x = "4";
console.log(+ + +x);
console.log(+ + ++x);
console.log(+ ++ +x);

What is the purpose for multiple comma-separated expressions in a WHILE condition?

I stumbled over the following JavaScript:
Code:
var x="", i=0;
while (i<4, i<7, i<5, i<6)
{
x=x + "The number is " + i + "<br>";
i++;
}
document.write(x);
I never know that it is possible to use multiple comma-separated expression in one WHILE statement.
Result:
The number is 0
The number is 1
The number is 2
The number is 3
The number is 4
The number is 5
What is the reason for this and what is the behavior (only the last expression is evaluated for the while-exit)?
Is the behavior standardize in all Javascript/C/Java languages?
Only the last result is kept in result of the comma operator, so
while (i<4, i<7, i<5, i<6)
is really equivalent to
while (i<6)
That's the reason why you don't see this more often : it's useless if your comparisons don't have side effects.
This is a special operator in JavaScript which is called comma operator;
so when JavaScript comes across this line
(i<4, i<7, i<5, i<6)
it will evaluate one by one all the operands in the parenthesis and will return the evaluation of the last item i.e. i < 6
It is rarely used; One occasion that I remember to have used it was for indirect call to eval.
(0, eval)(src)
But again in you example the use of it is redundant.

Why does "a + + b" work, but "a++b" doesn't?

I was fiddling around with different things, like this
var a = 1, b = 2;
alert(a + - + - + - + - + - + - + - + b); //alerts -1
and I could remove the spaces, and it would still work.
a+-+-+-+-+-+-+-+b
Then I tried
a + + b
It ran and evaluated to 3, but when I removed the spaces, (a++b) it wouldn't run, and it had a warning which read "Confusing plusses."
I can understand that in cases like
a+++++b
which could be interpreted as any of the following
(a++) + (++b)
(a++) + +(+b)
a + +(+(++b))
a + +(+(+(+b)))
that it would be confusing.
But in the case of
a++b
the only valid way to interpret this, as far as I can tell, is
a + +b
Why doesn't a++b work?
The Javascript parser is greedy (it matches the longest valid operator each time), so it gets the ++ operator from a++b, making:
(a++) b
which is invalid. When you put in spaces a + + b, the parser interprets it like this:
(a) + (+b)
which is valid and works out to be three.
See this Wikipedia article on Maximal munch for more details.
It's reading a++, then it encounters a b and doesn't know what to do with it.
This is b/c of the difference in unary operators.
"a + + b" is the same as "a + (+b)"
"a++b" is the same as "(a++) _ b" <--- there is a missing operator where the _ is
Javascript's operator precendence rules for the ++ increment operator has no left-right associativitity. That means a++b can be interpreted as a++ b or a ++b depending on the particular implementation. Either way, it's a syntax error, as you've got 2 variables, one unary-operator, and nothing joining the two variables.
In practical terms:
a = 1
b = 2;
a++ b; -> 2 2
a ++b; -> 1 3
What does 1 3 mean as JS code?
Most programming language parsers tries to get longest chunk of text that make sense, so when Javascript sees:
[a][][][][]
"variable a" - it make sense, let's see next character:
[a][+][][]
"will be adding to varaible a" - it make sense, let's see next character:
[a][+][+][]
"will post-increment variable a" - it make sense, let's see next character,
[a][+][+][b]
This does not make sense. I have two expressions (a++) and (b) and no infix operator between them.
If you make it a+ +b it will not find the ++ operator and it will work as a + + b.
Longest Match rule comes into picture here. It says parser has to take longest token into consideration starting from left to right (I assume Javascript's grammar is Left to Right). So just apply this rule and you will get your answer.
Parser will start from left and will make a, +, + & b separate tokens in case of "a + + b" (due to white space in between them). In case of "a++b" it will apply longest match rule and will create a++ & b as token. a++ b as an expression does not make any semantic sense hence it will not be compiled.
The answer is that ++ is an operator as well as +, and that + + is two + operators, not a ++ operator.
Although it's not Javascript, C++ has similar fun with + and ++ operators. This was investigated in one of the Gurus of the Week from way back when.

Categories

Resources