Understanding Javascript Callbacks And Formal Parameters
Solution 1:
anatomy first
JavaScript can be confusing because there's a variety of ways to express functions – for all intents and purposes, the functions below can be considered identical
// named functionfunctionmyfunc (param1, param2) {
return returnValue
}
// function literal syntaxconst myfunc = function (param1, param2) {
return returnValue
}
// arrow function with explicit return (note { ... })constmyfunc = (param1, param2) => {
return returnValue
}
// arrow function with implicit returnconstmyfunc = (param1, param2) => returnValue
Above you can see functions have parameters – below, you'll see function calls have arguments
// call myfunc with 0 arguments
myfunc ()
// call myfunc with 1 argument
myfunc (arg1)
// call myfunc with 2 arguments
myfunc (arg1, arg2)
they're just functions
a) Which function calls the
callbackfunction?
So wherever we see a function supplied with arguments, we know we're dealing with a call – to answer A, just look to see the enclosing function of the call
functionsomeFunc (param1, param2) {
// do somethingconst result = param1 * 2// param2 called with result
param2 (result)
}
Hey look, param2 (result)
is a function call. We look to the enclosing function to see that someFunc
is the one that called it
b) Which function supplies the actual parameter of the
callbackfunction?
Well that sounds silly doesn't it? That's like asking "Who does Bobby's name belong to?" Bobby, of course. You probably meant to ask, which function supplies the argument – in which case, that answer would be someFunc
– it supplies result
argument
c) Why give a
callbackfunction parameters?
This is instantly answered as soon as we stop calling functions a "callback" – a callback is a function, not the other way around. We give functions parameters so that we can affect the behaviour of the function
d) What are you giving up when you have a
n 'asynchronous'call without supplying acallbackfunction?
Don't worry about asynchronous vs synchronous function calls; there's just function calls. Function calls happen at different times, but at some point the call will evaluate the function's body with the supplied arguments and return the result; undefined
or otherwise
In most cases, you "give up" the ability to do anything useful with the result – look at our function again: if we don't supply param2
, result
just goes unused
functionsomeFunc (param1, param2) {
// do somethingconst result = param1 * 2// param2 called with result
param2 (result)
}
But of course that's not always true. To understand why, we have to first fix your question tho
d) What are you giving up when you have a call without supplying an argument?
Kind of a silly question right? But it's no different for callbacks functions – they're just ordinary values like anything else
Below we have someFunc
with a function parameter naïvely named callback
– someFunc
produces a "valid" result with or without the callback specified – so the answer for D is: you give up nothing, explicitly
functionsomeFunc (x, callback) {
if (callback)
return callback (x * 10)
elsereturn x * 2
}
// with the callback
someFunc (5, console.log) // 50// withoutconsole.log (someFunc (5)) // 10
e) Can the called function in a
n asynchronouscall ever containsynchronouscalls?
Yes, functions can call other functions. This idea of "sync" and "async" in javascript is historically a mental construct and therefore a lot of people have differing opinions on it. To add to this, newer versions of JS have an async
keyword which will implicitly convert your function's return value to a Promise
To further illustrate this, observe doSomething
– is it "asynchronous" or is it "synchronous" ?
// "synchronous" functionconstmult = (x,y) => x * y
// "synchronous" functionconstdouble = (x) => mult (x, 2)
// function with "callback"constdoSomething = (x, callback) =>
callback (x)
// is it async ?
doSomething (5, x => {
const result = double (x)
console.log (result) // 10
})
// or is it sync ?console.log (doSomething (5, double)) // 10
where to go from here
There is actually a more uniform understanding of asynchrony in JavaScript now – especially with the standardization and widespread adoption of Promises. ES2017 adds new control syntax async
/await
too. "Callback" patterns are mostly dead – even the dominant force that was Node with it's popular "Node-style (error first) callbacks" has conceded to support Promised-based interfaces for asynchronous programs
That's not to say higher-order functions (functions with function parameters, or functions that return other functions) are without their uses – you'll see the functional programmers waving their Array.prototype.map
and Array.prototype.reduce
all over the place
But this idea of "callbacks" can be extremely powerful – especially when represented in ways other than we've seen above. Continuation-passing style is a style where we pass a continuation (another fancy name for a function) that serves as the "next" step of our program. I've written a lot on the subject of continuations. If you find this stuff interesting, keep reading. You'll learn amazing things about the call stack, principles of recursion, functors, monads, all sorts of things !
constcont = x => k => k (x)
constdouble = x => cont (x * 2)
consttriple = x => cont (x * 3)
double (2) (console.log) // 4
double (2) (double) (console.log) // 8
double (2) (double) (double) (console.log) // 16
double (2) (double) (double) (double) (console.log) // 32
double (2) (triple) (console.log) // 12
Post a Comment for "Understanding Javascript Callbacks And Formal Parameters"