Expressions (Expressions) are Javascript-like code snippets, usually placed in the binding area (such as {{expression}}). Expressions are parsed and executed through the $parse service (/1.0.2/docs/api/ng.$parse).
For example, the following are valid expressions in angular:
- 1+2
- 3*10 | currency
1. Angular expression vs. Js expression
This is easy for people to associate an angular view expression as a javascript expression, but this is not entirely correct, because angular does not evaluate an expression through javascript's eval(). You can think of an angular expression as a javascript expression with the following differences:
- Property evaluation: All properties are evaluated for scope, while JavaScript is for window objects.
- Forgiving: Expression evaluation, angular is tolerant for undefined and null, but Javascript will generate NullPointerExceptions (-_-!!!!!! Why haven't I seen it before).
- No process control statement: In an angular expression, we cannot do any of the following: conditional branching, looping, throwing exceptions.
- Filters: We can pass the result of the expression into the filter chains. For example, convert a date object to a locally specified human-readable format.
On the other hand, if we want to execute arbitrary Javascript code (in an angular expression), we can write that code into one of the Controller's methods and call it. If we want to eval() an angular expression in javascript, we can use the $eval() method.
<!DOCTYPE HTML> <html lang="zh-cn" ng-app="ExpressionTest"> <head> <meta charset="UTF-8"> <title>expression-e1</title> <style type="text/css"> .ng-cloak { display: none; } </style> </head> <body ng-controller="MyCtrl"> 1 + 2 = {{1+2}} <br/> Expression: <input type="text" ng-model="expr"/> <button ng-click="addExp(expr)">Evaluate</button> <ul> <li ng-repeat="expr in exprs"> [<a ng-click="removeExp($index)" href="">X</a>] <tt>{{expr}}</tt>=><span ng-bind="$parent.$eval(expr)"></span> </li> </ul> <script src="../angular-1.0." type="text/javascript"></script> <script type="text/javascript"> var app = ("ExpressionTest", []); ("MyCtrl", function ($scope) { var exprs = $ = []; $ = "3*10|currency"; $ = function(expr) { (expr); }; $ = function (index) { (index, 1); }; }); </script> </body> </html>
2. Property Evaluation
The context of the angular expression parsing environment is scope, while JavaScript is window (it should refer to the strict mode evel), and angular needs to access the global window object through $window. For example, if we need to call alert() defined on a window object in an expression, we need to use $(). This is intended to avoid accidentally accessing the global state (a common source of subtle bugs).
<!DOCTYPE HTML> <html lang="zh-cn" ng-app="PropertyEvaluation"> <head> <meta charset="UTF-8"> <title>PropertyEvaluation</title> <style type="text/css"> .ng-cloak { display: none; } </style> </head> <body> <div ng-controller="MyCtrl"> Name: <input ng-model="name" type="text"/> <button ng-click="greet()">Greet</button> </div> <script src="../angular-1.0." type="text/javascript"></script> <script type="text/javascript"> var app = ("PropertyEvaluation", []); ("MyCtrl", function ($scope,$window) { $ = "Kitty"; $ = function() { $("Hello " + $); }; }); </script> </body> </html>
3. Forgiving (tolerance, fault tolerance?)
Expression evaluation is forgiving undefined and null. In javascript, when a is not an object, an exception will be thrown for evaluation. Sometimes this is reasonable for common languages, and expression evaluation is mainly used for data binding, and the general form is as follows:
{{}}
If a does not exist, no display seems to be more reasonable than throwing an exception (unless we wait for the server to respond, which will be defined in a short while). If the expression is not tolerant enough when evaluating, then we write the binding code so confusingly:
{{((a||{}).b||{}).c}} //This...
Similarly, when referring to a function(), if it is undefined or null, then simply return undefined.
4. No Control Flow Statements
We cannot write process control statements in expressions. The reason behind this is that the core system of angular is that the logic of application should be in the controller (scope), not in the view. If we need to add conditional branches, loops or throw exceptions into the view expression, we can delegate the javascript method instead (you can call the method in scope).
5. Filters
When we present data to users, we may need to convert the data from the original format to a friendly (highly readable) format. For example, we have a data object that needs to be formatted based on the region before being displayed to the user. We can pass expressions to a series of filters, such as:
name | uppercase
This expression evaluator can simply pass the value of name into the uppercase filter.
Chain filters use this syntax:
value | filter1 | filter2
We can also transfer parameters divided by colons into filters, for example, displaying 123 in two decimals:
123 | number:2
6. Prefix "$"
We may find it strange, what is the meaning of the prefix "$"? It is a simple prefix (preventing conflicts) used by angular to differentiate its API name from other APIs. If angular does not use $, then evaluation of() will return undefined. Because neither a nor angular defines this property.
Considering that future versions of angular may choose to increase length, this will change the behavior of this expression. What's worse is that we developers might create a length property that will then conflict with angular. This problem exists because angular extends the currently existing object by adding methods. By adding the prefix "$", angular retains a specific namespace, so angular developers and developers using angular can live in harmony.