Generating a function from a string in Javascript - javascript

I am using jQuery to take data from an xml file and save it to a string. The string is a switch statement which I want to become a function.
$.get('type.xml', function(xml) {
var cases=[];
$(xml).find('type').each(function(){
index=parseInt($(this).find('earn').text());
if($.isArray(cases[index])){
cases[index].push($(this).find('name').text());
}else{
arr=$.makeArray($(this).find('name').text());
cases[index]=arr;
}
});
var autoearn="function(x){switch(x){";
for(i=0;i<=100;i+=5){
if($.isArray(cases[i])){
$.each(cases[i], function(index,v){
autoearn+='case "'+v+'":';
});
autoearn+='$("input[name^=\'earn\']").val('+i+');break;';
}}
autoearn+='}}';
});
The first section makes a 2D array that associates an array of cases to their resultant output by their index. So that something that earns $10 (e.g. Meeting) will be stored in cases[10] (Meeting=cases[10][0]).
The second part writes a string that makes a puts into a switch statement that looks something like this:
function(x){
switch(x){
case "Meeting":
$("input[name^='earn']").val(10);
break;
case "Event1":
case "Event2":
$("input[name^='earn']").val(20);
break;
}
}
Note that the syntax for the switch cases make Event1 and Event2 have the same result.
Now autoearn is just a string that has the code for the function I want. How do make into a function? Is there a better way to do this? I'm thinking of sending it through PHP to return it back to jQuery but this whole thing seems really indirect and there is probably an easier way to do this.

First of all, make sure the code in the string is trusted, or you'll run into problems by executing arbitrary code.
You can create a function from a string as follows:
var f = new Function('arg1', 'arg2', ..., 'function code');
The above is equivalent to:
function f(arg1, arg2, ...) {
function code
}
In your case, you would want to remove the function(x) and the opening/closing braces from the autoearn string and create the function like this:
new Function('x', autoearn)

Here's a small piece of code to take a script from a string and execute it:
function loadScript(script) {
var func = null;
if (script) {
try {
func = new Function(script);
} catch (eParse) {
console.error("Error parsing script.");
console.debug(" error : %o", eParse);
console.debug(" script: %s", script);
}
}
if (func) {
try {
func(); // beware of scoping here, you might want to call this differently
} catch (eExec) {
console.error("Error running code.");
console.debug(" error : %o", eExec);
}
}
}
BEWARE: Using new Function is basically as dangerous as using an eval statement. Be sure of what you receive for the script parameter.

Related

Can you use parent function variables inside a returned function in javascript?

Here's the function code:
function TestFunction(number){
return function(e){
return `${number}`;
}
}
When I use it on google's devtools command line it returns:
function(e){
return `${number}`;
}
So it looks like the function returned is not created with the number I give to TestFunction, instead it takes the string just like it was written. I have tried to use concatenation instead of interpolation but still not working. What can I do?
There is indeed a closure around the second function, so it will have memory of what num is.
function a(num) {
return function b() {
return `${num}`;
}
}
const c = a(6);
console.log(c());

TypeError: "listener" argument must be a function. Using npm pixelmatch in node JS [duplicate]

