<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script data-require="angular.js@1.3.14" data-semver="1.3.14" src="https://code.angularjs.org/1.3.14/angular.js"></script>
<script src="script.js"></script>
</head>
<body>
<div ng-controller="Ctrl">
<div>
<label>A = </label><input type='number' ng-model='a'>
</div>
<div>
<label>B = </label><input type='number' ng-model='b'>
</div>
<div>
<p>(local) A + B = {{ localSum(a, b) }}</p>
</div>
<div>
<p>(global) A + B = {{ globalSum(a, b) }}</p>
</div>
</div>
</body>
</html>
// Some global function from some generic javascript library
function globalSum(a, b) {
console.log('global sum function call, a = ', a, ' b = ', b);
return a + b;
}
function www() {
console.log('www');
return {
someFn: function () {
console.log('hello');
}
}
}
angular
.module('myApp', [])
.controller('Ctrl', function($scope) {
$scope.a = 2;
$scope.b = 3;
$scope.localSum = function(a, b) {
console.log('local sum function call, a = ', a, ' b = ', b);
return a + b;
};
$scope.globalSum = globalSum;
// Call a function by it's name defined in a string.
// The first argument in 'call' must be present though it is not used anywhere
console.log('localSum: ', $scope.$eval('localSum').call([], $scope.a, $scope.b));
console.log('globalSum: ', $scope.$eval('globalSum').call([], $scope.a, $scope.b));
// It is possible to get a function from $eval and then call it as a normal javascript function
var evalLocalSum = $scope.$eval('localSum');
console.log('evalGlobalSum: ', evalLocalSum($scope.a, $scope.b));
var evalGlobalSum = $scope.$eval('globalSum');
console.log('evalGlobalSum: ', evalGlobalSum($scope.a, $scope.b));
var wwwEval = $scope.$eval('www');
console.log(wwwEval);
wwwEval();
});
# Brief
This is an example of using $eval in angularjs to call javascript function when their name is given as a string.
# Use case
Imagine a situation when you need to use some generic javascript library, like three.js inside angularjs. And you want to get data from some server that streams a name of function and set of numeric values, for example you want to stream geometry objects, and then visualize it in browser. So it is possible by using $scope.$eval to make browser receive objects like:
```JSON
{
"function_name": "THREE.Vector3",
"data": [[0, 1, 2], [3, 4, 5]]
}
```
and then convert them to expressions (refer to http://mrdoob.github.io/three.js/docs/#Reference/Core/Geometry):
```javascript
var geometry = new THREE.Geometry();
geometry.vertices.push(
new THREE.Vector3(0, 1, 2);
new THREE.Vector3(4, 5, 6);
);
```
Why I need to pass a function_name is that the array may not necessarily consist of THREE.Vector3 objects, it may be anything else.
# How to do the same in plain javascript
Please note that using eval is not recommended because of safety reasons (refer to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#Don.27t_use_eval.21)
```javascript
// Define some custom function
function sum(a, b) {
console.log('sum function call, a = ', a, ' b = ', b);
return a + b;
}
// Call a function by it's name defined in a string.
// The first argument in 'call' must be present though it is not used anywhere
console.log(eval('sum').call([], 2, 3));
// It is possible to create a function and call it as a normal javascript function
var evalSum = eval('sum');
console.log(evalSum(2, 3));
```