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);
}
I was just wondering;
Why does this work;
test = function(message) {
console.log('xxx');
}
setTimeout(test, 3000);
but not this;
test = function(message) {
console.log(message);
}
setTimeout(test('xxx'), 3000);
I know it should be written like this;
But the version above would be so much more convenient...
test = function(message) {
console.log(message);
}
setTimeout(function() { test('xxx'); }, 3000);
You're assigning the returned result of test to the callback argument of setTimeout instead of passing the function reference.
function callback(callback) {
callback();
}
function say(message) {
console.log(message);
// this function doesn't return anything
}
// callback(say('Hello World!')) === callback() because say(message) doesnt return anything.
In your 2nd example it is immediately calling test with the string xxx.
You are calling the function immediatly in your second example. To pass the string, you can bind the parameter instead of calling it on its own:
setTimeout(test.bind(null,'xxxx'), 3000);
test = function(message) {
alert(message);
}
setTimeout(test.bind(null,'xxxx'), 3000);
If you write a function name with parenthesis, it will call it instead giving reference.
The second one doesn't work because setTimeout requires a function as a parameter (which it will call) and the second version you show has test('xxx') which means "the result of calling test('xxx')" which is undefined - not a function.
I wondering if we can set a function containing a Callback function as parameter to another function who takes a callback too.
Example
function save(err, data, cb){};
function get(id, cb){};
get('12', save)?
Of course, a variable can be passed as argument of a function!
It may be clearer for you if you do:
// This also works with the notation `function save(...)`
var save = function(err, data, cb) {
alert('save' + err); // save12
},
get = function(id, cb) {
alert('get' + id); // get12
cb(id); // This call the "save" function
}
;
get('12', save);
Just be careful to not stack your callback too much or you will enter in the callback hell world!
Yes you can, check this example:
jsFiddle Example
jQuery(document).ready(function () {
function1({
param: "1",
callback: function () {
function2({
param : "2",
callback: function(){
alert("hello");
}
})
}
});
});
function function1(params){
alert(params.param);
params.callback();
}
function function2(params){
alert(params.param);
params.callback();
}
I hope it will be useful.
I have this code:
var callbackAfterLoad = function(data, ecBlock) {
ecBlock.html(data);
ecBlock.slideDown();
}
function bindevents(userInput, ecBlock, callbackAfterLoad) {
userInput.keyup(function () {
delay(function () {
$.post("/preview", {content:userInput.val()}, callbackAfterLoad(data, ecBlock));
}, 500);
});
}
And this error:
Uncaught ReferenceError: data is not defined
But when I check out jQuery examples
$.post("test.php", function(data) {
alert("Data Loaded: " + data);
});
Why do I got this error ? Why do jQuery example is working and not mine ? (we cannot add parameters ?). Is the default $.post callback defined and his signature cannot be overriden ?
The third argument in $.post should be a function, but when you do this:
$.post("/preview", {content:userInput.val()}, callbackAfterLoad(data, ecBlock))
The third argument is not the function, but the return value of the function. Like this:
fn = callbackAfterLoad // function reference
fn = callbackAfterLoad() // function execution and return value reference
And when executed in your example, data is not available yet. The correct syntax would be:
$.post("/preview", {content:userInput.val()}, callbackAfterLoad)
If you need to pass custom arguments to your callback, you can create a new proxy function like this:
var callback = function(data) {
callbackAfterLoad.call(this, data, ecBlock);
};
$.post("/preview", {content:userInput.val()}, callback);
Try to use .post method in little bit another way:
$.post("/preview", {content:userInput.val()}, function(data){ callbackAfterLoad(data, ecBlock)} );
Your example doesn't work because you're immediately calling to callbackAfterLoad , before the .post actually "happens" and returns data. In jQuery example the callback function is only registered as handler but not firing immediately.
Why is this code working:
function onCordovaReady() {
navigator.globalization.getLocaleName(function (locale) {
jQuery.i18n.properties({
name:'message',
path:'lang/',
mode:'map',
language:locale.value,
callback: function(){
alert(locale.value);
alert(jQuery.i18n.prop('msg_hello'));
alert(jQuery.i18n.prop('msg_complex', 'John'));
}
});
});
}
And this one not:
function onCordovaReady() {
navigator.globalization.getLocaleName(function (locale) {
jQuery.i18n.properties({
name:'message',
path:'lang/',
mode:'map',
language:locale.value,
callback: onLanguageReady(locale)
});
});
}
function onLanguageReady(locale) {
alert(locale.value);
alert(jQuery.i18n.prop('msg_hello'));
alert(jQuery.i18n.prop('msg_complex', 'John'));
}
I want to make the callback in a different function so my code will look cleaner, but couldn't get it to work. The first alert will work (it will display nl_NL), but the second and third alert will output [msg_hello] and [msg_complex].
Many thanks!
Try with this:
// beginning of code omitted
callback: function(locale) {
onLanguageReady(locale)
}
it is because you are assigning undefined to the callback property.
You are calling onLanguageReady and assigns that value to the callback method.
The solution is to use another function as callback function which will call the onLanguageReady function as given by #romainberger
function onCordovaReady() {
navigator.globalization.getLocaleName(function (locale) {
jQuery.i18n.properties({
name:'message',
path:'lang/',
mode:'map',
language:locale.value,
callback: onLanguageReady
});
});
}
function onLanguageReady(locale) {
alert(locale.value);
alert(jQuery.i18n.prop('msg_hello'));
alert(jQuery.i18n.prop('msg_complex', 'John'));
}
will work if the function calls back with locale.
the callback is expecting a function pointer that it can call once the processing is done when you say onLanguageReady(locale) you are actually executing the function and thus assigning the result of the function as the call back in this case the return is nothing thus undefined