Why does {{undefined + number}} return number?

That's the advantage of interpolation.

Interpolation markup with embedded expressions is used by AngularJS to provide data-binding to text nodes and attribute values.

If the interpolated value is not a String, it is computed as follows:

  • undefined and null are converted to '' (empty string)
  • if the value is an object that is not a Number, Date or Array, $interpolate looks for a custom toString() function on the object, and uses that.
  • if the above doesn't apply, JSON.stringify is used.

During runtime the compiler uses the $interpolate service to see if text nodes and element attributes contain interpolation markup with embedded expressions.

Also, the angular compiler use an interpolateDirective and registers watchers in order to listen for model changes. That's the process of digest cycle.

Read more here to understand how interpolation works.

Why {{'' == +Infinity}} returns true ?

In AngularJS, $interpolate service evaluates +Infinity to 0 value.

angular.module('app', [])

.controller('Controller', ['$injector', function($injector) {

}]);
setTimeout(function() {
  angular.bootstrap(document.getElementById('body'), ['app']);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
<div id="body">
  <div ng-controller="Controller">
    {{+Infinity}}
  </div>
</div>

Now the expression remain {{0==''}}.

Why 0=='' is evaluated to true ?

The left side is of type Number. The right side is of type String.

In this case, the right operand is coerced to the type Number:

0 == Number('') => 0 == 0,

which is evaluated to true boolean value.

Here is applied The Abstract Equality Comparison Algorithm.

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


To explain by referencing AngularJS code, this is the magic:

function plusFn(l, r) {
  if (typeof l === 'undefined') return r;
  if (typeof r === 'undefined') return l;
  return l + r;
}

If you have a "plus" expression, this function is parsed into your template.

The expression replacement is invoked by the Parser.parse (angular.js:16155) or parse.js:1646 (https://github.com/angular/angular.js/blob/87a586eb9a23cfd0d0bb681cc778b4b8e5c8451d/src/ng/parse.js#L1646).