I'm watching an Angular JS tutorial that keeps using variations of this code snippet without explaining it.
(function(param, undefined){
//Normal function definition in here
...
}(bar.foo = bar.foo || {}));
So I get most if this. I recognize the following a self-executing function used to encapsulate bits of javascript to avoid scope pollution.
(function(param, undefined){
//Normal function definition in here
...
});
But I don't understand the syntax of having parentheses after a function definition.
Edit
I understand what is going on inside the parentheses.
What I don't understand is the syntax of having parentheses after a function definition: function(...){...}(...);
It is a self-executing function that expects parameters. bar.foo is the parameter that is sent to it (will be param in use of the function).
If bar.foo does not have a value prior to the execution of the function, it is set to {}, otherwise, it is set to itself, and then it is passed in.
(function(param1, param2, param3) {
var ele = document.getElementById("result");
ele.innerHTML += "param1: " + param1;
ele.innerHTML += "<br />";
ele.innerHTML += "param2: " + param2;
ele.innerHTML += "<br />";
ele.innerHTML += "param3: " + param3;
ele.innerHTML += "<br />";
param3 = param3 || "bananas";
ele.innerHTML += "param3 after change: " + param3;
})("apples", "oranges");
<div id="result"></div>
The function is being triggered with (bar.foo = bar.foo || {}) as the argument. If bar.foo exists, then the function will take bar.foo as the argument. If it is undefined (which is falsey), then it will take in {} as the argument. I hope this helps!
Placing parentheses after the function declaration initiates a call to it immediately. It's the same as doing this:
var fn = function () { ... };
fn();
Because the return value of a function declaration is the function object, and when you apply parentheses to a function object, you call it. And, as always, the stuff inside those parentheses are the parameters to the function.
If bar.foo is defined, use that -- but if it isnt, use this empty object ({})
Edit - to fit new clarification
Its placement means that before executing the function, it will handle the bar.foo assignment; like setting a default.
Related
The code goes like this (The syntax may seem odd but as far as I know, there is nothing wrong with it. Or is there?)
var add=function addNums(a, b) {
return a+b;
}
alert("add: "+ add(2,3)); // produces 5
alert("addNums: "+addNums(2,3)); // should also produce 5
addNums() is declared as a function. So, when I pass the parameters to it, it should also return the result.
Then, why am I not getting the second alert box?
You are seeing a named function expression (NFE).
An anonymous function expression is where you assign a function without a name to a variable1:
var add = function () {
console.log("I have no own name.");
}
A named function expression is where you assign a named function to a variable (surprise!):
var add = function addNums() {
console.log("My name is addNums, but only I will know.");
}
The function's name is only available within the function itself. This enables you to use recursion without necessarily knowing the "outside name" of the function - even without having to set one in the first place (think callback functions).
The name you choose shadows an existing name, so if another addNums is defined elsewhere it will not be overridden. This means you can use any name you like without fear for scoping problems or breaking anything.
In the past you would have used arguments.callee to refer to a function inside itself without knowing its name. But support for that is being removed from JavaScript2, so NFEs are the correct way to do this nowadays.
Here is a lot of stuff to read on the topic: http://kangax.github.io/nfe/
1 Assigning it to a variable is not necessary, it just serves as an example to distinguish it from a plain function declaration. It could be any other context where JS expects an expression (a function argument, for example).
2 You will receive an error if you have strict mode in effect and try to use arguments.callee.
The problem
You are using a named function expression - and a function expression's name is not available outside of that function's scope:
// Function statement
function statement() {
console.log("statement is a type of " + typeof statement);
}
statement();
console.log("statement is a type of " + typeof statement);
results in:
statement is a type of function
statement is a type of function
whereas:
// Function expression with a name
var expression = function namedExpression() {
console.log("namedExpression is a type of " + typeof namedExpression);
};
expression();
// namedExpression(); // uncommenting this will cause an exception
console.log("expression is a type of " + typeof expression);
console.log("namedExpression is a type of " + typeof namedExpression);
will produce:
namedExpression is a type of function
expression is a type of function
namedExpression is a type of undefined
The solution
Depending on what you are trying to do, you want do do one of the following:
Change your function declaration to use a statement and then alias your function:
function addNums(a, b) {
return a + b;
}
var add = addNums;
Alias both names to your expression:
var add = addNums = function addNums(a, b) {
return a + b;
};
Why does JavaScript do things this way?
Named function expressions are useful because they let you reference a function inside itself and they give you a name to look at in a debugger. However, when you use a function as a value you don't generally want parts of it leaking into the enclosing scope. Consider:
(function setup() {
var config = retrieveInPageConfig();
if (config.someSetting) {
performSomeOtherSetup();
}
kickOffApplication();
})();
This is a perfectly licit use of a function expression - in such a case you would not expect the name setup to leak into the enclosing scope. Assigning a named function expression to a variable is just a special case of this, that just happens to look like a function statement declaration.
addNums is only available in the scope of the newly-defined function.
Quite obviously, when a function expression has a name (technically —
Identifier), it is called a named function expression. What you’ve
seen in the very first example — var bar = function foo(){}; — was
exactly that — a named function expression with foo being a function
name. An important detail to remember is that this name is only
available in the scope of a newly-defined function; specs mandate that
an identifier should not be available to an enclosing scope.
Read more detail form this article.
You should either declare as named function:
function addNums(){
}
or assign function to the variable:
var add= function(){// your code }
The reason why addNum() doesn't return anything is because it's not added to the global scope with the way you declare it.
Demo
function addNums(a, b) {
return a+b;
}
var add = addNums;
alert("add: "+ add(2,3));
alert("addNums: "+addNums(2,3));
I have added your code in my test web app and works fine for me. Here is the code. Would you please share the more details of your code/app?
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="JavascriptTest.aspx.cs" Inherits="GetGridViewColumnValue.JavascriptTest" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type="text/javascript">
var add = function addNums(a, b) {
return a + b;
}
alert("add: " + add(2, 3)); // produces 5
alert("addNums: " + addNums(2, 3));
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
</div>
</form>
</body>
</html>
Cheers!!!
Consider the following code:
var f = function g() {
// function
};
The g will be access only in the function itself, and its needed when you want to use the function
by itself, for writing recursive functions. For example, you want the factorial function:
var f = function factorial(x) {
if (x <= 1) return 1;
// here we want to use the function itself
return x * factorial(x - 1);
};
console.log(f(5));
However, its really needed as you can access the function itself by arguments.callee:
// note that the function has not any name
var f = function (x) {
if (x <= 1) return 1;
// here we want to use the function itself
return x * arguments.callee(x - 1);
};
console.log(f(5));
I've slightly modified your code:
var add = function addNums(a, b){
return a+b;
}
console.log(add);
console.log(typeof(add));
console.log("add: "+ add(2,3)); // produces 5
console.log("addNums: "+addNums(2,3));
And then proceeded to run it inside of node.js to get this output:
[Function: addNums]
function
add: 5
/home/mel/l.js:44
console.log("addNums: "+addNums(2,3));
^
ReferenceError: addNums is not defined (... backtrace)
Normally, a variable assigned an inline anonymous method would print out [Function] when called with console.log(var); Here console.log(add); results in the name of the function also being printed.
So it's not like your addNums declaration is invalid or not used, it's simply scoped to be bound to the variable add.
addNums is not a function in the global namespace..
It's an function defined only within the assignment operator..
if you want to have access to it try the follow:
function addNums(a, b)
{
return a+b;
}
var add = addNums;
var add = function <---- the function name is add and it's value is a function..
Let's say I declare a function and use it as a handler for an event on an object.
Let's say that it needs to access a variable who's value will change before the event is called.
How do I provide to the function the value of the variable the moment the function is declared?
For example:
var I_Like_to_Change_Frequently = "...";
some_DOM_object.addEventListener( "some_arbitrary_event_to_fire_later", function I_Need_the_Current_Value(){
alert( "at the time I was defined, 'I_Like_to_Change_Frequently' was " + I_Like_to_Change_Frequently)
})
var I_Like_to_Change_Frequently = undefined //doesn't really matter. The point is it changes
EDIT: This codeblock is repeated multiple times in a for loop where some_DOM_object is different each iteration. Every iteration I_Like_to_Change_Frequently changes as well.
A couple options:
1) Move your code into a function. The function parameter will be a new binding, and thus will be "locked in" to that value
function createListener(domObject, val) {
domObject.addEventListener("some_arbitrary_event_to_fire_later", function () {
alert("at the time i was defined, I_Like_to_Change_Frequently was " + val;
});
}
var I_Like_to_Change_Frequently = "...";
createListener(some_DOM_object, I_Like_to_Change_Frequently);
var I_Like_to_Change_Frequently = undefined
2) Do it inline with an IIFE
var I_Like_to_Change_Frequently = "...";
(function (val) {
some_DOM_object.addEventListener( "some_arbitrary_event_to_fire_later",
function (){
alert( "at the time I was defined, 'I_Like_to_Change_Frequently' was " + val)
})
})(I_Like_to_Change_Frequently);
var I_Like_to_Change_Frequently = undefined
Using Function.prototype.bind():
You can also make use of the javascript bind() function to define the scope of the function.
This way, the variable value at the time of creation of the function can be retained.
some_DOM_object.addEventListener( "some_arbitrary_event_to_fire_later", (function I_Need_the_Current_Value(){
alert( "at the time I was defined, 'I_Like_to_Change_Frequently' was " + this.variableAtTheTimeOfCreation)
}).bind({variableAtTheTimeOfCreation: I_Like_to_Change_Frequently}));
Breakdown:
In this example, we bind the function to a scope object {variableAtTheTimeOfCreation: I_Like_to_Change_Frequently}.
When the handler executes, it's this will be the scope object we defined and bound to it (which was at creation).
More on Function.prototype.bind() on MDN
Working through Javascript Koans, I'm getting hung up on the following code:
it("should use lexical scoping to synthesise functions", function () {
function makeMysteryFunction(makerValue)
{
var newFunction = function doMysteriousThing(param)
{
return makerValue + param;
};
return newFunction;
}
var mysteryFunction3 = makeMysteryFunction(3);
var mysteryFunction5 = makeMysteryFunction(5);
expect(mysteryFunction3(10) + mysteryFunction5(5)).toBe(FILL_ME_IN);
});
It gets 23, and that's fine. The thing I'm puzzled by is how/why the parameter given to the 'mysteryFunction3' variable gets passed to the doMysteriousThing function as 'param'.
Is it just a fact of life that if there's an inner and an outer function which each take one parameter, defining a variable equal to the outer function given a specified parameter like:
var mysteryFunction3 = makeMysterFunction(3);
will make it so that sending a parameter to the variable instance of the outer function, like:
mysteryFunction3(10)
will cause that parameter (10) to be read as the parameter for the inner function?
I struggled through understanding this as well at first. This is how I reached clarity with it blow for blow. This is my first post on stack and excuse my being long-winded about it.
Let's take a very basic function that returns a string:
function fun() {
return 'Hi!';
}
If we log the above function without the invocation parentheses, the console just logs a reference to the function:
console.log(fun); //logs ---> [Function: fun]
If we log it again, but WITH the invocation parenthesis:
console.log(fun()); //logs ---> Hi!
the invocation of a function is equal to its return value:
console.log(fun() === 'Hi!'); //logs ---> true
So building off of that, let's rewrite our function to have another function declared within it that returns a string. The outer function will return the invocation of the inner function:
function funAgain() {
function innerFun() {
return 'Hello there!';
}
return innerFun();
}
So within the scope of funAgain (innerFun() === 'Hello there!') evaluates to true so when we log an invocation of funAgain to the console:
console.log(funAgain()); //logs ---> 'Hello there!'
But what if we left off the invoking parentheses of innerFun in the return statement of the outer function?
function funAgain() {
function innerFun() {
return 'Hello there!';
}
return innerFun;
}
console.log(funAgain()); //logs [Function: innerFun]
The function ITSELF is returned. Though it's not actually the whole story, we could think of (funAgain() === innerFun) Obviously, you can't actually run this comparison in practice because of scoping issues (innerFun can't exist outside of an invocation of funAgain).
BUT! Let's for a moment think of it that way. That means that if we capture the return value of funAgain in a variable:
var innerFunCaptured = funAgain();
console.log(innerFunCaptured); // logs [Function: innerFun]
We have, again conceptually, (innerFunCaptured === innerFun) ...
So now that our variable is bound to the inner function, we can invoke that inner function by adding parentheses to the variable.
console.log(innerFunCaptured()); //logs ---> 'Hello there!'
When I was talking about the "whole story" above, what I left out was that the inner function's binding to the variable is the result of the outer function's invocation, so really the binding not only includes innerFun itself, but ALSO the environment which it was created within including any potential arguments passed through the invocation of the outer function, which allows us to...
Rewrite the outer and inner function once more so that they now have parameters which interact:
function funOnceMore(greetingPartOne) {
function innerFun(greetingPartTwo) {
return greetingPartOne + ' ' + greetingPartTwo;
}
return innerFun;
}
What if we log funOnceMore with an argument.
console.log(funOnceMore('Hello')) //logs ---> [Function: innerFun]
Again, innerFun itself is returned. But what about the argument greetingPartOne we passed? Well, it was passed alright, but since innerFun was never invoked within funOnceMore, greetingPartOne was never used in any meaningful way. We have to figure out how to invoke innerFun! The answer: we need to bind it to a variable like we did in the previous step.
var innerFunCapturedAgain = funOnceMore('Hello')
Now innerFunCapturedAgain holds innerFun AND the environment of funOnceMore with the argument 'Hello' that we passed into it.
So now we can invoke innerFun by putting parentheses on innerFunCapturedAgain, and those parentheses will encapsulate the argument for greetingPartTwo that we pass to innerFun.
console.log(innerFunCapturedAgain('there!')) //logs ---> 'Hello there!'
Both the answers are very helpful, but struggling through this myself, I think the best answer is to just walk through what's happening and change it just enough to shed a new light on it:
makeMysteryFunction makes a function which adds its argument (makerValue) to the argument that's being passed to the function that it returns (mysteryFunctionX).
So, what helped me understand this is converting the numbers to strings:
function makeGreeting(greeting)
{
var newFunction = function greet(name)
{
return greeting + ' ' + name;
};
return newFunction;
}
var makeGreetingHi = makeGreeting('Hi');
var makeGreetingHello = makeGreeting('Hello');
//finally call functions
makeGreetingHi('Stranger');
//Hi Stranger
makeGreetingHello('Friend');
//Hello Friend
All I did was change the name of the functions, and concatenate strings instead of adding numbers. What makes the koan confusing is the function names: guess thats a good example of bad practices. The point of the exercise is simply that in the example I provided the greet function has access to greeting. Unfortunately thats lost in the nomenclature
Something that I just found extemely usefull in understanding what exactly is going on here is adding a console.log to show the contents of "mysteryFunction3". So:
var mysteryFunction3 = makeMysteryFunction(3);
var mysteryFunction5 = makeMysteryFunction(5);
console.log(mysteryFunction3);
expect(mysteryFunction3(10) + mysteryFunction5(5)).toBe(FILL_ME_IN);
The console output was this:
doMysteriousThing(param)
{
return makerValue + param;
}
Coming from a C# background, this is crazy. But at least I understand it now!
I'm a total Javascript newb, and I'm trying to wrap my head around OLN. What I'm encountering is that, when calling an object method from another method on the same object, the value of local value of 'this' in the called method is changing. Here's my code:
var generator = {
generateForLevelSkillAndCount : function(level, skill, count) {
var functionCall = this['generate_' + level + '_' + skill];
return functionCall(count);
},
generate_0_4 : function(count) {
return this.generate_generic_dots(count, 3);
},
generate_generic_dots : function(count, maxDots) {
/* do cool stuff and return it */
}
};
So, I call generator.generateForLevelSkillAndCount(0, 4, 20) and it works properly, calling generate_0_4(count). However, this is where it fails, with Chrome's Javascript console telling me "Uncaught TypeError: Object [object DOMWindow] has no method 'generate_generic_dots'."
I know enough to know that the problem is that the value of this in generate_0_4 is a DOMWindow object, rather than generator (which is what this is pointing to in generateForSkillLevelAndCount but I can't figure out why that would possibly be happening.
Update: I updated the example code per CMS's suggestion to get rid of eval, but the same error is being returned, so it's not just an eval bug.
In JavaScript, the context object (this) is set to the "global object" (window, in browsers) unless the method is accessed as an object property. Therefore:
var foo = { bar: function() { alert(this.baz); }, baz: 5 };
var bar = foo.bar;
var baz = 3;
foo.bar(); // alerts 5, from foo
foo["bar"](); // alerts 5, from foo
bar(); // alerts 3, from the global object
Note that all three function calls are to the exact same function!
So, in your code, you're assigning the desired method to functionCall and calling it directly, which causes the function to use window as its context object. There are two ways around this: access the method as an object property or use .call() or .apply():
function generateForLevelSkillAndCount1(level, skill, count) {
return this['generate_' + level + '_' + skill](count);
}
function generateForLevelSkillAndCount2(level, skill, count) {
var functionCall = this['generate_' + level + '_' + skill];
return functionCall.call(this, count);
}
First of all, I would encourage you to avoid eval where you don't need it, for example, in your fist function:
//...
generateForLevelSkillAndCount : function(level, skill, count) {
var functionCall = this['generate_' + level + '_' + skill];
return functionCall(count);
},
//...
You can use the bracket notation property accessor instead eval, it's unnecessary in this case.
Now, I guess you are trying your code on the Chrome's Console, and eval is failing because the console has a bug, when eval is invoked from a FunctionExpression (such as generateForLevelSkillAndCount), the evaluated code uses the Global context for its Variable Environment and Lexical Environment.
See this answer for more information on this bug.
Edit: After re-reading your code, the problem happens because you lose the base object reference when you assign the function to your functionCall variable, you can either:
Invoke the function directly, without using that variable:
//...
generateForLevelSkillAndCount : function(level, skill, count) {
this['generate_' + level + '_' + skill](count);
},
//...
Or still use your variable, but persist the this value:
//...
generateForLevelSkillAndCount : function(level, skill, count) {
var functionCall = this['generate_' + level + '_' + skill];
return functionCall.call(this, count);
},
//...
More info on this...
You can control the execution context of the method call by using call():
var generator = {
generateForLevelSkillAndCount : function(level, skill, count) {
return this['generate_' + level + '_' + skill].call(this, count);
},
generate_0_4 : function(count) {
return this.generate_generic_dots.call(this, count, 3);
},
generate_generic_dots : function(count, maxDots) {
/* do cool stuff and return it */
}
};
I'm as baffled as you are, but have you considered checking out what happens if you call generate_0_4 explicitly, instead of parsing it through eval()?
When you call generate_0_4 dynamically (using an implicit to_string()) it is returned to generateForLevelSkillAndCount as an ad-hoc function. Because it's in Window scope rather than Object scope, it can't reference this, and the internal call fails because this doesn't exist in that context.
Here's how to see what's happening:
generate_0_4 : function(count) {
throw(this);
return this.generate_generic_dots(count, 3);
},
With generator.generateForLevelSkillAndCount(0, 4, 1); you get [object Window] or [object DOMWindow].
With generator.generate_0_4(1); you get what you're expecting (and what works): [object Object] or #<an Object>.
This is a feature of Javascript: the value of this will depend on the object from which the function was called, not where it was defined. (Which makes sense when functions are first-class objects themselves.) this in most other contexts refers to the window object.
There are two common workarounds, using a wrapper function:
function bind(func, obj) {
return function() {
func.apply(obj, arguments);
}
}
or using a closure:
var self = this;
function generate_blah() {
// use self instead of this here
}
In your case, though, simply replacing
var functionCall = this['generate_' + level + '_' + skill];
return functionCall(count);
with
this['generate_' + level + '_' + skill](count);
would do the trick.
This question already has answers here:
How to execute a JavaScript function when I have its name as a string
(36 answers)
Closed 9 years ago.
I got a string like:
settings.functionName + '(' + t.parentNode.id + ')';
that I want to translate into a function call like so:
clickedOnItem(IdofParent);
This of course will have to be done in JavaScript. When I do an alert on settings.functionName + '(' + t.parentNode.id + ')'; it seems to get everything correct. I just need to call the function that it would translate into.
Legend:
settings.functionName = clickedOnItem
t.parentNode.id = IdofParent
Seeing as I hate eval, and I am not alone:
var fn = window[settings.functionName];
if(typeof fn === 'function') {
fn(t.parentNode.id);
}
Edit: In reply to #Mahan's comment:
In this particular case, settings.functionName would be "clickedOnItem". This would, at runtime translate var fn = window[settings.functionName]; into var fn = window["clickedOnItem"], which would obtain a reference to function clickedOnItem (nodeId) {}. Once we have a reference to a function inside a variable, we can call this function by "calling the variable", i.e. fn(t.parentNode.id), which equals clickedOnItem(t.parentNode.id), which was what the OP wanted.
More full example:
/* Somewhere: */
window.settings = {
/* [..] Other settings */
functionName: 'clickedOnItem'
/* , [..] More settings */
};
/* Later */
function clickedOnItem (nodeId) {
/* Some cool event handling code here */
}
/* Even later */
var fn = window[settings.functionName];
/* note that settings.functionName could also be written
as window.settings.functionName. In this case, we use the fact that window
is the implied scope of global variables. */
if(typeof fn === 'function') {
fn(t.parentNode.id);
}
window[settings.functionName](t.parentNode.id);
No need for an eval()
Here is a more generic way to do the same, while supporting scopes :
// Get function from string, with or without scopes (by Nicolas Gauthier)
window.getFunctionFromString = function(string)
{
var scope = window;
var scopeSplit = string.split('.');
for (i = 0; i < scopeSplit.length - 1; i++)
{
scope = scope[scopeSplit[i]];
if (scope == undefined) return;
}
return scope[scopeSplit[scopeSplit.length - 1]];
}
Hope it can help some people out.
JavaScript has an eval function that evaluates a string and executes it as code:
eval(settings.functionName + '(' + t.parentNode.id + ')');
eval() is the function you need to do that, but I'd advise trying one of these things to minimize the use of eval. Hopefully one of them will make sense to you.
Store the function
Store the function as a function, not as a string, and use it as a function later. Where you actually store the function is up to you.
var funcForLater = clickedOnItem;
// later is now
funcForLater(t.parentNode.id);
or
someObject.funcForLater = clickedOnItem;
// later is now
(someObject.funcForLater)(t.parentNode.id);
Store function name
Even if you have to store the function name as a string, you can minimize complexity by doing
(eval(settings.functionName))(t.parentNode.id);
which minimizes the amount of Javascript you have to construct and eval.
Dictionary of handlers
Put all of the action functions you might need into an object, and call them dictionary-style using the string.
// global
itemActions = { click: clickedOnItem, rightClick: rightClickedOnItem /* etc */ };
// Later...
var actionName = "click"; // Or wherever you got the action name
var actionToDo = itemActions[actionName];
actionToDo(t.parentNode.id);
(Minor note: If instead here you used syntax itemActions[actionName](t.parentNode.id); then the function would be called as a method of itemActions.)
While I like the first answer and I hate eval, I'd like to add that there's another way (similar to eval) so if you can go around it and not use it, you better do. But in some cases you may want to call some javascript code before or after some ajax call and if you have this code in a custom attribute instead of ajax you could use this:
var executeBefore = $(el).attr("data-execute-before-ajax");
if (executeBefore != "") {
var fn = new Function(executeBefore);
fn();
}
Or eventually store this in a function cache if you may need to call it multiple times.
Again - don't use eval or this method if you have another way to do that.
I wanted to be able to take a function name as a string, call it, AND pass an argument to the function. I couldn't get the selected answer for this question to do that, but this answer explained it exactly, and here is a short demo.
function test_function(argument) {
alert('This function ' + argument);
}
functionName = 'test_function';
window[functionName]('works!');
This also works with multiple arguments.
If settings.functionName is already a function, you could do this:
settings.functionName(t.parentNode.id);
Otherwise this should also work if settings.functionName is just the name of the function:
if (typeof window[settings.functionName] == "function") {
window[settings.functionName](t.parentNode.id);
}
This took me a while to figure out, as the conventional window['someFunctionName']() did not work for me at first. The names of my functions were being pulled as an AJAX response from a database. Also, for whatever reason, my functions were declared outside of the scope of the window, so in order to fix this I had to rewrite the functions I was calling from
function someFunctionName() {}
to
window.someFunctionName = function() {}
and from there I could call window['someFunctionName']() with ease. I hope this helps someone!
I prefer to use something like this:
window.callbackClass['newFunctionName'] = function(data) { console.log(data) };
...
window.callbackClass['newFunctionName'](data);
Based on Nicolas Gauthier answer:
var strng = 'someobj.someCallback';
var data = 'someData';
var func = window;
var funcSplit = strng.split('.');
for(i = 0;i < funcSplit.length;i++){
//We maybe can check typeof and break the bucle if typeof != function
func = func[funcSplit[i]];
}
func(data);
In javascript that uses the CommonJS spec, like node.js for instance you can do what I show below. Which is pretty handy for accessing a variable by a string even if its not defined on the window object. If there is a class named MyClass, defined within a CommonJS module named MyClass.js
// MyClass.js
var MyClass = function() {
// I do stuff in here. Probably return an object
return {
foo: "bar"
}
}
module.exports = MyClass;
You can then do this nice bit o witchcraft from another file called MyOtherFile.js
// MyOtherFile.js
var myString = "MyClass";
var MyClass = require('./' + myString);
var obj = new MyClass();
console.log(obj.foo); // returns "bar"
One more reason why CommonJS is such a pleasure.
eval("javascript code");
it is extensively used when dealing with JSON.