It uses the Abstract Equality Comparison Algorithm.
Specifically for your example
If Type(x) is Number and Type(y) is String,
  return the result of the comparison x == ToNumber(y).
So then you'll end up with:
0 == 0
...in both cases because an empty string converts to the number 0, and a numeric string converts to the number given.
From 9.3.1 ToNumber Applied to the String Type:
A StringNumericLiteral that is empty or contains only white space is converted to +0
Since we're now doing a comparison of the same Type on the second pass, it will do the following:
If Type(x) is the same as Type(y), then
...
  If Type(x) is Number, then
...
  If x is the same Number value as y, return true.
To test a toNumber conversion, you can use the unary + operator.
console.log( +'' );   // 0
console.log( +'0' );  // 0