calling a jQuery function named in a variable - javascript

I have several jQuery function like
function setOne();
setTwo(); setThree();
and a variable var number that values respectively "one", "two", "three".
How can I call function "setOne()" when number values "one", function "setTwo" when number values "two" and so on...?
Thank you so much in advance. Any help will be apreciated.

If you have your function in the global scope (on the window object) you can do:
// calls function setOne, setTwo, ... depending on number.
window["set" + number]();
And using eval will allow you to run functions in local scope:
eval("set" + number + "()");
When is JavaScript's eval() not evil?

Create a name -> function map:
var funcs = {
'one': setOne,
'two': setTwo
/*...*/
};
Then you call the function with:
funcs[number]();

If the variable details the actual name of the JQuery function and you want to apply the function to a DOM element like 'body', you can do the following:
$('body')['function-name']('params');

Provided your functions are in the global scope, try:
function setOne() {
console.log('setOne called');
}
function setTwo() {
console.log('setTwo called');
}
function setThree() {
console.log('setThree called');
}
var number, funcName;
number = 'one';
funcName = 'set' + number.charAt(0).toUpperCase() + number.slice(1);
window[funcName](); // output: setOne called
number = 'two';
funcName = 'set' + number.charAt(0).toUpperCase() + number.slice(1);
window[funcName](); // output: setTwo called
number = 'three';
funcName = 'set' + number.charAt(0).toUpperCase() + number.slice(1);
window[funcName](); // output: setThree called

As simple as this is:
function hello(){
alert("hello");
}
var str = "hello";
eval(str+"()");

Why do you have three functions for that?
var number;
function setNumber(n) {
number = n;
}
setNumber(1) will set number to 1
setNumber(2) will set number to 2
ect

Further to #Andreas answer, the following illustrates the approach when not using a global.
Make a variable that holds a set of functions:
var callbacks = {
setOne: function(params) {
// ...
},
setTwo: function(params) {
// ...
},
};
Then if you have a variable holding the function name, you can do:
var number = "Two";
callbacks["set" + number](params);

Related

Javascript rename function (not variable name)

