Dynamically execute a function in JavaScript - javascript

I would like to call a function whose name I have in a variable.
For example:
I get the string "pageTracker._trackpageview('/url/page1.page'); " dynamically and assign it to a variable as below
var myFunction = pageTracker._trackpageview('/url/page1.page');";
Now when I submit the page I want to execute the function which is in variable myFunction.
Thank you all.

function functionFromString(funcDef) {
try {
return (new Function("return function() {" + funcDef + "};"))();
} catch (e) {
alert(e);
return (function() {});
}
}
var myFunction = "pageTracker._trackpageview('/url/page1.page');";
var realFunction = functionFromString(myFunction);
realFunction();
Why do it this way?
Just doing eval runs the function right away. If there are errors thrown in the called function itself we can't tell the difference between that and an error in parsing. So by creating a function out of the text, we can separate when we parse it from when we execute it.
Just using newFunction = Function(myFunction) won't compile it, so it's slower. So using new Function() to return a function (that in turn creates a function) is our trick. We could use eval this way, too, but I like new Function better.
What others have said about being really careful with eval (and new Function()) is true. It can be an opening for malicious script.

You can do this with the JavaScript eval() function. Just be careful about controlling the value passed to eval() as it will execute whatever string it is given.
eval("pageTracker._trackpageview('/url/page1.page');");

You are not simply trying to execute a function whose name you have but a complex line of code with a receiver, a method name and a literal string argument. The only way to execute an arbitrary snippet of codes is with eval() But eval() is dangerous. If you're not very careful, someone can pass malignant code to your script that will be executed inside the eval() call.

You can make use of eval in javascript..
var myFunction = "pageTracker._trackpageview('/url/page1.page');";
//...
eval(myFunction);

Solution: Wrap the function
//define:
var myFunction = function (){pageTracker._trackpageview('/url/page1.page');}
//call:
myFunction();
Full Example:
<html>
<head>
<script type="text/javascript">
var foo = function (){alert('bar');}
</script>
</head>
<body onload="foo();"> </body>
</html>

But this way, you cannot check if parameter is correct url, or encode it ect. And I avoid eval as hell for known reasons.
I would prefer the harder, but more safe way - if it is a string, it can be parsed:
//test dub
pageTracker = {
_trackpageview: function(path) {alert(path)}
}
var str = "pageTracker._trackpageview('/url/page1.page')";
//get param
var urlpathregex = /\('([a-z0-9\-._~%!$&'()*+,;=:#\/]+)'\)/;
var param = urlpathregex.exec(str)[1];
//do some stuff/validation with param
[...]
//get object and function name
var funcregex = /([a-zA-Z0-9_]+)?\.?([a-zA-Z0-9_]+)(?=\()/;
var match = funcregex.exec(str);
var obj, func;
obj = match[1];
func = match[2];
//invoke
window[obj][func](param);
This is just an example, and not copy&paste ready code :) Because to begin with - if you get dynamically "pageTracker._trackpageview('/url/page1.page')" as a string, there is some code smell here already.

Related

Executing javascript functions stored as string using AngularJS

Is there any way to inject JavaScript code stored in a string in AngularJS controllers dynamically?
var dynamicJS = "function DoSomething(value){var x = 1+1 return 2;}"
I have to dynamically inject the above function into my AngularJS controller and have it be called on selection change of drop-down, the values of which are bound to the AngularJS controller. The reason is the JavaScript function would vary based on my each row of data which I have based on my configuration at an application level. I am aware we can make use of $eval but would like to get some better approaches, if any exist.
Can anyone give me any idea on this?
Note: I am using AngularJS v1.4.5
I would believe the easier way will be to parse the String and then use the function constructor.
Something like this:
var DoSomething = new Function('value', 'var x = 1+1 return 2');
There are multiple ways to achieve this.
Function object
Create a Function, passing the one argument (i.e. value) and functionBody as parameters:
var dynamicJS = "var x = 1+1; return 2;"
var DoSomething = new Function("value", dynamicJS );
eval()
While arguably more dangerous1, eval() can be used.
var dynamicJS = "function DoSomething(value){var x = 1+1 return 2;}"\
eval(dynamicJS);
Because you mentioned in a comment
"it is intranet application and not going to outer world. no issues on this for this req."
this would likely be fine but please read the section below.
Caution
From the this section of the MDN documentation about eval():
Don't use eval needlessly!
eval() is a dangerous function, which executes the code it's passed with the privileges of the caller. If you run eval() with a string that could be affected by a malicious party, you may end up running malicious code on the user's machine with the permissions of your webpage / extension. More importantly, third party code can see the scope in which eval() was invoked, which can lead to possible attacks in ways to which the similar Function is not susceptible.
eval() is also generally slower than the alternatives, since it has to
invoke the JS interpreter, while many other constructs are optimized by modern JS engines.
There are safer (and faster!) alternatives to eval() for common use-cases.
2
See a demonstration of these techniques utilized below. Click on the buttons corresponding to each technique to see the output on the console.
var dynamicJS = "function DoSomething(value){var x = 1+1; return 2;}"
var functionBody = "var x = 1+1; return 2;";
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('eval').addEventListener('click', function() {
eval(dynamicJS);
console.log('DoSomething(3) -> ',DoSomething(3));
});
document.getElementById('function').addEventListener('click', function() {
var dynamicFunction = new Function("value", functionBody);
console.log('dynamic function(3) ->',dynamicFunction(3));
});
});
<button id="eval">click to eval</button>
<button id="function">click to use Function</button>
1https://stackoverflow.com/a/4599946/1575353
2https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#Don't_use_eval_needlessly!
Perhaps try something like:
function myFunc(obj){
var param = obj.hasOwnProperty('param') ? obj.param : undefined;
console.log(param);
}
var funcString = "myFunc({ param: 'something' });",
Construct = new Function(funcString);
Construct();
Haven't tested it to be honest ... but this way you avoid eval().
more info on Function object

