admin管理员组

文章数量:1127686

I was practicing some JavaScript when one of my friends came across this JavaScript code:

document.write(('b' + 'a' + + 'a' + 'a').toLowerCase());

I was practicing some JavaScript when one of my friends came across this JavaScript code:

document.write(('b' + 'a' + + 'a' + 'a').toLowerCase());

The above code answers "banana"! Can anyone explain why?

Share Improve this question edited Aug 24, 2019 at 23:24 BSMP 4,7978 gold badges35 silver badges45 bronze badges asked Aug 12, 2019 at 5:50 HV SharmaHV Sharma 5,0874 gold badges16 silver badges32 bronze badges 7
  • 35 That second plus is an unary operator: +"a" is NaN. – Gerardo Furtado Commented Aug 12, 2019 at 5:54
  • 11 In a console, write +'a' by itself and see what happens. – Some programmer dude Commented Aug 12, 2019 at 5:54
  • 26 And for those eager for more. See full fun list – Giddy Naya Commented Aug 12, 2019 at 6:13
  • 4 Strongly related: stackoverflow.com/q/9032856 – Kyll Commented Aug 13, 2019 at 14:21
  • 1 Also related: What is the explanation for these bizarre JavaScript behaviours mentioned in the 'Wat' talk for CodeMash 2012? – Herohtar Commented Aug 14, 2019 at 21:20
 |  Show 2 more comments

8 Answers 8

Reset to default 629

+'a' resolves to NaN ("Not a Number") because it coerces a string to a number, while the character a cannot be parsed as a number.

document.write(+'a');
To lowercase it becomes nan.

Adding NaN to "ba" turns NaN into the string "NaN" due to type conversion, gives baNaN. And then there is an a behind, giving baNaNa.

The space between + + is to make the first one string concatenation and the second one a unary plus (i.e. "positive") operator. You have the same result if you use 'ba'+(+'a')+'a', resolved as 'ba'+NaN+'a', which is equivalent to 'ba'+'NaN'+'a' due to type juggling.

document.write('ba'+(+'a')+'a');

'b' + 'a' + + 'a' + 'a'

...is evaluated as....

'b' + 'a' + (+'a') + 'a'

(see: operator precedence)

(+'a') attempts to convert 'a' to a number using the unary plus operator. Because 'a' is not a number, the result is NaN ("Not a Number"):

'b'  +  'a'  +  NaN  + 'a'

Although NaN stands for "Not a Number", it's still a numeric type; when added to strings, it concatenates just as any other number would:

'b'  +  'a'  +  NaN  + 'a'  =>  'baNaNa'

Finally, it's lowercased:

'baNaNa'.toLowerCase()      =>  'banana'
('b' + 'a' + + 'a' + 'a').toLowerCase()

For clarity, let's break this down into two steps. First, we get the value of the parenthesized expression and then we apply the toLowerCase() function on the result.

Step one

'b' + 'a' + + 'a' + 'a'

Going L-R, we have:

  • 'b' + 'a' returns ba, this is regular concatenation.
  • ba + + 'a' attempts to concatenate ba with + 'a'. However, since the unary operator + attempts to convert its operand into a number, the value NaN is returned, which is then converted into a string when concatenated with the original ba - thus resulting in baNaN.
  • baNaN + 'a' returns baNaNa. Again, this is regular concatenation.

At this stage, the result from step one is baNaNa.

Step two

Applying .toLowerCase() on the value returned from step one gives:

banana

There are many similar puns in JavaScript that you can check out.

It's just because of + operator.

We can get further knowledge from chunk it.

=> ( ('b') + ('a') + (++) + ('a') + ('a'))
=> ( ('b') + ('a') + (+) + ('a') + ('a')) // Here + + convert it to +operator 
Which later on try to convert next character to the number.

For example

const string =  '10';

You can convert a string into number by 2 ways:

  1. Number(string);
  2. +string;

So back to the original query; Here it tries to convert the next char ('a') to the number but suddenly we got error NaN,

( ('b') + ('a') + (+'a') + ('a'))
( ('b') + ('a') + NaN + ('a'))

But it treats as a string because the previous character was in the string. So it will be

( ('b') + ('a') + 'NaN' + ('a'))

And last it converts it to toLowerCase(), So it would be banana

If you are put number next to it, Your result will be change.

( 'b' + 'a' +  + '1' + 'a' ) 

It would be 'ba1a'

const example1 = ('b' + 'a' + + 'a' + 'a').toLowerCase(); // 'banana' 
const example2 = ('b' + 'a' + + '1' + 'a').toLowerCase(); // 'ba1a'
console.log(example1);
console.log(example2);

This line of code evaluates an expression and then calls a method based on the returned value.

The expression ('b' + 'a' + + 'a' + 'a') is solely composed of string literals and addition operators.

  • String Literals "A string literal is zero or more characters enclosed in single or double quotes."
  • The Addition operator ( + ) "The addition operator either performs string concatenation or numeric addition."

An implicit action taken is the call for ToNumber on a string

  • ToNumber Applied to the String Type "ToNumber applied to Strings applies grammar to the input String. If the grammar cannot interpret the String as an expansion of StringNumericLiteral, then the result of ToNumber is NaN."

The interpreter has rules of how to parse the expression, by breaking it down into its components of left and right hand expressions.


Step 1: 'b' + 'a'

Left Expression: 'b'
Left Value: 'b'

Operator: + (one of the expression sides is a string, so string concatenation)

Right Expression: 'a' Right Value: 'a'

Result: 'ba'


Step 2: 'ba' + + 'a'

Left Expression: 'ba'
Left Value: 'ba'

Operator: + (one of the expression sides is a string, so string concatenation)

Right Expression: + 'a' (this evaluates the Math Value of the character 'a' assuming that it is a positive number from the + sign -- the minus sign would have also worked here indicating a negative number -- which results in NaN)
Right Value: NaN (because the operator is string concatenation, toString is called on this value during concatenation)

Result: 'baNaN'


Step 3: 'baNaN' + 'a'

Left Expression: 'baNaN'
Left Value: 'baNaN'

Operator: + (one of the expression sides is a string, so string concatenation)

Right Expression: 'a'
Right Value: 'a'

Result: 'baNaNa'


After this the grouping expression has been evaluated, and toLowerCase is called which leaves us with banana.

Using + will convert any value to Number in JavaScript!

So...

The main thing here to know first and learn from is using + before any value in JavaScript, will convert that value to a number, but if that value can not be converted, JavaScript engine will return NaN, which means, not a number (can not be converted to a number, mate!) and the rest of story as below:

Read more about NaN at W3Schools or Mozilla Developer Network

See the magic here. Second plus is an unary operator which gives 'NaN'

console.log(('b' + 'a' + + 'a' + 'a').toLowerCase());
console.log(('b' + 'a' + + 'a' + 'a'));
console.log(('b' + 'a' + 'a' + 'a').toLowerCase());

本文标签: javascriptWhy is the result of (39b3939a3939a3939a39)toLowerCase() 39banana39Stack Overflow