I am trying to change the name of the function that is given by .toString(), or create a new function with a new name but the same body.
function func() {}
func.toString() // returns 'function func() {}'
changename(func, "newname") // this is the functionality that I am trying to achieve
func.toString() // should now return 'function newname() {}'
I have tried using Object.defineProperty() which sucessfully updates the value returned by func.name but not func.toString().
Object.defineProperty(func, "name", {
value: "newname",
writable: true,
});
func.name // returns 'newname'
func.toString() // still returns 'function func() {}'
Edit: Reason for wanting to do this
I need take take an arbitrary function with an unknown name and write it to a file with a known name, for example (using nodejs):
const fs = require("fs");
changename(func, "newname");
fs.writeFileSync("tmp.js", func.toString());
tmp.js then contains:
function newname() {}
If all you need to do is write the code of the function to a file, just regex replace the name with whatever you want:
let func = // whatever;
let funcCode = func.toString();
funcCode = funcCode.replace(/^function [^(]*(.*)$/, "function newName$1");
Now funcCode has the text you can dump out to a file.
Changing the reported "name" property of an actual function object is another story entirely, and is either impossible or impractical at best. If you're just working with the text of the function, it's easy.
If you are okay with extending toString function, this should work:
function func() {}
func.toString() // returns 'function func() {}'
changeName=function(funcToExtend, name){
funcToExtend.toString = () => name;
}
changeName(func,"new name");
func.toString(); // new name
One way to do this is to change how the toString function works. I don't think this is a good solution but I came up with this:
function test(){
console.log('hello');
}
test.newName = 'helloFunc';
test.toString = function(){
var str = Function.prototype.toString.call(this);
return 'function ' + this.newName + str.substring(str.indexOf('('), str.length);
}
console.log(test.toString());
I believe that a much nicer solution could implement the Function constructor.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function
If you want just a new String with the new name, you can do this way:
function func() {}
console.log(func.toString())
Object.prototype.changeName = function (newName) {
return "function " + newName + "(){}";
}
let newNameFunction = func.changeName("newName")
console.log(newNameFunction);
But this way, you don't have the body of the function.

Overriding a javascript function definition

I am trying to monkeypatch a 3rd party javascript library but the original function definition I am overloading keeps getting called.
var ns = {};
ns.topFxn = function(){
var _me = "me";
function _toOverride(){
console.log("This is the original: " + _me);
}
function pubFxn(){
_toOverride();
}
console.log("Original");
ns.pubFxn = pubFxn;
};
//attempt to monkey patch
var oldTopFxn = ns.topFxn;
ns.topFxn = function(){
oldTopFxn();
function _toOverride(){
console.log("This is the overriden: " + _me);
}
console.log("MonkeyPatch");
};
ns.topFxn();
ns.pubFxn();
OUTPUT:
scratch.js:15> Original
scratch.js:26> MonkeyPatch
scratch.js:10> This is the original: me
I think this is because this function is indirectly called by another function, and that function might hold a closure on the function it is pointing to - so maybe this isn't possible? Any suggestions on how to override?
jsfiddle
You can't override a local function in another function, because of variable scope. The name _toOverride is local to each function, and assigning it in your function has no effect on the function with the same name in a different function.
You would have to override ns.pubFxn.
var oldTopFxn = ns.topFxn;
ns.topFxn = function(){
oldTopFxn();
var oldPubFxn = ns.pubFxn;
function _toOverride(){
console.log("This is the overriden: " + _me);
}
ns.pubFxn = function() {
oldPubFxn();
_toOverride();
}
console.log("MonkeyPatch");
};

Modifying object properties with a method

so I'm trying to write a simple game to work with objects and get used to manipulating and working with them. What I want to do is set base stats (user/programmer defined) and then use those base stats in a method to create a complex stat. sample code for what I'm trying to do:
var main = function() {
function Boss (name, lvl, str, dex, int) {
this.bName = name
this.level = lvl
this.strength = str
this.dexterity = dex
this.intelligence = int
this.pAttack = pAttack();
}
function pAttack() {
(2*this.level) + (2*this.strength);
}
var a1Boss = new Boss("test", 50, 500, 500, 500)
console.log(a1Boss.pAttack)
}
This returns undefined to the console, although everything else returns correctly. Should the pAttack function be set up as
var pAttack = function() {code}
Any help would be appreciated
If you want your method to be attached to the new object do this :
this.pAttack = pAttack;
// and the function should be initialized as a variable
var pAttack = function(){...};
If you want your method to be attached to the prototype :
Boss.prototype.pAttack = pAttack;
Lots of syntax errors.
function Boss (name, lvl, str, dex, int) {
this.bName = name;
this.level = lvl;
this.strength = str;
this.dexterity = dex;
this.intelligence = int;
this.pAttack = this.pAttack();
}
Boss.prototype = {
pAttack: function () {
return (2*this.level) + (2*this.strength);
},
pDefend: function () {
//Defend stuff
},
levelUp: function () {
this.level = this.level + 1;
}
};
var a1Boss = new Boss("test", 50, 500, 500, 500);
console.log(a1Boss.pAttack)
https://jsfiddle.net/sLhrek8h/1/
You've actually executed the method pAttack instead of assigning it. Since pAttack returns nothing, undefined is returned as an alternative.
So just don't execute it,
this.pAttack = pAttack;
or return something
function pAttack() {
return (2*this.level) + (2*this.strength);
}
Your function needs to return a value. I would create it as a method of the object, however, and call it as such:
var main = function() {
function Boss(name, lvl, str, dex, int) {
this.bName = name;
this.level = lvl;
this.strength = str;
this.dexterity = dex;
this.intelligence = int;
this.pAttack = function() {
return (2 * this.level) + (2 * this.strength);
}
}
var a1Boss = new Boss("test", 50, 500, 500, 500);
console.log(a1Boss.pAttack());
};
main(); // outputs '1100' to the console
Another solution that may help out depending on what you're doing in the long run is passing in arguments into your function, and returning that value.
function pAttack(level, strength) {
return (2*level) + (2*strength);
}
and calling it with
this.pAttack = pAttack(this.level, this.strength);
Currently pAttack is not invoked in the context of a Boss instance so this is not pointing at what you expect, you have 3 options
In all cases, don't forget to return from the pAttack function!
Option 1, Have instances inherit pAttack
After defining pAttack, add the following
Boss.prototype.pAttackFn = pAttack;
What does this do?
It makes all instances of Boss, i.e. Objects constructed by new Boss, inherit the function pAttack as the property pAttackFn so you can call it e.g.
this.pAttack = this.pAttackFn();
Option 2, Define the context of invocation using .call or .apply
this.pAttack = pAttack.call(this);
Option 3, Give pAttack parameters instead of relying on this
function pAttack(lvl, str) {
return (2 * lvl) + (2 * str);
}
Then
this.pAttack = pAttack(this.level, this.strength);

Create a JavaScript function dynamically from a string name

Given a string classname, I want to dynamically create a new JavaScript function named after that string that can be used to instantiate objects.
I've tried using eval() but for some reason the declared function does not appear in the global (window) scope.
eval( "function " + classname + "() {}" );
window[ classname ]; // => undefined
Is there a way I can dynamically create a new function named after a string?
Or, alternatively, give me some way to reference the created function after creating it via eval. Interestingly it appears as a local variable when I debug it in Safari.
Update:
Got it! Of course it's obvious, I just use eval again to create the instance:
var myInstance = eval( "new " + classname );
myInstance.constructor.name; // => classname (yay)
This should work in my case because I only need to create one instance of the class right after it's declared. For the general case though see Pointy's answer.
Yes:
window[classname] = function() { ... };
Now, in honesty, that's not exactly like what you were attempting, but it's pretty close. When you instantiate a function via a function expression like that, and without a name, the function can't refer to itself except via the name in the outer scope (in this case, the global scope).
If that's important, what you could do is this: create the function with some stock "internal" name, and then assign it to the global name:
function secretName() { ... }
window[classname] = secretName;
function registerFunction(functionBody) {
"use strict";
var script = document.createElement("script");
script.innerHTML = "function " + functionBody;
document.body.appendChild(script);
}
registerFunction("fooBar(x, y) { return x + y; }");
fooBar(1, 2); // will give you 3
Although this is essentially the same as eval() but it will register the function in the domain of the current page. You can later remove this script element, or reuse it for other functions.
Try this:
var classname = "myFunction";
window[ classname ] = function () {};
alert( window[ classname ] ); // => undefined
In case you don't want to create new functions based on some string, but based on another similar function: (this might not be a good example but hope you can get the idea)
function createListOfFunctions(functionNameList) {
resultFunctions = {};
// Loop all names to create a list of functions with those names
$.each(functionNameList, function(index, functionName) {
resultFunctions[functionName] = _createFunction(functionName);
});
return resultFunctions;
}
function _createFunction(name) {
return function(anotherNameToCompare) {
// customize this funciton whatever you like
return name == anotherNameToCompare;
};
}
// USAGE:
functionNameList = ['stack', 'overflow'];
result = createListOfFunctions(functionNameList); // result = { stack: function(name) {...}, overflow: function(name) {...} }
result.stack('stack'); // true
result.stack('not stack'); // false
result.overflow('overflow'); // true

JavaScript: Get Argument Value and NAME of Passed Variable [duplicate]

This question already has answers here:
Determine original name of variable after its passed to a function
(9 answers)
Closed 8 years ago.
What I want to do is get the NAME of a variable passed to a function and the VALUE of that variable, and only have to pass in one variable to the function. So:
var x = "anything";
function showName() {
}
showName(x);
or
showName("x");
Which will return: "x = anything".
Right now, I have to specify the variable twice:
showName("x", x);
In order to get the name and value of the variable I am passing in.
Note that I am not interested in the name of argument in the prototype of showName, but the name of the variable in the calling function. Also, the variable passed may be local, so I can't use the window object to find the variable.
The short answer is that you can't.
The longer, evil answer is that you sort of can with some real nastiness. And it only works when called from another function.
there are two interesting attributes available to you that could help
arguments.callee
caller
for fn to do something like this:
(function(){
var showMe = function(s){
alert(arguments.callee.caller.toString().match(/showMe\((\S)\)/)[1] +
' = '+ s)
}
x = 1
showMe(x)
})()
What arguments.callee.caller.toString().match(..)[1] does is look for the showMe being called in the function calling it and prints it and its value.
But this is still pretty limited because it will only hit the first call of showMe(x). So if there is two calls to it, it won't work.
But, it was fun to play with these arcane things.
Strategy 1:
If you can control the data structure during function invocation then you can pass a dictionary which will encode name as a key, paired with its value, notice the stealth curly braces:
var foo = "bar";
yourfunction({foo});
Which passes a javascript dictionary that looks like this:
{foo : "bar"}
When yourfunction( is executed, unpack name and value thustly:
yourfunction = function(dict) {
var name = Object.keys(dict)[0];
var value = dict[name];
console.log(name); //prints foo
console.log(value); //prints bar
}
Strategy 2:
If you can maintain an as-you-go list of name-value pairs in a global scope, then reflection and introspection is always available for set and get, for example:
var my_global_stack = [];
yourfunction = function() {
//Chomp the stack
var dict = my_global_stack.pop();
//The name is the key at index 0
var name = Object.keys(dict)[0];
//Fetch the value by keyname:
var value = dict[name];
console.log(name); //prints foo
console.log(value); //prints bar
}
foo = "bar";
my_global_stack.push({foo});
yourfunction();
Strategy 3:
If user-hostile input isn't an issue, you can use eval( to rediscover value given variablename, for example:
yourfunction = function(somevariable) {
console.log(somevariable); //prints foo
console.log(eval(somevariable)); //prints bar
}
foo = "bar";
yourfunction("foo");
People say eval( is evil here, because if a hostile user is able to overwrite the value of foo in memory at any point, then they can do OS Command Injection and run any command they want.
http://cwe.mitre.org/top25/#Guidance
var x = "anything";
function showName(s) {
alert(s + " = " + eval(s));
}
showName("x");
Not recommended, but there it is.
You could create a hash and pass that in:
var x = {a: 1,b:2}
function showVars(y) {
for (var z in y) { alert(z + " is " + y[z]); }
}
showVars(x);
This doesn't necessarily show the name of the variable, but it does allow for key-value pairs, which may be more to the point of what you need.
This is what I use for debugging. No global variables, no eval, no arguments.callee or arguments.caller:
var Helpers = (function () {
// ECMAScript 5 strict mode
'use strict';
var Module = {};
Module.debug = function () {
var i;
for (i = 0; i < arguments.length; i++) {
console.log(arguments[i] + ':', this[arguments[i]]);
}
};
Module.SomeObject = function SomeObject() {
this.someMember = 1;
this.anotherMember = 'Whatever';
Module.debug.call(this, 'someMember', 'anotherMember');
var privateMember = {
name: 'Rip Steakface',
battleCry: 'Raaaaaaaaahhhhhhhhhrrrrrrrrrg!'
};
Module.debug.call(privateMember, 'name', 'battleCry');
};
return Module;
}());
For those who are wondering why you would want to do this, it's just a way to efficiently log multiple variables along with their names.
If you want to be able to log nested members, as in Module.debug.call(obj, 'hair.fluffiness'), you can modify the function like so:
Module.debug = function () {
var i, j, props, tmp;
for (i = 0; i < arguments.length; i++) {
tmp = this;
props = arguments[i].split('.');
for (j = 0; j < props.length; j++) {
tmp = tmp[props[j]];
}
console.log(arguments[i] + ':', tmp);
}
};
Unfortunately, I can't find any way to efficiently log multiple private variables that aren't members of an object, e.g. var roll = 3, value = 4; Module.debug.call(???);
Not sure you can directly get what you want from JavaScript, since the variable name is not carried around with the value it references (think of variable names as identifiers only the compiler knows about; but which get thrown away at runtime).
You can, however, do something slightly different which allows for passing around named arguments. Create an anonymous object and pass that to your function:
function showNames(o)
{
for( var ix in o )
{
alert( ix + ":" + o[ix] );
}
}
var z = { x : "Anything" }
showNames( z );
// or
showNames( { a : "ay", b : "bee", c: "see" } )
For iterating object properties, I tend to prefer a functional-style, as in:
Array.iteri = function(o, f)
{
for(var i in o) { f(i, o[i]) }
}
function showNames(o)
{
Array.iteri( o, function(i,v)
{
alert( i + ": " + v )
});
}
showNames( { a : "ay", b : "bee", c: "see" } )
The below code is about the best you can do. Unfortunately local variables in a function are properties of the hidden Call Object so they can't be accessed from Javascript like window[a] where a is a property of the window object.
x = "this is x";
var say = function(a) {
document.write(a + " = " + window[a]);
}
say("x");
var wrapper = function () {
var x = "this is x";
document.write(x + " = " + eval("x"))
}
wrapper()

Categories

Resources