0

I'm building and AngularJS app and would like to do the following thing:

I get JS Code with a web service call:

{ 
 "script":"function foo(a, b) { c = bar(a,b) $scope.c = c } function bar(a,b) { return a+b }"
}

In my AngularJS application I'd like to call foo(a,b) and get the property c in my $scope set to the value computed in the function bar(a,b).

Is this possible? Can the function foo(a,b) access $scope? What if there already exists a function foo() or bar() in my application?

I was already looking at the eval and Function() functionality in JS. But I'm not sure if I can solve my problem like this.

pass function in json and execute

Any help or guidance is greatly appreciated :)

Cheers

Kevin

Community
  • 1
  • 1
user2298830
  • 55
  • 1
  • 2
  • 8

1 Answers1

1

I would look at whether you can structure things differently. It's usually a big red flag if you're passing around code as text like that, and then eval'ing it. Refactor so you're using proper code if at all possible.

With that out of the way:

I was already looking at the eval and Function() functionality in JS. But I'm not sure if I can solve my problem like this.

Yes, it can. eval works within the scope where you call it (it's a bit magical in that way). So if you eval that code within a function, the foo and bar it creates will only be created within that function, for the duration of the call to that function (unless you keep a reference to them somewhere).

E.g.:

function blah($scope) {
    eval(yourString);
}

...will create foo and bar only within that function, and they will have access to the $scope argument.

(See note below after e

Live Example:

var str = "function foo() { $scope.x = a + b; }";
function bar($scope) {
  var a = Math.floor(Math.random() * 10),
      b = Math.floor(Math.random() * 10);
  eval(str);
  foo();
  snippet.log("$scope.x = " + $scope.x);
}
snippet.log("typeof foo === " + typeof foo);
bar({});
snippet.log("typeof foo === " + typeof foo);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Final caveat: Be sure you're only calling eval on code from a trusted source.


It's probably worth noting that this is only true of direct calls to eval. eval is very special; if you call it indirectly, via a variable:

var e = eval;
e(yourString);

...that works differently (specifically, it works at global scope, not in the same scope where you called it). This is why you sometimes see code like (0,eval)(string);: That calls eval indirectly, making it behave globally rather than locally. (Why not just use var globalEval = eval; and then globalEval(string);? Some people are really into their l33t stuff like (0,eval)(...). Me, I prefer maintainability, so if I ever needed a global eval [haven't in years], I would go down the globalEval route...)

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • I agree with TJ here. Somewhere down the line, especially if someone else is editing your code, things like this can throw a major wrench in a project. I would try and figure out a different way. – m.e.conroy Sep 11 '15 at 12:41
  • Thank you very much! Especially for the thorough explanation. I haven't had time to use it in my application but created a few snippets and it worked great! Edit: about the "big red flag": I get this javascript code from a system, which I can't change. But I agree :) – user2298830 Sep 19 '15 at 13:14