1

I'm having a hard time understanding exactly what is happening in the code here and how this script is changing other functions.

This is taken from eloquentjavascript.net chapter 5 on higher order functions.

function noisy(f) {
  return function(arg) {
    console.log("calling with", arg);
    var val = f(arg);
    console.log("called with", arg, "- got", val);
    return val;
  };
}
noisy(Boolean)(0);

// → calling with 0
// → called with 0 - got false
  • 1
    The code edit was Eric. I was more concerned about the "Can you explain higher order functions to me" being something that people might answer without trying to answer the bit about this code... and that question is a bit on the broad side. – user40980 Jan 28 '16 at 23:04
7

Since it's not clear what part of this is confusing you, let's take this step by step.

1) Boolean is a function. In this case, it takes one argument, and returns either true or false depending on whether the argument was truthy or falsy. So if it helps, you could replace Boolean with function(x) { return !!x; } and get roughly the same behavior.

2) This line:

noisy(Boolean)(0);

is interchangeable with:

var func = noisy(Boolean);
func(0);

Assuming the identifier func is not used anywhere else in your code.

3) noisy(Boolean) obviously calls the noisy function, with f set to the function Boolean. The call to noisy then returns a function like this:

function(arg) {
    console.log("calling with", arg);
    var val = Boolean(arg);
    console.log("called with", arg, "- got", val);
    return val;
}

4) The function returned by noisy is then called with 0 as the value of arg. That effectively does the following:

console.log("calling with", 0);
var val = Boolean(0);
console.log("called with", 0, "- got", val);
return val;

5) If #1 made sense, then it shouldn't be surprising that Boolean(0) evaluates to false. From there it should be obvious why the output is what it is.

3

Consider the line noisy(Boolean)(0);

Boolean is a javascript function that takes an optional parameter.

The first part of the line in question, noisy(Boolean)(0); , takes the Boolean function, and passes it into the noisy function as a parameter.

The noisy function returns a (new) function that takes a parameter (return function(arg)).

The second half of the line in question, noisy(Boolean)(0); , takes the return value of noisy (a function that takes a parameter) and invokes it with the parameter 0;

The function that noisy returns will do a couple of console writes, but in between will invoke the function that was originally sent into noisy (the Boolean function, called f) with the parameter (0, called arg), and then capture and pass on Boolean's return value through the variable val.


I think that it is misleading to say that this is changing any function. This code is creating a new function that wraps an existing function with extra functionality.

In this case, this code simply wraps the Boolean function with a couple of console.log calls, but the Boolean function remains unchanged.

2

First keep in mind that this code is not changing/mutating the passed in function. Passing in the Boolean constructor is a bit odd and may lead to some confusion so lets remove it and break it down more for clarity.

var noisyIsArray = noisy(Array.isArray);

noisyIsArray([]);
> calling with []
> called with [] - got true
true

noisyIsArray(2);
> calling with 2
> called with 2 - got false
false

In its simplest form noisy can take any function and return a function. Inside of the function that it returns it calls the function that it takes in. Before calling it, it just logs the arguments and returns value.

In the above case Array.isArray is the function that we are passing into noisy and var noisyIsArray is a function as well (the function returned by noisy).

Here is a very simple (and not robust) higher order function :

function logSomething() {
    console.log('something');
}

function invoke(fn) {
    return function() {
        fn();
    }
}

var invokeLogSomething = invoke(logSomething);

invokeLogSomething();
>something

All invoke does is take a function and return a function that calls the passed in function. There is nothing special about the fn function call is just like any other one.

0

This JavaScript snipped implements and show two particular points :

  • a Closure: that is a special habitability of some languages to capture a variable into another context.
  • the fact that in Javascript any variable is an object (a string, an integer, a function, a class, ...)

This snipped finally provide a function noisy() that can run another function with extra debug information.

Let's see step by step :

function noisy(f)

This function takes a function as argument. No problem: with JS a function is also an object.

return function(arg) {

The noisy() function returns another function without a name (an anonymous function). Still no problem: with JS a function is also an object.

You can notice that the argument f is not use anywhere in function noisy(). It is used only in the anonymous function. If you don't know about Closure you should think that argument f is superfluous in noisy(), and that it should raise an error in the anonymous function since it is not declared a local nor global. In fact, because of the Closure feature, argument f is actually passed to the anonymous function as a variable, and this variable is closed in the context of the function. That is the variable f is no more linked to argument f after the anonymous function is actually created.

The other part of the functions is quite simple : the anonymous function run the function f and log some debug info in the console, before and after.

The last part of the snipped is a test of the function.

noisy(Boolean)(0);

It is tested with the class Boolean. This is a strange choice for a test, but is works because in JS a class is an object. Calling a class as a function simply creates a new object of that type. Another well know example is Date('2016-01-01').

  • In Javascript, almost everything is a function, not an object. – Adam Zuckerman Jan 28 '16 at 23:39
  • 1
    @AdamZuckerman A function is always an object (it has methods call() and apply()). While a string is not, an integer is not, .... try ("hello")() and you will have an error TypeError: "hello" is not a function. – Skrol29 Jan 28 '16 at 23:54
  • 1
    In javascript, Boolean is an object of type 'function', but it's not a class. – Eric King Jan 29 '16 at 0:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.