This question already has answers here:
How to execute a JavaScript function when I have its name as a string
(36 answers)
Closed 8 years ago.
I have a JavaScript variable which contains the name of a JavaScript function. This function exists on the page by having been loaded in and placed using $.ajax, etc.
Can anyone tell me how I would call the javascript function named in the variable, please?
The name of the function is in a variable because the URL used to load the page fragment (which gets inserted into the current page) contains the name of the function to call.
I am open to other suggestions on how to implement this solution.
I'd avoid eval.
To solve this problem, you should know these things about JavaScript.
Functions are first-class objects, so they can be properties of an object (in which case they are called methods) or even elements of arrays.
If you aren't choosing the object a function belongs to, it belongs to the global scope. In the browser, that means you're hanging it on the object named "window," which is where globals live.
Arrays and objects are intimately related. (Rumor is they might even be the result of incest!) You can often substitute using a dot . rather than square brackets [], or vice versa.
Your problem is a result of considering the dot manner of reference rather than the square bracket manner.
So, why not something like,
window["functionName"]();
That's assuming your function lives in the global space. If you've namespaced, then:
myNameSpace["functionName"]();
Avoid eval, and avoid passing a string in to setTimeout and setInterval. I write a lot of JS, and I NEVER need eval. "Needing" eval comes from not knowing the language deeply enough. You need to learn about scoping, context, and syntax. If you're ever stuck with an eval, just ask--you'll learn quickly.
If it´s in the global scope it´s better to use:
function foo()
{
alert('foo');
}
var a = 'foo';
window[a]();
than eval(). Because eval() is evaaaaaal.
Exactly like Nosredna said 40 seconds before me that is >.<
Definitely avoid using eval to do something like this, or you will open yourself to XSS (Cross-Site Scripting) vulnerabilities.
For example, if you were to use the eval solutions proposed here, a nefarious user could send a link to their victim that looked like this:
http://yoursite.com/foo.html?func=function(){alert('Im%20In%20Teh%20Codez');}
And their javascript, not yours, would get executed. This code could do something far worse than just pop up an alert of course; it could steal cookies, send requests to your application, etc.
So, make sure you never eval untrusted code that comes in from user input (and anything on the query string id considered user input). You could take user input as a key that will point to your function, but make sure that you don't execute anything if the string given doesn't match a key in your object. For example:
// set up the possible functions:
var myFuncs = {
func1: function () { alert('Function 1'); },
func2: function () { alert('Function 2'); },
func3: function () { alert('Function 3'); },
func4: function () { alert('Function 4'); },
func5: function () { alert('Function 5'); }
};
// execute the one specified in the 'funcToRun' variable:
myFuncs[funcToRun]();
This will fail if the funcToRun variable doesn't point to anything in the myFuncs object, but it won't execute any code.
This is kinda ugly, but its the first thing that popped in my head. This also should allow you to pass in arguments:
eval('var myfunc = ' + variable); myfunc(args, ...);
If you don't need to pass in arguments this might be simpler.
eval(variable + '();');
Standard dry-code warning applies.
Related
Recently I was debugging a bit of code that one of my coworkers wrote and found something along the lines of this within a conditional, inside of a larger function.
(function(foo){
...
console.log(foo);
...
})();
So it looks like this very boiled down
function display(db, user, foo) {
if (isValid(db, user) {
(function(foo){
console.log(foo);
})();
}
...
}
Originally it didn't have (); at the end so to my understanding it wasn't even being called but to my broader question, what's the difference between that and something like below? I've seen this syntax a few times but I don't understand how above would be useful for this purpose. My understanding would reason that this just adds unnecessary complexity. Someone please enlighten me!
function display(db, user, foo) {
if (isValid(db, user) {
// without abstract function
console.log(foo);
}
...
}
Thanks :-)
With such a simple example, there is no reason to use an anonymous function like this in node.js or any other JavaScript environment when the inner function could be called directly instead.
When conducting reviews, I often will assume that any console.log (or choose-your-language logging) is accidental. If the surrounding source doesn't do anything of value itself, it is likely only intended to support a (possibly-out-of-date) console.log during development and debugging.
Because JavaScript is single-threaded, constructing an anonymous function of this sort is strictly for scoping. In the case of the original source that didn't have the execution (i.e. it was missing the ()), this is actually a way to "hide" debug code from the runtime while leaving it in-place if a step-through debug ever needed it.
When debugging, it's as easy as adding the ('isValid succeeded') to have it execute all the source inside.
(function(foo){
console.log(foo);
})( /* You're missing a parameter value here; will print 'undefined'. */ );
Sometimes you use an anonymous function to limit the scope of your code. It may come handy if you do not want to pollute the global scope with your variables. Also, it makes dependency injection for testing easier.
Consider the following examples:
var a = 2, b = 3;
function print(x)
{
console.log('x= ', x);
}
print(a+b);
In the above example, the a, b, and print now belongs to the window object. When your code grows it becomes difficult to keep track and avoid of name collisions. The problem becomes even more severe if you are using 3rd party libs etc.
In the example below, your code is wrapped in an anonymous function protecting the global scope. You can also pass parameters to the anonymous function
(function(localParam){
var a = 2, b = 3;
function print(x)
{
console.log('x= ', x);
}
print(a+b);
//also
console.log(localParam); // = safe way to access and global variables
})(globalParam);
This code always works, even in different browsers:
function fooCheck() {
alert(internalFoo()); // We are using internalFoo() here...
return internalFoo(); // And here, even though it has not been defined...
function internalFoo() { return true; } //...until here!
}
fooCheck();
I could not find a single reference to why it should work, though.
I first saw this in John Resig's presentation note, but it was only mentioned. There's no explanation there or anywhere for that matter.
Could someone please enlighten me?
The function declaration is magic and causes its identifier to be bound before anything in its code-block* is executed.
This differs from an assignment with a function expression, which is evaluated in normal top-down order.
If you changed the example to say:
var internalFoo = function() { return true; };
it would stop working.
The function declaration is syntactically quite separate from the function expression, even though they look almost identical and can be ambiguous in some cases.
This is documented in the ECMAScript standard, section 10.1.3. Unfortunately ECMA-262 is not a very readable document even by standards-standards!
*: the containing function, block, module or script.
It is called HOISTING - Invoking (calling) a function before it has been defined.
Two different types of function that I want to write about are:
Expression Functions & Declaration Functions
Expression Functions:
Function expressions can be stored in a variable so they do not need function names. They will also be named as an anonymous function (a function without a name).
To invoke (call) these functions they always need a variable name. This kind of function won't work if it is called before it has been defined which means Hoisting is not happening here. We must always define the expression function first and then invoke it.
let lastName = function (family) {
console.log("My last name is " + family);
};
let x = lastName("Lopez");
This is how you can write it in ECMAScript 6:
lastName = (family) => console.log("My last name is " + family);
x = lastName("Lopez");
Declaration Functions:
Functions declared with the following syntax are not executed immediately. They are "saved for later use" and will be executed later, when they are invoked (called upon). This type of function works if you call it BEFORE or AFTER where is has been defined. If you call a declaration function before it has been defined Hoisting works properly.
function Name(name) {
console.log("My cat's name is " + name);
}
Name("Chloe");
Hoisting example:
Name("Chloe");
function Name(name) {
console.log("My cat's name is " + name);
}
The browser reads your HTML from beginning to end and can execute it as it is read and parsed into executable chunks (variable declarations, function definitions, etc.) But at any point can only use what's been defined in the script before that point.
This is different from other programming contexts that process (compile) all your source code, perhaps link it together with any libraries you need to resolve references, and construct an executable module, at which point execution begins.
Your code can refer to named objects (variables, other functions, etc.) that are defined further along, but you can't execute referring code until all the pieces are available.
As you become familiar with JavaScript, you will become intimately aware of your need to write things in the proper sequence.
Revision: To confirm the accepted answer (above), use Firebug to step though the script section of a web page. You'll see it skip from function to function, visiting only the first line, before it actually executes any code.
Some languages have the requirement that identifiers have to be defined before use. A reason for this is that the compiler uses a single pass on the sourcecode.
But if there are multiple passes (or some checks are postponed) you can perfectly live without that requirement.
In this case, the code is probably first read (and interpreted) and then the links are set.
I have only used JavaScript a little. I am not sure if this will help, but it looks very similar to what you are talking about and may give some insight:
http://www.dustindiaz.com/javascript-function-declaration-ambiguity/
The body of the function "internalFoo" needs to go somewhere at parsing time, so when the code is read (a.k.a parsing) by the JS interpreter, the data structure for the function is created and the name is assigned.
Only later, then the code is run, JavaScript actually tries to find out if "internalFoo" exists and what it is and whether it can be called, etc.
For the same reason the following will always put foo in the global namespace:
if (test condition) {
var foo;
}
I recently joined a large software developing project which uses mainly JavaScript and a particular question has been on my mind since day one. I know this issue has been here on SO before, but I have never seen the core question being properly answered. So here I ask it again:
Are there any benefits in JavaScript in using function expressions rather than function declarations?
In other words, is this:
var myFunction = function () {
// Nice code.
}
in any way better than this:
function myFunction () {
// Nice code.
}
As I see it, function expressions only introduce negative aspects on several levels to the code base. Here I list a few.
Function expression as the one above, suddenly forces you to be careful with forward references, as the anonymous function object that the myFunction variable refers to, does not exist until the variable expression actually executes. This is never a problem if you use function declarations.
Apart from generating twice as many objects as in the case with function declarations, this usage introduces a very bad programming habit, which is that developers tend to declare their functions only when they feel they need them. The result is code that mixes object declarations, function expressions and logic in something that obscures the core logic of a piece of code.
As a side effect of 2), code becomes much harder to read. If you would use proper function declarations and only var declarations for objects that actually will be variable in the code, it becomes far easier to scan the indentation line of code segment and quickly find the objects and the functions. When everything is declared as "var", you are suddenly forced to read much more carefully to find this piece of information.
As yet another nasty side effect of 2), as users get into the bad habit of only declaring their functions when they feel they need them, function expressions start showing up inside event handlers and loops, effectively creating a new copy of the function object either each time an event handler is called or for each turn in the loop. Needless to say, this is bad! Here is an example to show what I mean:
var myList = ['A', 'B', 'C'];
myList.forEach(function (element) {
// This is the problem I see.
var myInnerFunction = function () {
// Code that does something with element.
};
};
So to sum up, at least in my view, the only situation in which it is fair to use something like:
var myFunction = function () {
// Nice code.
}
is when your logic intends to change the myFunction reference to point at different functions during execution. In that situation myFunction (the variable) is something that is variable in the code, hence you are properly informing a different programmer of your intents, rather than confusing him/her.
With this background in mind, I ask my question again. Have I missed something central about function expressions (in the context described above) in which they provide any benefit over function declarations?
This question already has answers here:
What is the purpose of a self executing function in javascript?
(21 answers)
Closed 8 years ago.
So far I've learned the benefits of using this function (is it wrapping?)
So, it almost acts like namespaces.
Suppose we have:
( function() {
function foo(){
alert(true);
}
foo(); //alerts true
})();
( function() {
function foo(){ //the same title of the function as above
alert("another call of foo");
}
foo(); //alerts, ok.
})();
Also I've noticed it can access public vars, like this:
var __foo__ = 'bar';
( function() {
alert(__foo__); //alerts bar
})();
I have several questions regarding this approach
What I've tried:
Use Bing for tutorials (I' found them, but many of them don't answer my questions)
Play with passing objects into the body
Find the answer here
But, I'm still beating my head against the wall
So the questions are:
I've seen people pass objects as params, but when DOES it make sense?
For example, what does it mean?
( function(window) {
})(document);
I saw smth like this in Jquery UI Lib
( function($) {
//some code of widget goes here
})(Jquery);
This makes inner code visible outside the function, right? (not sure) Why, this is because
we can access the object (say we have "modal" widget), simply by calling it,
like:
$(function(){
$("#some_div").modal(); //here it's object the we got from the function
});
And the second question is: How does it work.
I've seen people pass objects as params, but when DOES it make sense? For example, what does it mean?
( function(window) {
})(document);
The language does not treat parameters to immediately called functions differently than parameters to other functions.
It makes sense to use a parameter whenever you want a local name in your function body for an input. In this case it's a bit confusing since window and document are likely to be confused.
( function($) {
//some code of widget goes here
})(Jquery);
This makes inner code visible outside the function, right? (not sure) Why, this is because we can access the object (say we have "modal" widget), simply by calling it,
No. It does not by itself make any code visible outside the widget. It's just a parameter definition which provides a new&local name for a global variable.
What makes inner code visible outside is attaching it to an external object as in
$.exportedProperty = localVariable;
which is a common convention in jQuery code.
There are mainly 2 purposes of passing in the window and document objects such as seen below
(function(window, document){
// code
}(window, document);
Javascript can access local variables faster than global variables. This pattern in effect makes the names window and document local variables rather than global, thus making your script slightly faster.
Making these names local variables has another benefit: minifiers can rename them. So if you minify the above script, the local version of window might get renamed to a and document might get renamed to b, thus making the minified script smaller. If you were to reference them as globals, these renamings are impossible because that would break your script.
For more info, checkout these awesome videos
http://paulirish.com/2010/10-things-i-learned-from-the-jquery-source/
http://paulirish.com/2011/11-more-things-i-learned-from-the-jquery-source/
on your first question, I dont think you seen window and document but something more like:
(function(doc) {
var fubar = doc.getElementById("fubar"); // === document.getElementById("fubar")
})(document);
you have a self-invoking function (or closure) with arguments like any function:
var b = function(str) { alert(str); }
b('hi there') //alert('hi there');
the same thing is it with the code above, but we are just calling the method at once we created it.
the other code you have:
( function($) {
//some code of widget goes here
})(Jquery);
is to reserve the $variable inside the metod to refer to the jQuery object, this is very handy if you have more frameworks or replaced the $ object with something else, everything inside that method with an $ will refer to the jQuery object and nothing else(if you don´t replace it inside your code).
the code:
$(function(){
$("#some_div").modal(); //here it's object the we got from the function
});
is calling jQuery and its a shortcut for $(document).ready
it will call the method:
function(){
$("#some_div").modal(); //here it's object the we got from the function
}
as soon as the DOM is ready
The pattern is called a closure. It makes sense to use when a module or function:
wants to avoid polluting globally-scoped variables
wants to avoid use globally-scoped variables and avoid other code polluting them
For an example of each, first take this pattern:
(function(window) {
// ...
})(window);
Everything inside the closure will be able to use window as if it were a local variable.
Next, take the same pattern using the JQuery symbol:
(function($) {
// ...
})($);
If you have some code that relies on a symbol/namespace like $, but another module reassigns that, it can screw up your code. Using this pattern avoids this by allowing you to inject the symbol into a closure.
Whenever you pass an argument to that wrapping function it's so that you won't mess up with any other libraries or global variables that may be present in your application.
For example as you may know jQuery uses $ as a symbol for calling itself, and you may also have another library, that will also use $ for calling itselt, under this condition you may have trouble referencing your libraries. so you would solve it like this:
(function($){
// here you're accessing jQuery's functions
$('#anything').css('color','red');
})(jQuery);
(function($){
// and in here you would be accessing the other library
$.('#anything').method();
})(otherLibrary);
This is specially useful when you're making jQuery or any other kind of library plugins.
What it does is allow you to use the $ variable inside your function in place of the jQuery variable, even if the $ variable is defined as something else outside your function.
As an example, if you're using both jQuery and Prototype, you can use jQuery.noConflict() to ensure that Prototype's $ is still accessible in the global namespace, but inside your own function you can use $ to refer to jQuery.
I am a newbie to java script and currently reading John Resig's Pro javascript techniques . While explaining closure he refers to calls like setTimeout("otherFunction()",2000) as instances where new JS developers have problems . I could not understand why this is a problem ? Can some one explain please ?In this http://www.w3schools.com/js/js_timing.asp I am seeing a call like var t=setTimeout("alertMsg()",3000); which looks similar to me .
It's not "wrong", it's just not necessarily "right", and it's certainly not recommended.
The setTimeout() function's first parameter can be a string or a function reference / function expression.
If you pass a string it will be slower because effectively you are doing an eval() which is not recommended. More important than speed though is that the scope in which the code in the string executes may not be what you are expecting (and may not be the same in different browsers).
By passing a function reference / function expression instead these problems can be avoided.
The "right" syntax for your example is:
setTimeout(otherFunction, 2000);
Note there are no parentheses after otherFunction - if there were it would call otherFunction() immediately and pass the return value from that function to setTimeout().
If you need to pass parameters to your function you can wrap it in an anonymous function:
setTimeout(function() {
otherFunction(param1, param2);
}, 2000);
That may seem kind of clunky compared to setTimeout("otherFunction(param1,param2)", 2000) but again it avoids issues with scope of where otherFunction, param1 and param2 are defined.
The recommended approach is to use the following:
setTimeout(otherFunction, 2000);
or a closure:
setTimeout(function() {
otherFunction();
}, 2000);
Do not use the overload which takes a string as first parameter because the javascript interpreter will need to parse this string into javascript code.
And yeah, the site you have linked to http://www.w3schools.com is probably one of the worst sites out there to learn programming. It shows exactly what you shouldn't do.
Because it has to eval otherFunction() (and hence spawn a new instance of the interpreter) every time. If you provide a reference to the function, setTimeout can execute it without the necessity to spawn a new interpreter.
So use:
setTimeout(otherFunction,2000);
Anything enclosed with "" is a string so a JavaScript interpreter will generally need to parse the string.
Parsing the string is unnecessary even if it works.
If we simply use
setTimeout(alertMsg,3000);,
the interpreter is not required to do any additional (unnecessary) work, resulting in better code.
Instead of setTimeout("otherFunction()",2000), pass the function directly by doing
setTimeout(otherFunction,2000) is much better. The previous way has to do eval the string "otherFunction()".