Javascript - Variable in function name, possible? - javascript

i hope this question is not too simple, but i have no idea :(
How can i start a function with a var in the function name?
For example ...
my functions
function at_26();
function at_21();
function at_99();
start the function
var test_id = 21;
at_'+test_id+'(); // doesn't work
I hope somebody can help me.
Thanks in advance!
Peter

Store your functions in an object instead of making them top level.
var at = {
at_26: function() { },
at_21: function() { },
at_99: function() { }
};
Then you can access them like any other object:
at['at_' + test_id]();
You could also access them directly from the window object…
window['at_' + test_id]();
… and avoid having to store them in an object, but this means playing in the global scope which should be avoided.

You were close.
var test_id = 21
this['at_'+test_id]()
However, what you may want:
at = []
at[21] = function(){ xxx for 21 xxx }
at[test_id]()

An example to pass an array of params to those composed functions, .
/* Store function names and match params */
let at = {
at_26 : (a,b,c) => at_26(a,b,c),
at_21 : (a,b,c) => at_21(a,b,c),
at_99 : (a,b,c) => at_99(a,b,c),
at_om : (a,b,c,d,e) => at_om(a,b,c,d,e)
}
/* Dynamic function router: name + array of Params */
function dynFunc(name, arrayParams){
return at[name](...arrayParams)
}
/* Usage examples */
dynFunc(`at_${99}`, ["track001", 32, true])
dynFunc("at_" + "om", ["track007", [50, false], 7.123, false, "Bye"])
/* In the scope */
function at_99(a,b,c){
console.log("Hi! " + a,b,c)
console.log(typeof(a), typeof(b), typeof(c))
}
function at_om(a,b,c,d,e){
console.log("Hi! " + a,b,c,d,e)
console.log(typeof(a), typeof(b), typeof(c), typeof(d), typeof(e))
}

You can also try
function at_26(){};
function at_21(){};
function at_99(){};
var test_id = 21;
eval('at_'+test_id+'()');
But use this code if you have very strong reasons for using eval. Using eval in javascript is not a good practice due to its disadvantages such as "using it improperly can open your script to injection attacks."

There is a better way then the window object - which is NOT friendly in firefox - use "self" instead - so in the example posted by Quentin it looks like this:
self['at_' + test_id]();

Related

Function chaining with function names from list [duplicate]

What is the equivalent code of window["functionName"](arguments) in NodeJS server-side?
If you need such a capability within a module, one hack is to store such module functions in variables within the module and then call them by accessing them from the module object properties. Example:
var x = { }; // better would be to have module create an object
x.f1 = function()
{
console.log('Call me as a string!');
}
Now, within the module, you can call it using the value from a string:
var funcstr = "f1";
x[funcstr]();
I am learning the ropes with Node myself, the above is probably all sorts of wrong :-). Perhaps a marginally better way to write this example would be (for the module m.js):
module.exports =
{
f1: function() { console.log("Call me from a string!"); },
f2: function(str1) { this[str1](); }
}
Now you can:
var m = require('m.js');
m.f2('f1');
Or even just:
var m = require('m.js');
m['f1']();
FWIW!
you're looking for global
Note, however, that in modules nothing is ever exposed to this level
1) If methods are in same js file
define all methods as properties of Handler:
var Handler={};
Handler.application_run = function (name) {
console.log(name)
}
Now call it like this
var somefunc = "application_run";
Handler[somefunc]('jerry codes');
Output: jerry codes
2) If you want to keep methods in a different js file
// Handler.js
module.exports={
application_run: function (name) {
console.log(name)
}
}
Use method defined in Handler.js in different.js:
// different.js
var methods = require('./Handler.js') // path to Handler.js
methods['application_run']('jerry codes')
Output: jerry codes
If you want to call a class level function using this then following is the solution and it worked for me
class Hello {
sayHello(name) {
console.log("Hello " + name)
}
callVariableMethod() {
let method_name = 'sayHello'
this[`${method_name}`]("Zeal Nagar!")
}
}
If You need it in module scope, You can use something like this
var module = require('moduleName');
module['functionName'](arguments);
Honestly, looking at all these answers they seem a bit too much work. I was playing around to look for other ways around this. You can use the eval() command to print a variable as text then call it as a function
I.e
let commands = ['add', 'remove', 'test'];
for (i in commands) {
if (commands[i] == command) {
var c = "proxy_"+command;
eval(c)(proxy);
}
}
eval(string)(arg1, arg2);
This example script would execute the function proxy_test(proxy)
You know, the OP's code inspired me to try this:
global.test = function(inVal){
console.log(inVal);
}
global['test']('3 is the value')
But now that I think about it, it's no better than #Ravi' s answer.
I use this for node, see if this approach works for you
var _ = require('lodash');
var fnA1 = require('functions/fnA1');
var fnA2 = require('functions/fnA2');
module.exports = {
run: function(fnName, options, callback) {
'use strict';
var nameSpace = fnName.toString().split('.');
// if function name contains namespace, resolve that first before calling
if (nameSpace.length > 1) {
var resolvedFnName = this;
_.forEach(nameSpace, function(name){
resolvedFnName = resolvedFnName[name];
});
resolvedFnName(options, callback);
} else {
this[fnName](options, callback);
}
},
fnA1: fnA1,
fnA2: fnA2
};
call this like
importVariable.run('fnA1.subfunction', data, function(err, result){
if (err) {return callback(err);}
return callback(null, result);
});
That is not specific to the window object. In JavaScript any property of the object can be accessed this way. For example,
var test = {
prop1 : true
};
console.log(test.prop1); // true
console.log(test["prop1"]); // also true
Read more here : https://developer.mozilla.org/en/JavaScript/Guide/Working_with_Objects

