newtover
newtover

Reputation: 32084

Javascript: strange comparison behaviour

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 =)

Upvotes: 5

Views: 510

Answers (5)

Pratik
Pratik

Reputation: 307

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

Upvotes: 0

Jere
Jere

Reputation: 3397

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 "".

Upvotes: 10

Quentin
Quentin

Reputation: 943097

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.

Upvotes: 9

Gabriel Gartz
Gabriel Gartz

Reputation: 2870

['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

Upvotes: 1

Raynos
Raynos

Reputation: 169373

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!"

Upvotes: 4

Related Questions