Understanding javascript callbacks and formal para

2019-07-30 14:48发布

Here is an example of a question that I am slightly confused about.

Function one calls function two, and passes it a callback that has a formal parameter.

My answer:

function one(){
function two(callback) 
{callback (param1, param2)}
}

please correct, if this is wrong

Questions:

a) Which function calls the callback?

function two calls the callback function

b) Which function supplies the actual parameter of the callback?

unsure

c) Why give a callback parameters?

unsure

d) What are you giving up when you have an 'asynchronous' call without supplying a callback?

unsure

e) Can the called function in an asynchronous call ever contain synchronous calls?

unsure

1条回答
男人必须洒脱
2楼-- · 2019-07-30 15:25

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 function
function myfunc (param1, param2) {
  return returnValue
}

// function literal syntax
const myfunc = function (param1, param2) {
  return returnValue
}

// arrow function with explicit return (note { ... })
const myfunc = (param1, param2) => {
  return returnValue
}

// arrow function with implicit return
const myfunc = (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 callback function?

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

function someFunc (param1, param2) {
  // do something
  const 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 callback function?

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 callback function 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 an 'asynchronous' call without supplying a callback function?

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

function someFunc (param1, param2) {
  // do something
  const 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 callbacksomeFunc produces a "valid" result with or without the callback specified – so the answer for D is: you give up nothing, explicitly

function someFunc (x, callback) {
  if (callback)
    return callback (x * 10)
  else
    return x * 2
}

// with the callback
someFunc (5, console.log) // 50

// without
console.log (someFunc (5)) // 10

e) Can the called function in an asynchronous call ever contain synchronous calls?

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" function
const mult = (x,y) => x * y

// "synchronous" function
const double = (x) => mult (x, 2)
  
// function with "callback"
const doSomething = (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 !

const cont = x => k => k (x)

const double = x => cont (x * 2)

const triple = 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

查看更多
登录 后发表回答