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 read Addy's book here about revealing module patter. However, if you execute the example code it actually returns undefined. A fix is to add 'return' before each called functions. Am I supposed to add return for each functions being called if using RMP? Is this the right way to make it work? What am I missing?
var myRevealingModule = (function () {
var privateCounter = 0;
function privateFunction() {
privateCounter++; <--need to add return
}
function publicFunction() {
publicIncrement(); <-- need to add return
}
function publicIncrement() {
privateFunction(); <--need to add return
}
function publicGetCount(){
return privateCounter;
}
// Reveal public pointers to
// private functions and properties
return {
start: publicFunction,
increment: publicIncrement,
count: publicGetCount
};
})();
myRevealingModule.start(); <-return undefined
http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript
The issue nas nothing to do with RMP but rather with functions and return values.
Why would you expect a method that doesn't return anything to actually return something other than undefined?
Take a closer look here. The start in fact calls publicFunction but the body of the latter doesn't return anything.
Yet you call it and expect a value.
The answer to your question is then: yes, if you want a value back from the function, you have to return it.
In this particlar example they have a method count to return current value. Two other methods are just used to control the counter.
This is a question from substack's stream-adventure question set. Link to question and solution is here:
https://github.com/substack/stream-adventure/tree/master/problems/duplexer_redux
I don't understand how the "write" method could work correctly in the solution:
function write (row) {
counts[row.country] = (counts[row.country] || 0) + 1;
}
Specifically, is there any guarantee that "row" will be full record like below? Is it posssible that "row" could be partial record?
{"short":"OH","name":"Ohio","country":"US"}
Looking through the code, it appears that duplexer is setting stream.write to call the write function on the input writer (which in this example is the through instance). So when duplexer.write is called it's calling it's writer.write:
https://github.com/Raynos/duplexer/blob/6d6f4b5b85964f7037917a9a3b70659c6e152f21/index.js#L44-L48
function proxyWriter(methodName) {
stream[methodName] = method
function method() {
return writer[methodName].apply(writer, arguments)
}
}
Within through it uses the input write as the write variable if it's supplied:
https://github.com/dominictarr/through/blob/6f814a601b37db1f44113e56a1eaa0c32a33b0a2/index.js#L14
write = write || function (data) { this.queue(data) }
And when it's own stream.write function is called (stream is returned for the through), it calls write's instead:
https://github.com/dominictarr/through/blob/6f814a601b37db1f44113e56a1eaa0c32a33b0a2/index.js#L25-L28
stream.write = function (data) {
write.call(this, data)
return !stream.paused
}
So all of that to say, when write is called on the duplexer, it looks as though it calls your defined write function passing the arguments it received. So you should receive the entire argument each time.
Hope that makes sense?
i am starting to look at JS in more detail and after testing out some code i have come up with this situation:
var hello = function ()
{
console.log(arguments);
return (function(x,y){console.log(arguments);return x*y;});
}();
console.log(hello(2,5));
The output from the console is as follows:
[object Arguments] { ... }
[object Arguments] {
0: 2,
1: 5
}
10
Can someone please explain the behavior as i cannot get my head around it.
I understand the the first function is an IIFE and it is being executed immediately when it is created. My only problem is how does the passed parameters be passed to the internal function?
Thanks in advance for the information and comments
Alright, let me see if I can unwrap this for you:
var hello = function ()
{
console.log(arguments);
return (function(x,y){
console.log(arguments);
return x*y;
});
}();
console.log(hello(2,5));
First, I'm going to split out the IFFE into a function statement. It will work the same, but be more like traditional code:
// Create our function
function action(x, y) {
console.log(arguments);
return x*y;
}
var hello = function ()
{
console.log(arguments);
//Here we are returning a REFERENCE to a function that already exists.
// We are *not* running the `action` function -- just getting its
// reference so it can be called later.
return action;
}();
// At this point in time, if you did a
console.log(hello)
// You'd see that it just points to the `action` function -- since that is what the
// IIFE returned.
console.log(hello(2,5));
The value hello is now our action function.
The IFFE syntax has the following advantages:
Since it is an anonymous function, you aren't using a name or cluttering the global object.
The code is more "in-line" instead of being split into two separate pieces.
Might help, by the way, if I explain the difference between a function statement and a function expression.
A function statement looks like this:
function functionStatemnt() {
...
}
The functionStatement is available at compile done. That code doesn't need executed in order to be available.
A function expression is more like:
var functionExpression = function() {
...
};
And an IFFE is a function expression that immediately invokes. Gives you a way to create a scope and "hide" variables.
var myCounter = function() {
var counter = 0;
return function() {
return counter++;
}
}
console.log(myCounter());
console.log(myCounter());
console.log(myCounter());
I was wondering whether this is legal to do. Could I have something like:
function funct(a, foo(x)) {
...
}
where a is an array and x is an integer argument for another function called foo?
(The idea is to have one function that uses a for loop on the array, and calls that function in the params for every element in the array. The idea is so call this on different functions so elements of two arrays are multiplied and then the sums are added together. For example A[0] * B[0] + A[1] * B[1].)
I think this is what you meant.
funct("z", function (x) { return x; });
function funct(a, foo){
foo(a) // this will return a
}
This is not the way to declare a function with another function as one of it's parameters. This is:
function foodemo(value){
return 'hello '+ value;
}
function funct(a, foo) {
alert(foo(a));
}
//call funct
funct('world!', foodemo); //=> 'hello world!'
So, the second parameter of funct is a reference to another function (in this case foodemo). Once the function is called, it executes that other function (in this case using the first parameter as input for it).
The parameters in a function declaration are just labels. It is the function body that gives them meaning. In this example funct will fail if the second parameter wasn't provided. So checking for that could look like:
function funct(a, foo) {
if (a && foo && typeof a === 'string' && typeof foo === 'function'){
alert(foo(a));
} else {
return false;
}
}
Due to the nature of JS, you can use a direct function call as parameter within a function call (with the right function definition):
function funct2(foo){
alert(foo);
}
funct2(foodemo('world!')); //=> 'hello world!'
If you want to pass a function, just reference it by name without the parentheses:
function funct(a, 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:
funct(a, function(){foo(x)});
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 myFunc(myArray, callback, args)
{
//do stuff with myArray
//...
//execute callback when finished
callback.apply(this, args);
}
function eat(food1, food2)
{
alert("I like to eat " + food1 + " and " + food2 );
}
//will alert "I like to eat pickles and peanut butter"
myFunc([], eat, ["pickles", "peanut butter"]);
And what would you like it to achieve? It seems you mixed up a function declaration with a function call.
If you want to pass another calls result to a function just write funct(some_array, foo(x)). If you want to pass another function itself, then write funct(some_array, foo). You can even pass a so-called anonymous function funct(some_array, function(x) { ... }).
I would rather suggest to create variable like below:
var deleteAction = function () { removeABC(); };
and pass it as an argument like below:
removeETC(deleteAction);
in removeETC method execute this like below:
function removeETC(delAction){ delAction(); }
What you have mentioned is legal. Here, foo(X) will get called and its returned value will be served as a parameter to the funct() method
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)
});