Passing function does not evaluate - javascript

Please consider this javascript:
var a = function(arg1) {
alert(arg1);
}
a("hello");
a(function() { return "world"; });
How do I get it to return "world" in the second call? Right now it returns the whole function as a string.

Just execute the function expression, it will return world and that will be passed to the a function
a((function() { return "world"; })());
DEMO

You need to call the function, not just refer to it:
alert(arg1());
If you need to cope with a being called with either a string or a function, you'll need to check the type of the argument with typeof and handle them differently.

With the second call arg1 is a function.
To get the result you have to execute the function:
alert(arg1());

Related

Javascript invoke function without parentheses [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);
}

Passing A Function As Argument To A Function

function say(something) {
console.log(something);
}
function exec(func, arg) {
return func(arg);
}
exec(say, "Hi, there.");
Why does this code work? I feel like it shouldn't since what is in the second function should return
say(something) (arg) {
console.log(something) ;
}
It works as it does because when you write return func(arg);, the func(arg) bit executes the function. What is returned is then the result of executing func(arg).
However, you're right that say() doesn't actually return a value, it just logs to the console within that function. The output you're seeing is the result of that log command. If you logged the returned value instead you'd see undefined as the result.
But if you'd passed a different function to exec which did return a value, then you'd need the return in exec() for it to work properly.
P.S. I'm not sure if this is part of what you're asking, but the difference between that and when you wrote exec(say, "hi there"); is that in that code, say is a reference to the "say" function. At that moment it's treated like any other variable, just the same as if you passed in a number or a string, for example.
The difference is the (), which causes the function to be executed, rather than passed as a reference.
In the question you seem to imply that you'd expect the source code of the say() function to be displayed, but this is not what it does, and also is not possible anyway.
Function say returns undefined (default value if no return keyword is used), and therefore function exec also returns undefined.
Proof:
function say(something) {
console.log(something);
}
function exec(func, arg) {
var result = func(arg);
console.log(result);
return result;
}
var result2 = exec(say, "Hi, there.");
console.log(result2);
Maybe you are looking for a closure, where exec returns a function for getting arg for the first handed over function func.
function say(something) {
console.log(something);
}
function exec(func) {
return function (arg) {
return func(arg);
};
}
exec(say)("Hi, there.");

How to pass a callback function with multiple possible parameter lists