Use of Function class in JavaScript

I have seen usage like var f1=new Function(); but no more than that. Tried to search in Google regarding Function-class but nothing returned what I needed.
What is its significance?
Please suggest me how and when to use it. If possible give me some genuine link to study about it.
Best practice suggest you should never use a base type constructor functions. In a lot of case, use new with a base type will break the usage of typeof.
But, new Function() is valid JavaScript. Just not recommended, and not useful in most cases (var a= function() {} is equivalent).
Not that you can use the Function constructor as an eval call like so new Function('var a = 1; return a + a;'). But this can be dangerous, so use carefully.
There isn't necessarily a beneficial reason to use new Function() since you could simply create a blank function like so:
var f1 = function () {
// my function code here;
};
// calling the function
f1();
Each one will have the prototypes of Function attached to it either way.
new Function() (also new Array(), etc) should typically be avoided since it has to eval.
Technically, there really isn't a difference between these two bits of JavaScript (other answers have covered this):
var f1 = new Function();
and
var f1 = function () { };
What you can do, however, is use Function to check against the types of your variables:
var f1 = 'cat';
console.log(typeof(f1) === typeof(Function)); // false
var f2 = function () { return 'cat'; };
console.log(typeof(f2) === typeof(Function)); // true
Function objects created with the Function constructor are parsed when the function is created. This is less efficient than declaring a function and calling it within your code, because functions declared with the function statement are parsed with the rest of the code.
from MDN

Why we're not use () at window.onload?

At end of this code (full code is here)
function addSongs() {
var song1 = document.getElementById("song1");
var song2 = document.getElementById("song2");
var song3 = document.getElementById("song3");
song1.innerHTML = "Blue Suede Strings, by Elvis Pagely";
song2.innerHTML = "Great Objects on Fire, by Jerry JSON Lewis";
song3.innerHTML = "I Code the Line, by Johnny JavaScript";
}
window.onload = addSongs;
You will see addSongs didn't used with ().
If i change it as
window.onload = addSongs();
It doesn't works. Why?
when you have addSongs(), it's telling Javascript immediately execute that function and assign the return value of that call to the onload handler.
Without the (), it tells the JS engine to assign the function itself to onload.
e.g. if you had something like
function x() {
return 'hello';
}
// immediately assigns "hello" to the onload
window.onload = x();
which is the same as doing
window.onload = 'hello';
and at some point the JS engine will try to execute a function named "hello", whenever the onload handler is triggered.
addSongs is a function, which you can assign to a variable (namely, in this case, window.onload). On the other hand, addSongs() is calling that function, and therefore you're setting window.onload to whatever addSongs() returns. Which is nothing, in this case.
just like we assign int a = 5;
cuz we now know that a is an int and we can assign it a integer value like
similarly window.onload is a function , u can consider it to be of function type datatype
thus we can assign
window.onload=function(){ .. some code ... }
or we can use
function abc(){ ... some code ...}
window.onload=abc;
When you use addSongs() it executes it right away instead of when it is being called.
Because you're setting onload to be equal to the function.
If you call the function, then you're setting onload to be equal to the return value of the function (in this case, undefined).
Also, you have no control over when onload/onready/onclick/etc fire. That's the point.
You're asking the browser to fire the function when one of those things happen -- not before.

