Am a newbie in javascript, please help me understand below case where the callback function code is being considered as a string and passed as argument instead of passing the value of the callback function as an argument:
//Case3: Create Callback function in the argument section of calling statement.
function child3(callback,arg2=3) {
return console.log("Case3: callback function - parent function out:", callback+arg2,"\n");
}
child3(parent3=()=>{
let a=1;
let b=1;
return a+b;
},2);
Output:
Case3: callback function - parent function out: ()=>{
let a=1;
let b=1;
return a+b;
}2
When you use +, there are two possibilities:
If both operands are numbers or BigInts, they are added together
Otherwise, both operands are concatenated together into a string
If you do
callback+arg2
and callback isn't a number, the result will be a concatenation of it and arg2. In your code, callback is not a number; it's a function. You probably wanted to call the callback instead of concatenating it - eg, callback().
Another issue is that
child3(parent3=()=>{
should almost certainly be
child3(()=>{
unless you deliberately wanted to both create a new global function named parent3 and pass that to child3.
function child3(callback, arg2 = 3) {
console.log(callback() + arg2);
}
child3(() => {
let a = 1;
let b = 1;
return a + b;
}, 2);
It's not a string, but a parameter. It has a name in the function's parameter list, which is callback, so, inside the function it is referred to as callback and when you pass
"Case3: callback function - parent function out:", callback+arg2,"\n"
to console.log, you convert the function to string. By the way, you can do that without passing the function as parameter as well
function foo(a, b) {
return a + b;
}
console.log(foo);
So, you do not pass it as a string, you pass it as a function instead, but it is converted into a string, i.e. the function definition when you call console.log.
Related
How does the second argument get called in liftf(add)(1)?
function add (first, second) {
return first + second;
}
function liftf (binary) {
return function (first) {
return function (second) {
return binary(first, second);
};
};
}
var inc = liftf(add)(1);
I understand how lift(add) is called and stored.
I am confused on how a function is returned but then called with (1).
I first explored if it operated on the same principle of an IIFE but it doesn't seem to. IFFE's would be (function() {}()) vs funciton() {}().
The 'chained' function arguments confuse me and I want to understand what's going on.
Thanks!
If an expression evaluates to a function, then that function can be invoked with parentheses and the list of arguments.
Since the expression liftf(add) returns a function, you call the returned function with the parameter 1 in parentheses: liftf(add)(1)
Another way to look at it is if you set liftf(add) to a variable, then you could call the function stored in that variable:
var additionFunc = liftf(add) // Stores the new function in additionFunc
var result = additionFunc(1) // Evaluates the new function
Let's also look at IIFEs. Suppose we have one like this:
(function(x) {return x + 1})(5)
The (function() { /* ... */ }) expression evaluates to a function, which is then evaluated by the parentheses and argument (5).
Let's look at a simpler example of currying:
function add(x) {
return function (y) {
return x + y;
};
}
If you called it with only one argument, like so:
add(2);
It would expand to:
function (y) {
return 2 + y;
}
Which would expect a y argument (if you called it). You could run that like this:
function (y) {
return 2 + y;
}(5)
Or more succintcly:
add(2)(5);
Each function just expands to a new anonymous function when currying, so even though it looks weird, once you expand the code out, it will start to make sense.
Today, I saw the following code below:
log_execution_time = require('./utils').log_execution_time;
var fib = function fib(n) {
if (n < 2) return n;
return fib(n - 1) + fib(n - 2);
};
var timed_fib = log_execution_time(fib);
timed_fib(5);
>>> Execution time: 1.166ms
I am curious about function log_execution_time. I don't know how it is.
You can see the input of log_execution_time is a function. How can it call the function with parameter? But all of the methods from w3school need a parameter when calling a function. I assume:
var log_execution_time = function (input_function){
console.time("Execution time");
// input_function
console.timeEnd("Execution time");
}
Thanks and regards
I think the OP is specifically about how the 5 parameter gets passed to the function input_function
Functions are first class objects in JavaScript. You can set identifiers and pass their references around just the same as any other object.
log_execution_time(fib); does not invoke fib, it passes a reference to fib into the log_execution_time function as the first argument. This means the internals can reference fib
timed_fib is a function which can reference the closure from that invocation of log_execution_time due to when it was created, so it can hence invoke the reference to fib as desired
Here is a simple example;
function log(msg) {
console.log(msg);
}
function wrap(fn) {
return function () { // some anonymous function to be our wrapper
console.log('Wrapped:');
fn.apply(this, arguments); // this line invokes `fn` with whatever arguments
// that were passed into the anonymous function
};
}
var foo = wrap(log);
foo('Hello World'); // logs
// Wrapped:
// Hello World
We could also have used the more usual way to invoke fn, for example fn("fizz buzz");, instead of .apply but that would mean we needed to know more about how to invoke fn, which could have been anything
Useful stuff:
Function.prototype.apply
Function.prototype.call
This is known as function currying, in this case the function is being curried with a parameter that also happens to be a function. It may look something like this:
function logTime(f) {
return function() {
var s = new Date();
var r = f.apply(null, arguments);
var e = new Date();
console.log('Time taken ' + (e-s));
return r;
}
}
function numberlogger(n) {
console.log("logged number: " + n)
};
var timedlogger = logTime(numberlogger);
console.log(timedlogger(2));
We call logTime, passing in numberlogger as an argument. Functions in JavaScript are objects and can be passed around like anything else. The logTime function returns a different function that is then stored in timedlogger. When we invoke timedlogger, we're actually invoking the function that logTime returned. That uses a couple of variables to keep track of the start and end times for timing, but uses apply (which every function in js has) to call the original function (numberlogger) whilst passing in any arguments supplied.
I suggest reading up on Functions in Javascript. Here's a nice article from the Mozilla Developer Network (MDN) which is in my opinion, a much better resource than w3schools
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions
To answer your question though, functions in javascript are first class citizens, and what that means is that you can think of them as any other object (string,boolean,number etc). They can be saved in variables and they can be passed as arguments into other functions.
In your example, log_execution_time will actually return a function which is essentially a wrapper around the fib function that gets passed to it
The code can be like this:
var log_execution_time = function (input_function){
var f=function(args)
{
var t1=new Date().getTime();
input_function(arguments);
console.warn("Execution time:" +(new Date().getTime()-t1).toString());
}
return f;
}
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"
});
I'm new to jQuery and am bit confused about the use (or not) of parentheses with a callback function. Say I have a function:
function cb() {
// do something
}
Now what is the difference between:
$("p").hide(1000, cb);
and
$("p").hide(1000, cb());
Is it to do with when the cb function is executed? It would be great if someone could explain this to me in the simplest of terms.
cb() means give me the result of executing the function cb.
cb IS the function cb or, more accurately a pointer (reference) to it.
Is it to do with when the cb function is executed?
Essentially, yes, though the difference does run a little deeper than that.
cb is a reference of sorts to the function. You're passing the function along as a parameter to be invoked somewhere down the line.
cb() is a function call; the function will be invoked, and the result passed as an argument to .hide.
The difference is that in javascript functions are first class objects and can be passed to other functions so that they may executed at a later stage or depending on some logic.
Consider the following:
function add(a, b) {
return a + b;
}
function minus(a, b) {
return a - b;
}
function apply(func, a, b) {
return func(a,b);
}
apply(add, 3, 4); // returns 7
apply(minus, 3, 4); // returns -1
apply(add(), 3, 4); // error: invalid number of arguments for add
apply(add(0,0), 3, 4); // error: add returns 0, but 0 is not a function and
// so apply crashes when it tried to call zero as a function
$("p").hide(1000, cb); passes the function referenced by cb, as a callback.
$("p").hide(1000, cb()); passes the value returned when the function cb is called.
Given:
function cb(){ return true; }
The former is passing the callback for later calling. The latter passes the returned value true, and is essentially $("p").hide(1000, true);
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)
});