Here are two callback function:
function callback_a(){
alert('a');
}
function callback_b(p){
alert('b says'+ p)'
}
If I want use callback_a
function test(callback){
if(condition){
callback();
}
}
test(callback_a);
But the function test isn't applicable to callback_b, So how to implement a common function that you can passing some callbacks function with multiple possible parameter lists.
There are three options:
The easiest way is to use spread operator:
function test(callback, ...callback_args) {
callback(...callback_args);
}
in this case the invocation of test for function callback_b would be like this:
test(callback_b,"b")
The second way is using arguments which are scoped to any function in JavaScript:
function test(callback) {
callback.apply(null, arguments.slice(1));
}
the invocation of test for function callback_b would be the same:
test(callback_b,"b")
Another options is to use partially applied functions. In this case you should define b_callback like this (ES6 syntax):
let callback_b = (p) => () => void{
alert('b says'+ p)'
}
or without ES6:
function callback_b(p) {
return function(){
alert('b says'+ p)'
}
}
and invoke it like this:
test(callback_b("b"))
There is a special object called arguments that gets created when a function is invoked. It's an array-like object that represents the arguments passed in to a function:
It can be used like this:
test();
// no arguments passed, but it still gets created:
// arguments.length = 0
// arguments >> []
test(a);
// ONE argument passed:
// arguments.length = 1
// arguments >> [a]
test(a,b,c,d);
// FOUR arguments passed:
// arguments.length = 4
// arguments >> [a,b,c,d]
Knowing this, one can call a callback with the rest of the arguments passed in from the parent function using apply like this:
function test(callback) {
callback.apply(null, Array.prototype.slice.call(arguments, 1));
}
// arguments passed into test are available in the function scope when
// .slice is used here to only pass the portion of the arguments
// array relevant to the callback (i.e. any arguments minus the
// first argument which is the callback itself.)
//
// N.B. The arguments object isn't an array but an array like object so
// .slice isn't available on it directly, hence .call was used here)
Might be worth reading up on:
The arguments object
Function.prototype.apply, Function.prototype.call and Function.prototype.bind as they are way to bind a context and arguments to a function (i.e. they'll work with the arguments object to call a function where you may not know how many arguments will be passed)
So how to implement a common function that you can passing some callbacks function with multiple possible parameter lists.
Basically, you don't. The function receiving the callback is in charge of what the callback receives as arguments. When you call Array#forEach, it's Array#forEach that decides what arguments your callback gets. Similarly, String#replace defines what it will call its callback with.
Your job is to say what test will do, what it will call its callback with. Then it's the job of the person using test to write their callback appropriately. For instance: You might document test as calling the callback with no arguments. If the caller wants to use callback_b, then it's up to them to handle the fact that callback_b expects a parameter. There are several ways they can do that:
The could wrap it in another function:
test(function() {
callback_b("appropriate value here");
});
...or use Function#bind
test(callback_b.bind(null, "appropriate value here"));
...but it's their problem, not yours.
Side note: If they pass you callback_b and you call it without any arguments, you won't get an error. JavaScript allows you to call a function with fewer arguments than it expects, or more. How the function handles that is up to the author of the function.
You can pass an anonymous function as the callback that will itself return your desired callback function with parameters.
test(function() { return callback_b(' how are you'); });
see this working snippet that will first use callback_a, then callback_b (with parameter) as the callback:
function callback_a(){
alert('a');
}
function callback_b(p){
alert('b says'+ p);
}
function test(callback){
if(true){
callback();
}
}
test(callback_a);
test(function() { return callback_b(' how are you'); });
You can pass the parameter while calling the callback
function test(callback){
if(condition){
callback();
}
else if(other condition){
callback("b");
}
}
test(callback_b);
You can write your callback function like
function callback_a_b(){
if(arguments.length){
var arg = [].slice.call(arguments);
alert('b says'+ arg[0])
}
else{
alert('a');
}
}
You can pass array of parameters as second param of test function or in ES6 use spread operator read more here
function test(callback, params){
if(condition){
if (params === undefined){
callback();
} else {
callback.apply(null, params); //params must be array
//ES6: callback(...params);
}
}
}
test(callback_a);
test(callback_b, [" whatever"]);
I've just checked in my browser (ffox 51.0.1) that the following works:
function test(callback,other_args){if(condition){callback(other_args);}}
results:
condition=true
test(callback_a)
=> shows the alert with 'a'
condition=false
test(callback_a)
=> doesn't show anything
condition=true
test(callback_b,"pepe")
=> shows the alert with 'b sayspepe'
condition=false
test(callback_b,"pepe")
=> doesn't show anything

can we give a callback with parameters?

function abc(arg1,arg2, callback){
console.log(arg1 + arg2) // I am doing something really interesting
if(callback){
callback(arg1+ arg2)
}
}
function add(){
console.log("from call back " + arguments[0])
}
var a =10;
abc(1,2, add)
this works fine, but if we need to send some additional arguments to the call back, what should we do??
Here, Apart from (arg1+ arg2) I need some other arguments to be set from the caller of abc to the callback
And, what is the difference between abc(1,2,add) and abc(1,2,add()) ??
Thanks :)
abc(1,2,add) => Giving the function argument as "function type". This is like giving a pointer to the function for later invoking it.
abc(1,2,add()) => Calling the add() function and giving its return value as argument.
Do you need that the callback support more than an argument? Since JavaScript is a dynamic language, just call the same callback function with more arguments:
callback(1,2,3,4)
callback(1,2,3,4,5)
callback(1,2,3,4,5,6).
JavaScript isn't strict with function signatures: functions have as many arguments as the caller gives to them.
For example, if you've a callback function like this:
function(a, b) {
}
And later you call it this way:
function("hello"); // Where's the second argument??
JavaScript won't complain. Simply b will be undefined.
the difference between add and add():
add is a function and add() is the return value of the function.
if you want to get more arguments of the function. use the arguments object
every function has an arguments object
arguments[0] == 1 arguments[1] == 2 arguments[2] == add.
You can call your callback with parameters from your original function and you can also provide the parameters for the callback inside your function call:
function f1 (args, callback, params) {
callback.apply(this, params); // Params needs to be an array
callback.apply(this, [args]); // This would call callback with 1 param - args
callback.call(this, args); // This is the same as the line above
}
function f2 () {
for (item in arguments) {
console.log(item);
}
}
f1('arg', f2, [1, 2, 3]);
If you call your function with a function call inside the parameters then it would immediately evaluate and it would not be executed as a callback.
The difference between abc(1,2,add) and abc(1,2,add()) is that in the second case, it's not abc that calls add. The consequence is that add executes much sooner than expected and without any arguments.
The usual way to pass extra parameters to a callback is to create an anonymous function that closes over the parameters:
var a=10;
var b=20;
abc(a, b, function(text){
add(a, b);
console.log(text); //logs "abc"
});

Passing a function as an argument in a javascript function

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)
});

Categories

Resources