Javascript : can we reuse inner function to acces both global and local

var teamName ="studio";
var otherTeamName ={
teamName :'factory',
getTeamName : function(){
alert(this.teamName);
}
};
window.otherTeamName.getTeamName();// alerts factory
Is there any way to get the studio? by using the same getTeamName function.(i.e i know, removing this will fetch studio.) without removing the this?
Yes, it is possible. There are two ways:
use call: otherTeamName.getTeamName.call(window)
copy reference:
var getTeamName = otherTeamName.getTeamName;
getTeamName(); // alerts studio
call() is not supported by older browsers, the second solution works everywhere.
var teamName = "studio";
var otherTeamName = {
teamName: 'factory',
getTeamName: function() {
alert(this.teamName);
}
};
otherTeamName.getTeamName(); // alerts factory
var getTeamName = otherTeamName.getTeamName;
getTeamName(); // alerts studio
Yes, you can still use the same getTeamName method by changing context function is executed in:
var teamName = "studio";
var otherTeamName = {
teamName: 'factory',
getTeamName: function() {
alert(this.teamName);
}
};
otherTeamName.getTeamName.call(window);
By using Function.prototype.call you make this point to window instead of
otherTeamName object.
UPD. However, this will only work if teamName is global variable. If not, check Quentin's answer.
You can simply use
otherTeamName.getTeamName.call(this)
this here refers to the window
Short answer: No. It isn't a property of the object, so you can't access it as if it was.
Longer answer: You could replace the teamName property with a getter function that returned the value of the variable … but that would be an unintuitive approach to whatever the problem is.
// The good:
otherTeamName.getTeamName.call(this);
otherTeamName.getTeamName.apply(this);
// The okayish:
var f = otherTeamName.getTeamName; f();
otherTeamName.getTeamName.bind(this)();
// The bad:
((f) => f)(otherTeamName.getTeamName)();
(function(f) {f()})(otherTeamName.getTeamName)
// The ugly:
eval(otherTeamName.getTeamName)();
eval("(" + otherTeamName.getTeamName + ")()");
new Function("(" + otherTeamName.getTeamName + ")()")();

Is it possible to provide a custom scope add remove vars to eval function?