How do I pass a function as a parameter without the function executing in the "parent" function or using eval()? (Since I've read that it's insecure.)
I have this:
addContact(entityId, refreshContactList());
It works, but the problem is that refreshContactList fires when the function is called, rather than when it's used in the function.
I could get around it using eval(), but it's not the best practice, according to what I've read. How can I pass a function as a parameter in JavaScript?
You just need to remove the parenthesis:
addContact(entityId, refreshContactList);
This then passes the function without executing it first.
Here is an example:
function addContact(id, refreshCallback) {
refreshCallback();
// You can also pass arguments if you need to
// refreshCallback(id);
}
function refreshContactList() {
alert('Hello World');
}
addContact(1, refreshContactList);
If you want to pass a function, just reference it by name without the parentheses:
function foo(x) {
alert(x);
}
function bar(func) {
func("Hello World!");
}
//alerts "Hello World!"
bar(foo);
But sometimes you might want to pass a function with arguments included, but not have it called until the callback is invoked. To do this, when calling it, just wrap it in an anonymous function, like this:
function foo(x) {
alert(x);
}
function bar(func) {
func();
}
//alerts "Hello World!" (from within bar AFTER being passed)
bar(function(){ foo("Hello World!") });
If you prefer, you could also use the apply function and have a third parameter that is an array of the arguments, like such:
function eat(food1, food2) {
alert("I like to eat " + food1 + " and " + food2 );
}
function myFunc(callback, args) {
//do stuff
//...
//execute callback when finished
callback.apply(this, args);
}
//alerts "I like to eat pickles and peanut butter"
myFunc(eat, ["pickles", "peanut butter"]);
Example 1:
funct("z", function (x) { return x; });
function funct(a, foo){
foo(a) // this will return a
}
Example 2:
function foodemo(value){
return 'hello '+value;
}
function funct(a, foo){
alert(foo(a));
}
//call funct
funct('world!',foodemo); //=> 'hello world!'
look at this
To pass the function as parameter, simply remove the brackets!
function ToBeCalled(){
alert("I was called");
}
function iNeedParameter( paramFunc) {
//it is a good idea to check if the parameter is actually not null
//and that it is a function
if (paramFunc && (typeof paramFunc == "function")) {
paramFunc();
}
}
//this calls iNeedParameter and sends the other function to it
iNeedParameter(ToBeCalled);
The idea behind this is that a function is quite similar to a variable. Instead of writing
function ToBeCalled() { /* something */ }
you might as well write
var ToBeCalledVariable = function () { /* something */ }
There are minor differences between the two, but anyway - both of them are valid ways to define a function.
Now, if you define a function and explicitly assign it to a variable, it seems quite logical, that you can pass it as parameter to another function, and you don't need brackets:
anotherFunction(ToBeCalledVariable);
There is a phrase amongst JavaScript programmers: "Eval is Evil" so try to avoid it at all costs!
In addition to Steve Fenton's answer, you can also pass functions directly.
function addContact(entity, refreshFn) {
refreshFn();
}
function callAddContact() {
addContact("entity", function() { DoThis(); });
}
I chopped all my hair off with that issue. I couldn't make the examples above working, so I ended like :
function foo(blabla){
var func = new Function(blabla);
func();
}
// to call it, I just pass the js function I wanted as a string in the new one...
foo("alert('test')");
And that's working like a charm ... for what I needed at least. Hope it might help some.
I suggest to put the parameters in an array, and then split them up using the .apply() function. So now we can easily pass a function with lots of parameters and execute it in a simple way.
function addContact(parameters, refreshCallback) {
refreshCallback.apply(this, parameters);
}
function refreshContactList(int, int, string) {
alert(int + int);
console.log(string);
}
addContact([1,2,"str"], refreshContactList); //parameters should be putted in an array
You can also use eval() to do the same thing.
//A function to call
function needToBeCalled(p1, p2)
{
alert(p1+"="+p2);
}
//A function where needToBeCalled passed as an argument with necessary params
//Here params is comma separated string
function callAnotherFunction(aFunction, params)
{
eval(aFunction + "("+params+")");
}
//A function Call
callAnotherFunction("needToBeCalled", "10,20");
That's it. I was also looking for this solution and tried solutions provided in other answers but finally got it work from above example.
Here it's another approach :
function a(first,second)
{
return (second)(first);
}
a('Hello',function(e){alert(e+ ' world!');}); //=> Hello world
In fact, seems like a bit complicated, is not.
get method as a parameter:
function JS_method(_callBack) {
_callBack("called");
}
You can give as a parameter method:
JS_method(function (d) {
//Finally this will work.
alert(d)
});
The other answers do an excellent job describing what's going on, but one important "gotcha" is to make sure that whatever you pass through is indeed a reference to a function.
For instance, if you pass through a string instead of a function you'll get an error:
function function1(my_function_parameter){
my_function_parameter();
}
function function2(){
alert('Hello world');
}
function1(function2); //This will work
function1("function2"); //This breaks!
See JsFiddle
Some time when you need to deal with event handler so need to pass event too as an argument , most of the modern library like react, angular might need this.
I need to override OnSubmit function(function from third party library) with some custom validation on reactjs and I passed the function and event both like below
ORIGINALLY
<button className="img-submit" type="button" onClick=
{onSubmit}>Upload Image</button>
MADE A NEW FUNCTION upload and called passed onSubmit and event as arguments
<button className="img-submit" type="button" onClick={this.upload.bind(this,event,onSubmit)}>Upload Image</button>
upload(event,fn){
//custom codes are done here
fn(event);
}
By using ES6:
const invoke = (callback) => {
callback()
}
invoke(()=>{
console.log("Hello World");
})
If you can pass your whole function as string, this code may help you.
convertToFunc( "runThis('Micheal')" )
function convertToFunc( str) {
new Function( str )()
}
function runThis( name ){
console.log("Hello", name) // prints Hello Micheal
}
You can use a JSON as well to store and send JS functions.
Check the following:
var myJSON =
{
"myFunc1" : function (){
alert("a");
},
"myFunc2" : function (functionParameter){
functionParameter();
}
}
function main(){
myJSON.myFunc2(myJSON.myFunc1);
}
This will print 'a'.
The following has the same effect with the above:
var myFunc1 = function (){
alert('a');
}
var myFunc2 = function (functionParameter){
functionParameter();
}
function main(){
myFunc2(myFunc1);
}
Which is also has the same effect with the following:
function myFunc1(){
alert('a');
}
function myFunc2 (functionParameter){
functionParameter();
}
function main(){
myFunc2(myFunc1);
}
And a object paradigm using Class as object prototype:
function Class(){
this.myFunc1 = function(msg){
alert(msg);
}
this.myFunc2 = function(callBackParameter){
callBackParameter('message');
}
}
function main(){
var myClass = new Class();
myClass.myFunc2(myClass.myFunc1);
}