cache eval() result

In Javascript, is it possible to cache the results of eval?
For example it would be great if I could:
var str="some code...";
var code = eval(str);
//later on...
code.reExecute();
You can make str the body of a function and use New Function instead of eval.
var fn = new Function([param1, param2,...], str);
And reuse it by calling fn(p1, p2,...)
Or use eval, and make str be something like
var fn = eval("(function(a){alert(a);})")
The result of the 'eval' call is to evaluate the javascript. Javascript (in browsers) does not offer any kind of 'compile' function.
The closest you could get (using eval) is:
var cached_func = eval('function() {' + str + '}');
Then you can call the cached_func later.
Make a function that evaluates and stores the result in a cache object for asynchronous retrieval:
var Cache = { } ;
function evalString(string) {
var evaluated = eval(string) ;
Cache.evalResult = evaluated ;
}
You may then call that code like this:
Cache.evalResult(/* arguments */) ;
On a side note, "eval is evil" as http://www.jslint.com will tell you, since it may open the door for external manipulation of your content. Why do you need to eval that function it in the first place?

What's the difference in closure style

There are two popular closure styles in javascript. The first I call anonymous constructor:
new function() {
var code...
}
and the inline executed function:
(function() {
var code...
})();
are there differences in behaviour between those two? Is one "better" over the other?
Both cases will execute the function, the only real difference is what the return value of the expression may be, and what the value of "this" will be inside the function.
Basically behaviour of
new expression
Is effectively equivalent to
var tempObject = {};
var result = expression.call(tempObject);
if (result is not an object)
result = tempObject;
Although of course tempObject and result are transient values you can never see (they're implementation details in the interpreter), and there is no JS mechanism to do the "is not an object" check.
Broadly speaking the "new function() { .. }" method will be slower due to the need to create the this object for the constructor.
That said this should be not be a real difference as object allocation is not slow, and you shouldn't be using such code in hot code (due to the cost of creating the function object and associated closure).
Edit: one thing i realised that i missed from this is that the tempObject will get expressions prototype, eg. (before the expression.call) tempObject.__proto__ = expression.prototype
#Lance: the first one is also executing. Compare it with a named constructor:
function Blah() {
alert('blah');
}
new Bla();
this is actually also executing code. The same goes for the anonymous constructor...
But that was not the question ;-)
They both create a closure by executing the code block. As a matter of style I much prefer the second for a couple of reasons:
It's not immediately obvious by glancing at the first that the code will actually be executed; the line looks like it is creating a new function, rather than executing it as a constructor, but that's not what's actually happening. Avoid code that doesn't do what it looks like it's doing!
Also the (function(){ ... })(); make nice bookend tokens so that you can immediately see that you're entering and leaving a closure scope. This is good because it alerts the programmer reading it to the scope change, and is especially useful if you're doing some postprocessing of the file, eg for minification.
Well, I made a page like this:
<html>
<body>
<script type="text/javascript">
var a = new function() {
alert("method 1");
return "test";
};
var b = (function() {
alert("method 2");
return "test";
})();
alert(a); //a is a function
alert(b); //b is a string containing "test"
</script>
</body>
</html>
Surprisingly enough (to me anyway) it alerted both "method 1" and method 2". I didn't expect "method 1" to be alerted. The difference was what the values of a and b were. a was the function itself, while b was the string that the function returned.
Yes, there are differences between the two.
Both are anonymous functions and execute in the exact same way. But, the difference between the two is that in the second case scope of the variables is restricted to the anonymous function itself. There is no chance of accidentally adding variables to the global scope.
This implies that by using the second method, you are not cluttering up the global variables scope which is good as these global variable values can interfere with some other global variables that you may use in some other library or are being used in a third party library.
Example:
<html>
<body>
<script type="text/javascript">
new function() {
a = "Hello";
alert(a + " Inside Function");
};
alert(a + " Outside Function");
(function() {
var b = "World";
alert(b + " Inside Function");
})();
alert(b + " Outside Function");
</script>
</body>
</html>
In the above code the output is something like:
Hello Inside Function
Hello Outside Function
World Inside Function
... then, you get an error as 'b' is not defined outside the function!
Thus, I believe that the second method is better... safer!

Categories

Resources