5

If I execute the following snippet in FireBug console it somehow prints surprise!:

['surprise!', 'boring'][Number(0=="​")]

But why?

UPD

I am sorry, people, that was a joke! Jere is the first who noticed! Yesterday I found a ZERO WIDTH SPACE in a string, and had since then temptation to have some fun =)

newtover
  • 31,286
  • 11
  • 84
  • 89

5 Answers5

10

There is an extra, non visible, character between your quotes.

If you type this out, you will get 'boring' because 0=="" evaluates to true, Number(true) evalutes to 1.

Paste these two and watch the differing output:

0=="​"

outputs false

0==""

outputs true

The only thing I have changed is deleting the character between "".

noob
  • 8,982
  • 4
  • 37
  • 65
Jere
  • 3,377
  • 1
  • 21
  • 28
  • 1
    Yes, Jere is right. Copy and paste line somethere, then move with keyboard arrow and you'll notice one extra stop. It might be very tiny space – welldan97 Jan 19 '12 at 14:23
  • I initially was going to type up the same answer as everbody else... but noticed the black magic. :) – Jere Jan 19 '12 at 14:23
  • Nice spot. I did think it was wrong when I pasted it into chrome console and it returned 0. Never twigged though :( – Richard Dalton Jan 19 '12 at 14:25
9

0=="​" is false (Because you have a non-printing character in the string), Number(false) is 0 (as per page 34 of the spec), and "surprise" is the 0th index of the array.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
4

ES5 11.9.3 The == operator

If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).

and

The MV of StringNumericLiteral ::: [empty] is 0.

So 0=="" returns 0 == ToNumber("") which is 0 == 0 which is true.

By the == conversion rules 0=="" is true

ES5 15.7.1.1 Number ( value ) invokes ES5 9.3 toNumber toNumber(true) === 1

And ["suprize!", "boring"][1] returns "boring" which is clearly incorrect.

Why is it correct? Because

"​".charCodeAt(0) === 8203

Your string literal is not the empty string. You have a zero width space in your string.

Now if we go back to ES5 11.9.3 == operator we see

If the grammar cannot interpret the String as an expansion of StringNumericLiteral

Which means

  • 0==""
  • 0==NaN
  • false
  • toNumber(false) === 0
  • Number(0=="") === 0
  • ["suprize!", "boring"][0] === "suprize!"
Raynos
  • 166,823
  • 56
  • 351
  • 396
1

['surprise!', 'boring'][Number(0=="​")] will return 'boring' becouse your code:

Number(0=="​") //returns true

But your code is diferent, you have an invisible char in your text, that's why is returning false.

If you write the code correctly will return true and the result will be boring as expected.

But if copy and paste your code, will return false, that's why you have a char between the "​" (you can check using keyboard or "​".length)

so your code will return false, that will be 0 then return 'surprise!'

You are cheating man :P

['surprise!', 'boring'][Number(0=="​")]

"​".length //returns 1 ;)

"​" != "" // OH GOD THIS IS TRUE :P
Gabriel Gartz
  • 2,840
  • 22
  • 24
0

I get boring when ran this in console console.log(['surpeise!','boring'][Number(0=="")])

Pratik
  • 337
  • 2
  • 8