Javascript - Calling a function name based on a variable - javascript

I am trying to call a function whose name is defined elsewhere is the code.
Below is sample code:
Inner.testFunc = function(node) {
var functionName = node.substring(node, to.indexOf('#'));
// call the function based on functionName
[functionName + '()']
}
function something() {
//doing something
};
...
Assuming that functionName = something, this should try to call the function, but it isn't doing it.
I'm tried using other links such as Call javascript function which name is in variable but it didn't help.
I've also tried using eval():
eval(functionName + '()');
but this returned something about an illegal character...

Your eval call might not be working; use instead:
eval(functionName)(); //note () after the eval statement
In your code ensure first that functionName is something
console.log(functionName === 'something') //true

If your function is defined in the global scope, you could take advantage of the fact that global variables and global functions can be accessed as properties of the global scope:
function something(){ console.log('Works!'); }
window['something'](); // Works!
If it is not, perhaps a reference to it is stored as a property of an object:
var x = { something : function(){ console.log('Also works'); } };
x['something'](); // Also works
Otherwise, it is impossible to access.

functionName is the return of the substring method, not the function itself.

You can create a map of functions with their names as keys as shown below. And then you can pass the output of substring to the map and call the function.
function myName() {
console.log("thefourtheye");
}
var functions = { // map of functions and their names
name: myName
};
functions["name"](); // Instead of "name" pass the result of substring

It's a little more verbose but what about using a case statement to run a function based on the value of node.

Related

How to execute a function which details are passed as parm in another function

I need to execute an external function with params. The external function can be different so I am passing the details of external function with a main function is called. The main function takes object as params. So the information I am sending is transmitting correctly. However, when it's time to execute the external function the object key is trying to execute instead the value, hence I am getting error. What am I missing? Is there a better way to take resolve this issue?
HTML:
<button onclick="fn.funcExt({name: 'foo', param: 'bar+baz'})">Check</button>
JS:
fn = (function(){
var publicAPI = {
funcExt: function(o){return funcExt(o)}
};
////////////////////////////////////
function funcExt(o){
console.log(o.name)
console.log(o.param)
o.name(o.param);
}
return publicAPI;
})();
/////////////////////////////////////////
function foo(s){
alert('passed' + s);
}
Fiddle: http://jsfiddle.net/rexonms/sf8f05fh/
Assuming the external function is global, you'd access it as a property of the window object using square bracket notation so that the property name becomes the result of whatever expression you provide (in this case, the o.name property).
window[o.name](o.param);
If it's in a global "namespace" object, you'd do the same.
SomeNS[o.name](o.param);
Don't put foo in quotes.
<button onclick="fn.funcExt({name: foo, param: 'bar+baz'})">Check</button>
This way, o.name will be the function, not the function name.
If you want to log the name of the function, you can do:
console.log(o.name.name);
DEMO
If you don't want to mess the global context, you could consider bind.
You could modify the accepted answer solution to
this[o.name](o.param);
It will be window object by default, but if you want to be something else, you could alter your publicAPI object to something more meaningful:
var publicAPI = {
funcExt: funcExt.bind(yourContext);
}
So the this above will point to yourContext.

Modify variables inside a function with javascript

I'd like to know if it is posible, having one or more variables to pass them into a function and get those variables modified. I think it is posible with objects, as they behave as references, but I don't know.
With 1 var you could do:
var something = increase(something);
but what if you have, for example, 2 variables with recipies, and would like to exchange them?
exchange_recipies(book1, book2);
You could do this but the variables are parameters inside the function... So is there another way that I'm missing?
EDIT: I know it can be done in many ways but I'll state some here that I don't like due to obvious limitations:
-Use global variables.
-Use objects
-Return an array and reasign.
EDIT2: this Is it possible to change the value of the function parameter? helped me, but I think that answer is uncomplet and there are ways of doing this.
If the variables are declared globally then you wouldn't need to pass them into the function since they can be addressed inside the function.
var something = 1
function bar(){
something = increase(something);
}
For example.
This means you avoid changing the variables into parameters and can then address them from any function (dependant on nesting, ergo, if the variable is declared inside a function it can't be addressed outside of that function but can from a function inside)
function foo(){
var something = 1
function bar(){
//works because it exists in the parent function
something = increase(something)
}
}
function foobar()
//Something doesn't exist here so would return something = undefined
something = increase(something)
}
One way to do this is pass these two parameters as objects:
exchange_recipies({ obj: book1 }, { obj: book2 });
and then inside finction you can operate on obj properties
function exchange_recipies(book1, book2)
{
book1.obj = book2.obj;
...
}
http://codepen.io/anon/pen/eNRZZb