a pure synchronous function in javascript that returns an error

I have a pure function that looks like :
function foobar(str) {
let newStr;
// code that depends on str and forge a new string
...
return newStr;
}
Now, I would like to raise an error if str is not as expected.
My error will be a simple object like { code: 'foo', msg: 'bar' } and I'm searching for the proper way to return this error from my function.
I'd like to avoid exceptions and promises (as they are asynchronous) and ideally, I'd like this function to adopt a functional programming style.
Any clue?
If you need to avoid async and typical error handling, you need your function to return an object instead of just a string. The object can have properties
var returnObject = {
error: false,
value: "the string",
errorValue: "OK"
};
Then every time you call the function it needs to check the condition of returnObject.error first:
var getStringObj = foobar("string input");
if ( getStringObj.error ) {
// probably display getStringObj.errorValue
} else {
//normal handling
}

Is it possible to determine whether a certain function may be called when a passed-in callback function is executed in JavaScript?

The question title basically says it all. I made this Fiddle to make it easy to test. Here's the code:
var test = function(callback) {
console.log("callback() might call alert()");
callback();
}
test(function() {
alert("one");
});
Converting a function to a string returns the source code, you can search that with a regular expression.
var test = function(callback) {
if (callback.toString().test(/\balert\s*\(/) {
console.log("callback might call alert()");
callback();
};
This isn't perfect, though. It won't work with:
var foo = alert;
test(function() {
foo("Fooled you!");
});
It could also get a false positive if alert( appears in a string.
You can redefine function alert
function alert(str) {
console.log('Somebody call alert:'+str);
}
But IMHO it can't be definitely checked before call.

How to print arguments' list in javascript?

Is there a way to print arguments' list in full or in parts in JavaScript?
Example:
from within the function my_assert(a!=b) I'd like to print a!=b, or even 2!=3 for a particular function call.
you can't. a!=b is executed first and only the result of this (true or false) is given to your function so you don't have a chance to get back a!=b or 2!=3.
console.log (arguments)
will print the arguments given to the function, but in your case, all your function sees is a boolean, because a != b will be evaluated first, and only the result passed as a parameter in the function call.
umm... here, I'll google it for you :)
http://www.seifi.org/javascript/javascript-arguments.html
As some others pointed out, passing in a test (a != b) will only get you a boolean value (true|false) as your argument. But if you call myAssert(a,b), you can then evaluate the arguments and test their equality, as well as print their values, following the advice in the link I pasted.
Here you go:
my_assert = (test) ->
str = my_assert.caller.toString()
match = /return my_assert\((.*)\)/.exec str
console.log match[1], test
a = '1'
b = '2'
do -> my_assert(a!=b)
do -> my_assert(b!=a)
> a !== b true
> b !== a true
http://jsfiddle.net/m7qRN/
The only caveat is you have to call your my_assert calls from separate anonymous functions in order to be able to reliably get the source code of the assertion call.
In CoffeeScript its not so bad using the do -> notation.
In JS this is: (function(){my_assert(a!=b)})();.
You could pass in the test as a function like so:
my_assert -> a!=b
my_assert(function(){a!=b});
//
// A variation on vaughan's answer, from Oct 1 '13
// Includes simple unit test to debug the regex for multiline assert expressions
// Use console.error and/or 'throw new Error' depending how you handle errors
//
function test_assert() {
try {
(function () { assert(3 === 'a') })();
(function () {
assert('foo' !== 'bar')
})();
(function () {
assert('foo' ===
'bar')
})();
} catch (e) {
console.error(e.stack)
}
} // test_assert
function assert(expression) {
if (!expression) {
let caller = assert.caller.toString()
let test = caller.match(/assert[^]*\)/)
//throw new Error(test[0] + ' failed');
console.error('%s failed', test[0])
}
} // assert
/////////////////////////////////
// Here's a simple assert()
function assert2(condition, message) {
if (!condition) {
console.error('assert (%s) failed: "%s"', condition, message)
throw new Error("Assertion failed: " + message);
}
}
You can't do it. When you have the following line:
my_assert(a!=b);
The expression a!=b will first be evaluated and its result will be passed to my_assert.
Assuming your my_assert() function is used specifically for your own testing and you can control how it works and what you pass into it you could do something like this:
my_assert(a!=b, "a!=b");
I.e., pass an extra parameter to the function with a string representation of what is being tested. Obviously that doesn't stop you accidentally saying my_assert(a!=b, "a==b");, and it's clunky, but I can't think of another way to do it.

Categories