Javascript function name in variable - javascript

Hi guys!
Could you please help me with the function beloW?
Code executes as planned, but as soon as i replace the 'SLL' string below with a variable, I get error.
This works fine: x = 'SLL'
This does not work: x = schemename (assuming i define var schemename = 'SLL' earlier in the code)
Please see code below
function sll() {
return 'got it';
}
var mySchemes = {
SLL: sll
};
x = 'SLL';
mySchemes[x]();

What are you using to run the code? You can run the code right here on StackOverflow and see that it's running fine. The one issue you could be having is if 'use strict' is being enforced, in which case you need to define x explicitly.
function sll() {
return 'got it';
}
var mySchemes = {
SLL: sll
};
var x = 'SLL';
console.log(mySchemes[x]());

Related

Swapping hardcoded arguments for variables

I've got a functional script on my site that allows me to open a link in a new window when a specific class is added to the link. I need a lot of those on my site though so I figured I'd make the script a bit easier to edit by working with variables.
In the process of changing out hardcoded strings for variables my script stopped working though. The only one that works is the var where I set the url.
I'm learning that ${} doesn't work everywhere. Hope that someone can point out where my thinking is wrong. Also hope that I got the terminology right, trying to learn though! :-)
var function1Name = "test_function";
var function1Url = "https://www.google.com";
var function1Class = ".test_function_class";
function ${function1Name}() {
window.open(function1Url, "_blank", "height=200");
}
jQuery("${function1Class}").click(function(){
${function1Name}()
});
None of your uses of ${} are valid JavaScript syntax.
Your function declaration van be replaced with:
window[function1Name] = function () {
window.open(function1Url, "_blank", "height=200");
}
Please note that the function will no longer be hoisted when declared this way, so order of operation matters.
The click handler can be written as follows:
jQuery(function1Class).click(function() { // Note that I just used the variable there.
window[function1Name]();
});
There is a ${} concept in JavaScript, but that is only in template literals:
const myVariable = "Foo";
const message = `myVariable contains: "${myVariable}"!`;
console.log(message);
There's several syntax issues here.
Firstly, function ${function1Name}() is not valid syntax. Function names must be defined before runtime. If you want to dynamically access a function, place it in an object and set the key with the variable reference.
Secondly, ${function1Name}() is again not valid syntax. You cannot invoke a function like that dynamically. Referring to the suggestion above, you can access an object dynamically so the first point fixes this problem.
Thirdly, string interpolation only works within template literals, so you need to delimit the string with backticks: ``. However it's completely redundant here as you can just use $(function1Class)
With those issues in mind, here's an updated example:
var function1Name = "test_function";
var function1Url = "https://www.google.com";
var function1Class = ".test_function_class";
var funcObj = {
[function1Name]: function() {
console.log(`function called, window would open here containing ${function1Url}...`);
// window.open(function1Url, "_blank", "height=200");
}
}
$(function1Class).click(function() {
funcObj[function1Name]()
});
/*
alternative using a template literal, although note that it's redundant here
$(`${function1Class}`).click(function() {
funcObj[function1Name]()
});
*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Click me
One last thing to note is that no version of IE supports template literals, so be sure of your browser support requirements before using them.
So cool, I got it to work!
var function1Name = "test_function_1";
var function1Url = "https://www.google.com";
var function1Class = ".test_function_class1";
var function2Name = "test_function_2";
var function2Url = "https://www.cnn.com";
var function2Class = ".test_function_class2";
// Function 1
window[function1Name] = function () {
window.open(function1Url, "_blank", "toolbar=no,status=no,scrollbars=yes,resizable=yes,top=500,left=500,width=600,height=745");
}
jQuery(function1Class).click(function() {
window[function1Name]();
});
// Function 2
window[function2Name] = function () {
window.open(function2Url, "_blank", "toolbar=no,status=no,scrollbars=yes,resizable=yes,top=500,left=500,width=600,height=745");
}
jQuery(function2Class).click(function() {
window[function2Name]();
});
I can now add a bunch of url's and corresponding classes as was my intention. Super happy about that.
A follow up question though, as I'll have to experiment with what the ideal window parameters will be I'm trying to make those arguments variables as well. I've tried the examples of how to insert a variables output from the functional code but those methods don't work there. Here's that code:
var windowWidth = 250
var function1Name = "test_function_1";
var function1Url = "https://www.google.com";
var function1Class = ".test_function_class1";
var function2Name = "test_function_2";
var function2Url = "https://www.cnn.com";
var function2Class = ".test_function_class2";
// Function 1
window[function1Name] = function () {
window.open(function1Url, "_blank", "toolbar=no,status=no,scrollbars=yes,resizable=yes,top=500,left=500,width=[windowWidth],height=745");
}
jQuery(function1Class).click(function() {
window[function1Name]();
});
// Function 2
window[function2Name] = function () {
window.open(function2Url, "_blank", "toolbar=no,status=no,scrollbars=yes,resizable=yes,top=500,left=500,width=600,height=745");
}
jQuery(function2Class).click(function() {
window[function2Name]();
});
How would I insert the variables value (2nd line of Function1) there ?

Method not defined as a function (while defined as one)

I am experimenting a strange issue: at the beginning of my code, I defined a function like so:
function rootEmbed()
{
var embed = new Discord.RichEmbed()
.setColor(config.embedColor);
return embed;
//returns an object
}
Later in the same file, I define another function which calls the one above, like so:
function commandList()
{
var embed = rootEmbed();
//....
}
Calling that function causes no problem, however calling the following function returns an error that says
(node:4988) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: rootEmbed is not a function
Here is the told function:
function voidTrader(trader)
{
var rootEmbed = rootEmbed();
//...
}
I can't figure out why does the voidTrader() method causes an error while commandList() turns out perfectly fine. What am I doing wrong?
If you want the full code, you can find it here.
Thanks in advance!
This is a combination of variable hoisting and variable shadowing. When you initialize a variable var x = 5, what happens is that var x is hoisted to the top of the code file. However, function declarations are hoisted even higher. Meaning that when your file is run, this is what is happening:
function rootEmbed (){//...code here}
var rootEmbed = undefined;
To fix this problem, change this:
function voidTrader(trader)
{
var rootEmbed = rootEmbed();
//...
}
To something like this:
function voidTrader(trader)
{
var rootEmbedResult = rootEmbed();
//...
}
There is another problem at lines 25-26:
var year = "" + stamp.getYear();
var year = twoDigits("20" + year.substr(-2));
year is declared with var twice.

Overriding prototype.toString doesn't work

I have the following code.
function Test() {
this.myTest = "Test";
}
Test.prototype.toString = function testToString() {
return this.myTest;
};
var test = new Test();
console.log(test);
I expect this to print Test, but it prints Test { myTest: 'Test' }. I thought that overriding toString should use that new function whenever it tries to convert to a string. Any ideas why this isn't working?
According to the specifications (console.log --> Logger --> Printer) the implementation of console.log is ultimately up to the implementation.
So, it is likely that in the environment you are working in the implementation of console.log(obj) is not simply Printer("log", obj.toString()).
function Test() {
this.myTest = "Test";
}
Test.prototype.toString = function testToString() {
return this.myTest;
};
var test = new Test();
console.log(test.toString());
Based on some of the answers here I was able to solve this by using the following code. Although it's similar to some existing answers it is slightly different so decided to post it here.
function Test() {
this.myTest = "Test";
}
Test.prototype.toString = function testToString() {
return this.myTest;
};
var test = new Test();
console.log(test + "");
So just adding + "" to the end of the console.log works perfectly and will run the toString function.

How to dynamically change the contents of a function using JavaScript

To help understand this the function is in the html page and it is generated, I cannot change the generated code:
function Update_qu7260() {
var newVal = ''
for( var idx = 0; idx < 2; idx++ )
{
var test
if( idx == 0 ) test = text7263
else if( idx == 1 ) test = text7265
if( test.matchObj ) newVal += test.leftSel + "-" + test.matchObj.rightSel + ","
}
newVal = newVal.substring( 0, newVal.length-1 )
VarQuestion_0001.set( newVal )
qu7260.hasBeenProcessed=false;
doImmFeedback('qu7260');
}
var qu7260 = new Object();
...
qu7260.updFunc = Update_qu7260;
var qObj=[qu7260];
Note in the above the number "7260", the numbers start at 1 so there are lots of them and each Update_###() will be different so I cannot re-write them with "hard wired" code. My code is in an external JavaScript file and is executed onLoad:
...
var updFunc = qObj[0].updFunc.toString();
if(updFunc.indexOf('doImmFeedback(')!=-1){
updFunc = updFunc.replace('doImmFeedback','doImmQuestionFeedback'); // do my function
updFunc = updFunc.replace('function ',''); // remove the word function
var funcName = updFunc.substr(0,updFunc.indexOf('(')); // get the function name e.g. Update_qu7260
updFunc = "window['" + funcName + "']=function" + updFunc.replace(funcName,'');
eval(updFunc);
}
...
When I change the eval() to alert() I can see the that it's correct, however, the eval() is not raising any errors and my function doImmQuestionFeedback is not being called. When I subsequently do an alert(qObj[0].updFunc.toString()) I see the original function.
It would seem that I have provided information that is too complex, so the following code is a better example:
function hi(){alert('hi');}
function changeHi(){
hi(); // I get an alert box with hi
newHi = "function hi(){alert('hi there');}"
eval(newHi);
hi(); // I get an alert box with hi
window.setTimeout('hi()',500); // I get an alert box with hi
}
window.setTimeout('changeHi()',500);
The following is the original question:
I have a predefined function that I did not create, however, I know it's name so I can get the function itself and then I change it by doing:
var funcText = window.updateFunc.toString();
funcText = funcText.replace('doSomeOtherFunction(','doMyFunction(');
How do I update the actual function so it will do all that it did before except it will now call doMyFuntion()?
The following is an example to help visualize what I want to do, the actual function I need to change is very complex. I have:
function updateFunc(whatToUpdate,true){
... - do lots of stuff.
var retVal = doSomeOtherFunction(whatToUdate);
... - do lots of stuff based on retVal
}
I need to change this to:
function updateFunc(whatToUpdate,true){
... - do lots of stuff
var retVal = doMyFunction(whatToUdate);
... - do lots of stuff based on retVal, I have had a chance to change retVal
}
Then the first thing my function will do is call doSomeOtherFunction() check/change the returned value and subsequently return the value to the updateFunc().
I have tried to manipulate the funcText above to:
funcText = 'window.updateFunc = function(...';
eval(funcText);
Without success.
This may be closed enough to what you are looking for.
Assuming you have this original function:
function originalFunc(val) {
// this function converts input string to upper case
return val.toUpperCase();
}
Now you want to override it to something either before or after you execute that function (in this example, we execute before, of course before or after doesn't matter in this case).
// we preserve orignal function
var originalFunc_save = originalFunc;
// now we override the original function with this block
var originalFunc = function(text) {
// lets call the orignal function
text = originalFunc_save(text);
// now do our custom thing
return text.split('').reverse().join('');
}
So our test should work.
var text = 'This is a test';
console.log(originalFunc(text));
Output:
TSET A SI SIHT
This method also works if you have to override functions inside a class. The only thing we have to be careful of is to choose a saved name that doesn't interfere with the original class code. _save may not be good enough, but you get the idea.
UPDATE: I'm updating this code above to use a string variable pointing to the original function. I think this is what the OP wanted.
Original code which defined by some library
function originalFunc(val) {
// this function converts input string to upper case
return val.toUpperCase();
}
Now we use the func string variable to point to that function and execute it.
var text = 'This is a test';
var func = 'originalFunc';
text = window[func](text);
console.log(text);
Output: Of course we get the original intended result because we haven't overridden it.
THIS IS A TEST
Now we write our code to override the original function behavior using a string pointing to the function.
// let's define a new function string
var funcSaved = func + '___saved';
// now preserve the original function code
window[funcSaved] = window[func];
// override the original function code block
window[func] = function(text) {
// lets call the orignal function
text = window[funcSaved](text);
// now do our custom thing
return text.split('').reverse().join('');
}
// let's test the code
text = 'This is a test';
text = window[func](text);
console.log(text);
Output:
TSET A SI SIHT
You can make a clone of updateFunc function, edit it at your discretion and work with it in what follows.
function updateFunc(whatToUpdate, param){ // the initial function
...
var retVal = doSomeOtherFunction(whatToUpdate);
return retVal;
}
// formation of unnamed function as string
var newfunc = updateFunc.toString().replace('function updateFunc', 'function ').replace('doSomeOtherFunction(', 'doMyFunction(');
function doMyFunction(whatToUpdate){ // your new function, just for example
console.log(parseInt(whatToUpdate) * 10);
}
var newUpdateFunc;
// declaring new version of 'updateFunc' function
// which is stored in 'newUpdateFunc' variable
eval("newUpdateFunc = " + newfunc);
newUpdateFunc(3); // outputs '30'
I believe this is a valid use case for the forgotten JavaScript with feature.
Basic idea: you call original updateFunc supplying your own version of doSomeOtherFunction to it using with namespace injection:
function updateFunc(whatToUpdate,true){
... - do lots of stuff.
var retVal = doSomeOtherFunction(whatToUdate);
... - do lots of stuff based on retVal
}
function patchUpdateFunc() {
var original_doSomeOtherFunction = window.doSomeOtherFunction;
var original_updateFunc = window.updateFunc;
function doMyFunction() {
// call original_doSomeOtherFunction() here,
// do your own stuff here.
};
window.updateFunc = function() {
with ({doSomeOtherFunction: doMyFunction}) {
return original_updateFunc.apply(this, arguments);
}
}
}
patchUpdateFunc();
I think you are going at this way too complicated.
If you only have doMyFunction and doSomeOtherFunction to switch between, you could just create a flag somewhere telling you to use one or the other when used in an if-statement.
If you want to call a function with a name you do not know beforehand and you only get a name during runtime, you could either accept the function to call as a parameter or accept the name of the function as a parameter and call it like so: var retVal = window[functionName](); (assuming functionName is a property of the window object).
I would highly recommend directly accepting a function as a parameter since the function may not be defined in a global scope.
EDIT:
After your clarification, I think, I can give you a satisfying answer:
if you have a string like var functionString = "function updateFunc(whatToUpdate){var retVal = doMyFunction(whatToUpdate);}";
You can define a function using a Function object:
window.updateFunc = new Function("whatToUpdate", "return (" + functionString + ")(whatToUpdate)");
This will replace the already existing function and you can give it any valid function string you want as long as you know and specify the arguments.
If I understood correctly, you want to override the external function. You can achieve that with the following code
//Someone else's function
function externalFunction(foo){
return "some text";
}
//Your function
function myFunction(value){
//Do something
}
//Override
var externalFunction = (function(){
var original = externalFunction; //Save original function
return function(){
var externalFunctionReturnValue = original.apply(this, arguments);
return myFunction(externalFunctionReturnValue);
}
})();
I strongly sugest not to use eval, but since you want to parse javascript from string:
function hi(){alert('hi');}
function changedHi(){
hi(); // I get an alert box with hi
newHi = "window['hi'] = function(){alert('hi there');}"
eval(newHi);
hi(); // I get an alert box with hi there
window.setTimeout('hi()',500); // I get an alert box with hi there
}
window.setTimeout('changedHi()',500);
UPDATE:
This code snippet works which is your original code:
<script type="text/javascript">
function doImmFeedback(foo){
console.log("DoImmFeedback: " + foo);
}
function Update_qu7260() {
console.log("Some code")
doImmFeedback('qu7260');
}
</script>
<script type="text/javascript">
var qu7260 = new Object();
qu7260.updFunc = Update_qu7260;
var qObj=[qu7260];
var updFunc = qObj[0].updFunc.toString();
if(updFunc.indexOf('doImmFeedback(')!=-1){
updFunc = updFunc.replace('doImmFeedback','doImmQuestionFeedback'); // do my function
updFunc = updFunc.replace('function ',''); // remove the word function
var funcName = updFunc.substr(0,updFunc.indexOf('(')); // get the function name e.g. Update_qu7260
updFunc = "window['" + funcName + "']=function" + updFunc.replace(funcName,'');
console.log(updFunc);
eval(updFunc);
}
function doImmQuestionFeedback(foo){
//Your function
console.log("doImmQuestionFeedback: " + foo);
}
Update_qu7260(); //This executes your doImmQuestionFeedback
</script>
So if your function isn't running, your function isn't in the global scope, or something else is happening, and we can't know if don't have any more info. Check your developer's console for javascript errors.

how to get a property name which represent a function in JS

This is some JS code
var methodArr = ['firstFunc','secondFunc','thirdFunc'];
for(var i in methodArr)
{
window[methodName] = function()
{
console.log(methodName);
}
}
My problem is that how to get the name of a function in JS.
In JS, use this.callee.name.toString() can get the function name. But in this situation, it is a null value. How can i get the 'funName' string?
Sorry, I didn't make it clear.
I want to create functions in a for loop, all these functions has almost the same implementation which need its name. But others can call these functions use different name.I want to know what methodName function is called.
it seems a scope problem.
Try this:
var methodArr = ['firstFunc','secondFunc','thirdFunc'];
for(var i in methodArr) {
var methodName = methodArr[i]; // <---- this line missed in your code?
window[methodName] = (function(methodName) {
return function() {
console.log(methodName);
}
})(methodName);
}
window['secondFunc'](); // output: secondFunc

Categories

Resources