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

JavascriptAngularjs

Javascript Problem Overview


I'm working on an AngularJS project. I noticed that the following expression returns a number.

In the view, {{undefined + 10}} will output 10.

In JavaScript, undefined + 10 will output NaN.

Why is this behavior different in a view?

Javascript Solutions


Solution 1 - Javascript

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

Solution 2 - Javascript

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionZoolyView Question on Stackoverflow
Solution 1 - JavascriptMihai Alexandru-IonutView Answer on Stackoverflow
Solution 2 - JavascriptscipperView Answer on Stackoverflow