Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is 1 == [1] in javascript? [duplicate]

Recently I have been asked this question in an interview.

 var a = 1;  var b = [1]; 

What will a == b; return.

When I checked that on my chrome browser console I got this.

var a = 1; var b = [1]; a == b; true 

I have also checked

var a = 1; var b =(1); a == b; true 

I know that b in an array of size 1. Does that mean that the size of array is assigned to b. I am really confused. Can anyone explain me the logic?

like image 795
hmachahary Avatar asked May 04 '16 07:05

hmachahary


People also ask

Is 1== 1 in JavaScript?

This is because JavaScript only compares the values in the statement "1" == 1 . The double equals sign tells JavaScript that even if the types are different, its allowed to coerce and compare the pure values. This is why it is often advised to use the triple equals sign, to avoid this type coercion.

Why == is false in JavaScript?

Because == (and === ) test to see if two objects are the same object and not if they are identical objects.

What is the result of 1 1 in JavaScript?

In javascript + indicates concatination. That's why when you try to add a number(i.e. 1) to a string ('1'),it becomes 11.

Which is faster == or === JavaScript?

So === faster than == in Javascript === compares if the values and the types are the same. == compares if the values are the same, but it also does type conversions in the comparison. Those type conversions make == slower than ===.


2 Answers

I didn't really understood from Rayon answer how valueOf and toString come into play when converting an object to a primitive value; so I dug into the ECMAScript 2015 specifications.

Warning: Long answer.

We want to check the expression 1 == [1].

Starting from the 12.10 Equality Operators we see that, after retrieving the expressions values, the last step is

  1. Return the result of performing Abstract Equality Comparison rval == lval

Abstract Equality Comparison is defined at chapter 7.2.12 Abstract Equality Comparison.

7.2.12 Abstract Equality Comparison
The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:

  1. ReturnIfAbrupt(x).
  2. ReturnIfAbrupt(y).
  3. If Type(x) is the same as Type(y), then
    a. Return the result of performing Strict Equality Comparison x === y.
  4. If x is null and y is undefined, return true.
  5. If x is undefined and y is null, return true.
  6. If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).
  7. If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.
  8. If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
  9. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
  10. If Type(x) is either String, Number, or Symbol and Type(y) is Object, then return the result of the comparison x == ToPrimitive(y).
  11. If Type(x) is Object and Type(y) is either String, Number, or Symbol, then return the result of the comparison ToPrimitive(x) == y.
  12. Return false.

The expression 1 == [1] falls under case 10.
So basically, as expected, the array [1] is converted into a value of primitive type.

ToPrimitive is define at 7.1.1 ToPrimitive ( input [, PreferredType] )

The abstract operation ToPrimitive takes an input argument and an optional argument PreferredType. The abstract operation ToPrimitive converts its input argument to a non-Object type.

I haven't included the full quotation since the only interesting, for this example, parts are:

  1. The PreferredType argument (actually an hint var) is converted from "default" (since it is not passed) to "number".
  2. OrdinaryToPrimitive is called with the same arguments.

E now the interesting part, OrdinaryToPrimitive do the following:

  1. Assert: Type(O) is Object
  2. Assert: Type(hint) is String and its value is either "string" or "number".
  3. If hint is "string", then
    a. Let methodNames be «"toString", "valueOf"».
  4. Else,
    a. Let methodNames be «"valueOf", "toString"».
  5. For each name in methodNames in List order, do
    a. Let method be Get(O, name).
    b. ReturnIfAbrupt(method).
    c. If IsCallable(method) is true, then
    ... i. Let result be Call(method, O).
    ... ii. ReturnIfAbrupt(result).
    ... iii. **If Type(result) is not Object, return result. **
  6. Throw a TypeError exception

So in order to convert [1] to a primitive value, the runtime try first to call valueOf. This method returns the array itself, which is an object so by 5.c.iii the method toString is called next.
This method returns the elements of the array as a comma-separated list, so it just returns the string "1".

So we are reduced comparing 1 == "1" which by the rules of Abstract Equality Comparison, point 6, means to convert "1" into the number 1 and than performing the trivial comparison 1 = 1.

The dubious reader is invited to check how Strict Equality Comparison is actually defined in the standard.


You can play with this conversions for better understanding them, here a sample playground HTML file

<html>     <head><title>title</title></head>     <body>         <script>             var old_valueOf = Array.prototype.valueOf;             var old_toString = Array.prototype.toString;              Array.prototype.valueOf = function(){ console.log("Array::valueOf"); return old_valueOf.apply(this); };             Array.prototype.toString = function(){ console.log("Array::toString"); return old_toString.apply(this); };              console.log(1 == [1]); //Array::valueOf, Array::toString, true               Array.prototype.valueOf = function(){ console.log("Array::valueOf"); return 2; };              console.log(1 == [1]); //Array::valueOf, false               Array.prototype.valueOf = function(){ console.log("Array::valueOf"); return {}; };             Array.prototype.toString = function(){ console.log("Array::toString"); return {} };              console.log(1 == [1]); //Array::valueOf, Array::toString, Uncaught TypeError: Cannot convert object to primitive value         </script>     </body> </html> 
like image 79
Margaret Bloom Avatar answered Oct 12 '22 23:10

Margaret Bloom


If an object is compared with a number or string, JavaScript attempts to return the default value for the object. Operators attempt to convert the object to a primitive value, a String or Number value, using the valueOf and toString methods of the objects. If this attempt to convert the object fails, a runtime error is generated.[Ref]

var a = 1;  var b = [1];  //What is happening when `(a==b)`  //typeof a;   ==> number  //typeof b;  ==>object  //Object is converted to Primitive using `valueOf` and `toString` methods of the objects  var val = b.valueOf().toString();  console.log('Values after conversion is: ' + val + '  And typeof converted value is:  ' + typeof val);  //typeof val; ==> string  //a == b; will be evaluated as `true` because `'1' == 1` hence..  console.log(a == b); //'1'==1 ==> true

As converted value is of type String, When comparing a number and a string, the string is converted to a number value and then strict comparison is applied.

like image 29
Rayon Avatar answered Oct 13 '22 00:10

Rayon