I'm trying to use eval() to evalute a mathematical string with variables and functions
ex: algo = "1+len+customfunction(6)"
So i have data for len and the function for customFunction.
They are obviously declared in different scope.
I tried with something like
process = function(vars, algo) {
return (function() {
algo = algo.toLowerCase();
return eval(algo);
}).call(vars);
};
I need to provide required functions and variables to eval. Items are in different scopes, how do i do that ?
Now I'm a bit lost and confused, is this even possible ?
I think using eval('var'+vName+'='+value) would be ok for vars but not suitable for functions.
EDIT: btw eval can be replaced with (new Function(algo))()
http://moduscreate.com/javascript-performance-tips-tricks/
i would move the required data to an object, which hold all required items. access is possible with any given string. this solution does not requires eval()
var data = {
customfunction: function (x) {
return Math.PI * x * x;
},
len: 5
};
var variable = 'len';
if (data[variable]) {
// do something
;
}
var fn = 'customFunction';
function evaluate(vars, algo) {
if (data[algo.toLowerCase()]) { //
return data[algo.toLowerCase()].call(vars);
} else {
// fallback
}
}
var process = evaluate(vars, algo);
OK here is what i've found :
we can't provide a context for eval
eval('1+1') can be replaced by ((new Function('1+1'))() and it's way faster
eval have different scopes, can't use eval('var a = 1'); eval('alert(a)');
So, i'v managed to :
create a string to initiate all vars : vars += 'var '+key+'='+JSON.stringify(value)+';'
replace at runtime my algo string functions with their full path :
var algo = 'f(x)+5*2', x = 5;
window.object.functions.x = function(a) { return a*2; };
So at runtime i replace x( with object.functions.x(
the code executed by eval finally is eval('object.functions.x(5)+5*2'); and output is 20 of course :)
It seems to work.

JavaScript : use a function on the fly from an Object

Well, i understand my question is a little bit strange and the answer seems obvious ("it's impossible !"), but, as JS is a very open language, i go on anyway :)
Let's say, we have the following code :
function dummy() {
}
var obj = new dummy();
var result = obj.aFunction('a','b');
Obviously, the JS interpretor says :
obj.aFunction is not a function
I understand his anger :) but is there a trick to bypass the interpretor (or something like that) or to create on-the-fly the aFunction function into the obj object before the interpretor evaluates all the stuff ?
I've red all about using dynamic function names and so on (using eval() and other tricks) but that don't solve my (weird) problem ...
Thanks in advance.
EDIT : Well, folks, thanks for your answers, but it's not my problematic.
In fact, i used to code in Java with AOP and what i want is :
Create a Valve (or something like this) that catches all the exceptions
Analyse the exception
if the exception corresponds to my 'no function' error, i create from scratch the function and execute it
I garbage this exception
if it's not the good exception i let it to continue its job
Unfortunatly, You cannot do that in JS. Using an ExceptionHandler is not sufficient because its API is too poor ...
But, Thanks to all ...
There are many ways to achieve this. Here is one:
function dummy() {
}
dummy.prototype.aFunction = function (a, b) {
alert(a + ', ' + b);
};
var obj = new dummy();
var result = obj.aFunction('a','b');
Here is a working example. Warning: it will pop up an alert box.
http://jsfiddle.net/X4F67/
Here is another, if you don't know the function name at runtime:
var name = 'aFunction';
function dummy() {
}
dummy.prototype[name] = function (a, b) {
alert(a + ', ' + b);
};
var obj = new dummy();
var result = obj[name]('a','b');
Fiddle: http://jsfiddle.net/X4F67/1/
Note that both of these affect the dummy prototype itself, so all instances of dummy would contain aFunction. If you instead want to work directly on the obj, you could use something like this:
...
var obj = new dummy();
obj[name] = function () { };
You can create a function on the fly, your code just has some issues.
First of all, setting:
var result = obj.aFunction('a','b');
Is making the browser think that obj.aFunction is an existing function that you are calling, you have to set the function.
obj.aFunction = function(a,b)
{
alert(a + ' ' + b);
}.bind(obj);
...then you could state:
var result = obj.aFunction;
If you were to say:
var result = obj.aFunction('a', 'b');
...after declaring obj.aFunction, it would be called at that line and alert right away.
Instead, you can do this:
window['result']('a', 'b');
As for declaring a function on the fly, such as writing out a function as a string and using eval() to evaluate the function and append it to a variable, I'm not sure why it doesnt work. This is what I tried:
obj.aFunction = eval("function(a,b){alert(a + ' ' + b);}.bind(obj)");
And I get:
Uncaught Syntax Error: Unexpected token (
Either way, hope that helps.

Change var in object literal function

Hi guys I am writing some code using the object literal pattern, I have function that returns a value:
'currentLocation': function() {
var cL = 0;
return cL;
},
I then need to update the variable 'cL' from another function like this:
teamStatus.currentLocation() = teamStatus.currentLocation() + teamStatus.scrollDistance();
This part is part of another function - however I get an error back stating: invalid assignment left-hand side
I am guessing I can not update the variable in this way, could anyone suggest a better method or point me in the right direction.
Any help would be greatly appreciated.
Going to add more code to highlight what I am trying to do:
'currentLocation': function() {
var cL = 0;
return cL;
},
'increaseTable': function() {
if (teamStatus.currentLocation() <= teamStatus.teamStatusTableHeight() ) {
teamStatus.currentLocation = teamStatus.currentLocation() + teamStatus.scrollDistance();
$("#tableTrackActual").animate({scrollTop: (teamStatus.currentLocation)});
$("#tableMembers").animate({scrollTop: (teamStatus.currentLocation) });
//console.log(teamStatus.currentLocation());
teamStatus.buttonRevealer();
}
}
As you can see increaseTable should update the value of currentLocation - help this sheds more light on what I am trying to achieve.
You're writing teamStatus.currentLocation() =, which calls the function teamStatus.currentLocation and tries to assign to the return value. That isn't valid. You want just teamStatus.currentLocation = — no function call.
The variable inside your function is completely private to that function (and any functions defined within it). If you need to create a number of functions that share a set of private variables, you can do that with a closure. For instance:
var Thing = (function() {
var thingWideData;
function getData() {
return thingWideData;
}
function setData(newData) {
thingWideData = newData;
}
return {
getData: getData,
setData: setData
};
})();
What that does is create a Thing object which has getData and setData functions available for it, which get and set the completely private thingWideData variable contained by the anonymous closure. More about this pattern here and here, although the latter of those is more about private methods than private data.
What your code produces is:
0 = 0 + <some number>
Which variable do you want to update? cL? You are declaring it in the function, you cannot assign a value to it from outside. Depending on the rest of your code, you might be better off with getters and setters:
var object = {
_cL = 0,
get currentLocation() {
return this._cL;
},
set currentLocation(value) {
this._cL = value;
}
}
then you can do:
teamStatus.currentLocation = teamStatus.currentLocation + teamStatus.scrollDistance();
Update:
Regarding IE: If currentLocation should actually be just a number, it might be sufficient to just declare it as property:
var obj = {
currentLocation: 0
}

Categories