How to call functions by name in javascript where entire code is enclosed within some anonymous function

I want to write function that takes a function name as an argument and calls it. Normally i could do this using window[funcname]. However all my code is enclosed within an anonymous function and hence the namespace of the function is now window. In this case how could i write this function.
You could assign your functions to properties of an object:
var myFuncs = {
func1: function() {
//Do something
},
func2: function() {
//Do something else
}
};
You can then call func1 just like you suggest, but replacing window with myFuncs, like so:
myFuncs["func1"]();
Store your functions in an object as properties and retrieve them by name.

javascript object this

I have an object and it has another inner object. How can I call the parent object from the inner object?
var test = {
init: function () {
var instance = this;
},
call: function() {
this.stop(); // works
},
stop: function() {
this.parseText(); // works
},
parseText: {
load: function ()
{
this.call(); //*** dont work
instance.call(); // work, but what if i have this instance (same name) on another object, would'nt this conflict it?
}
}
};
I'm using an instance, which works fine, but what if I or someone wrote an instance (same name) var in another object, wouldn't it will conflict and overwrite this instance?
Eric's answer gives you a reasonable example of how to do what you want to do, but doesn't really go into why.
In JavaScript, this is set entirely by how a function is called (for now; see below the fold for details), not where the function is defined as it is in some other languages that have the same keyword (Java, C++, C#, ...).
You, the coder, determine what this will be each time you call a function. There are two main ways: By calling the function via an object property (in the same expression), or explicitly using the function's built-in call and apply functions.
Via an object property
Using an object property:
obj.foo(); // or
obj["foo"](); // both work
That does two very distinct things, but which collaborate to set the this value: First, the function reference is found by looking up the foo property of the object obj. Then, the function is called. Because you called it as part of the same overall expression retrieving the property value, the JavaScript engine will set this to obj within the call.
So in your example, test.parseText.load(), within the load call this will be parseText, not test, because that's the object on which load was looked up.
Note that setting-this-via-property-lookup only works when they're done at the same time. This does not work:
var f = obj.foo;
f(); // `this` will not be `obj` within the call
That doesn't work because they weren't done at the same time. The property lookup and function call were separated.
Using call or apply
The second way of setting this is more explicit: All functions have the call and apply properties, which are themselves function references that call the function using information you supply. In both cases, the first argument is the object to use as this during the call. So if we wanted to fix the example above that didn't work, we could do this:
var f = obj.foo;
f.call(obj); // `this` will be `obj` within the call
f.apply(obj); // same
The only difference between call and apply is how you supply function arguments. With call, you supply them as further discrete arguments to the function; with apply, you pass in an array of arguments.
So these all do the same thing:
// 1 - Directly via property
obj.foo("a", "b", "c");
// 2 - Using `call`
f = obj.foo;
f.call(obj, "a", "b", "c");
// 3 - Using `apply`
f = obj.foo;
f.apply(obj, ["a", "b", "c"]); // Note the `[ ... ]`, one array with three elements
You can see how call and apply could work with your existing structure:
test.parseText.load.call(test.parseText);
That calls test.parseText.load, making this = test.parseText within the call.
What Eric did in his answer was to use a closure to make it simpler for you to call parseText with the this value you expect.
Further reading (disclosure: from my blog):
Mythical methods
You must remember this
Closures are not complicated
Up top I said:
In JavaScript, this is set entirely by how a function is called
(for now...
The reason I said "for now" is that in ES6, JavaScript is getting "arrow functions" and unlike other functions, the value of this within an arrow function is set by where they're created, not how they're called: They get this from the context where you create them.
Suppose you were writing code in an object method and wanted to use another method of the object to, I don't know, output information from an array (yes, this is contrived). In ES5, you'd probably do this:
this.output("Entries:");
theArray.forEach(function(entry, index) {
this.output(index + ": " + entry);
}, this);
// ^------- tells `forEach` what to use as `this` during the callback
If you left off the argument, you'd have a bug:
this.output("Entries:");
theArray.forEach(function(entry, index) {
this.output(index + ": " + entry); // <== Bug, `this` is either
// `undefined` (strict) or
// the global object (loose)
});
But since arrow functions inherit this from where they're created rather than getting it based on how they're called, the arrow function version of that doesn't need the second argument:
this.output("Entries:");
theArray.forEach((entry, index) => {
this.output(index + ": " + entry);
});
If all you're worried about is test changing, do it like this:
var test = (function() {
var object = {}
object.call = function() {
this.stop(); // works
};
object.stop = function() {
this.parseText(); // apparently works, even though parseText is not a function
};
object.parseText = {
load: function() {
object.call(); // works
}
};
return object;
})();
If you don't know the name of test, you can use a self-invoking anonymous function to create a wrapper, and refer to the object as shown below.
Note that test is not a reference to a function, but to the return value of the anonymous function. Because the object name (obj) is wrapped inside a function, it cannot be read or modified from outside
The solution below is neat, does not pollute the scope of test, and works like a charm. As mentioned earlier, test refers to the same object as obj. It's however not possible to manipulate variable obj, from outside, so that the code inside the function breaks.
var test = (function(){ //Self-executing function
var obj = {
call: function() {
this.stop(); // works
},
stop: function() {
this.parseText(); // works
},
parseText: {
load: function ()
{
obj.call(); // obj refers to the main object
}
}
};
return obj; //Return the object, which is assigned to `test`.
})(); //Invoke function
Update
It's not possible to reliably refer to self, this, or any reference to the object inside an object, without wrapping it.
Your current solution does not work, see comments in the code below:
var obj = {
init: function(){
var instance = this; //`instance` is declared using `var` inside a function
}, // This variable cannot read from "the outside"
parseText: {
load: function(){
instance.call(); //Does NOT work! instance is not defined
}
}
}
"call" is actually a built-in function on the function object that can be used to call the function specifying what to use for this. How does your code work? It doesn't seem like it should since parseText isn't a function...
Maybe try this:
parseText: function() {
var load = function ()
{
this.call(); //*** should work
};
load.call(this);
}

Different syntax for passing methods as arguments?

I'm currently trying to teach myself more about javascript, and I find myself stumbling over the syntax for passing a method as an argument to another method call. Say you have two functions like these:
function FirstFunction()
{
DoesSomething();
}
function SecondFunction(func)
{
func();
}
In actually passing the FirstFunction to the SecondFunction, I seem to see a wild variety of variations on doing so:
SecondFunction(FirstFunction);
or
SecondFunction("FirstFunction()");
or sometimes, if FirstFunction was defined as follows:
var thisisafunction = function FirstFunction()
{
DoesSomething();
}
SecondFunction(thisisafunction);
I'm guessing there's no "one right way" to do this, so when is it appropriate to use each way of passing a function? Is it better to use one way over another in a certain situation?
Passing a string is always bad. It only works with functions like setTimeout which automatically eval() strings and it's bad since it runs in the global context.
If you just want to pass a plain function without creating a closure or passing arguments, passing the function without () is fine:
myFunc(someCallbackFunc);
If you need to pass arguments or want a closure so you can access some non-global variables inside that function, use an anonymous function:
myFunc(function() {
someCallbackFunc('meow');
});
Of course you can also assign the function to a variable first:
var cb = function() {
someCallbackFunc('meow');
};
myFunc(cb);
While var cb = function someName() {}; is valid, I'd recommend against giving your function expressions names - it's not supported by all browsers. The only advantage is having a function name in debuggers anyway...
First let me clear something. You can define functions both as:
function name() { ... };
or assign it to a variable
var myFunc = function() { ... };
you don't mix both by doing
var myFunc = function name() { ... }; //WRONG
since name won't be binded to anything.
After this, the most usual way of passing functions as arguments, is just to pass the function object without the function call operator "()", which means the function object is not executed.
var func1 = function() { console.log("func1 here") };
var func2 = function(f) { f(); };
func2(func1);
Also, passing the function as String with the function call operator means that the receiving function will have to evaluate that using eval() for the function argument to be executed. It is not recommended.

Categories