Reputation: 41
This is a problem from chapter 5 of Eloquent JS http://eloquentjavascript.net/05_higher_order.html
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)(12);
// → calling with 0
// → called with 0 - got false
Can someone please explain how f(arg) makes sense? I mean he is calling the argument f on another argument arg?? I am very confused.
How about the part that has return val; Why does that have to be there? When I delete it, the code still runs like it should.
Lastly, can some explain the code interpretation line by line? How does passing boolean make sense in the example?
Thank you so much
Upvotes: 0
Views: 1253
Reputation: 18734
keeping it simple:
the argument in function noisy (that acts as a wrapper) is actually just
(Boolean());
(for ref on boolean-type check this).
Furthermore you use 0
as argument of console.log in the inner function,
and as the argument of Boolean() (in var val
).
How about the part that has return val; Why does that have to be there? When I delete it, the code still runs like it should.
as long as you're using console.log you're not actually using the return statement, but if you were to do this
console.log(noisy(Boolean)(0))
you can see the return statement after the previous console.logs
Upvotes: 0
Reputation: 17238
Basics:
noisy
maps a function to another function that does the same as the original but writes input and output value ( moreprecisely their string representations) to the console.
Q1: The intention seems to be the enhancement of object constructors with a simple logging facility to show which initialization arguments produce which kind of object state. To this end, noisy
returns a function object - the original function enhanced by output to the console.
Q2: The enhanced Boolean
constructor is called without assigning its return value. Thus it makes no difference to the code whether the enhanced constructor does return a value or not.
Q3: Boolean
reveals what boolean values you get for different initialization arguments. I guess the lesson to be learned is that a numerical of 0
gets you a false
, anything else true
(the latter is informed guessing on my part, but with noisy
you have a tool to generically check that for arbitrary constructors and initialization values).
Upvotes: 1
Reputation: 707238
One simple rule to remember is that nested functions in Javascript (e.g. functions declared within other functions) have access to all the variables and arguments of their parent functions.
When noisy(f)
is called and it returns another function, that creates a closure in Javascript. That means that even though noisy(f)
has finished execution, it's arguments and any local variables are still alive and can still be used by the inner function.
So, when that inner function is then called, it has full access to the f
argument from the prior execution of its parent function. Here's an MDN reference on closures which might be worth reading and a StackOverflow answer explaining closures.
So, let's break down what your code is doing step by step:
function noisy(f) {
return function(arg) {
console.log("calling with", arg);
var val = f(arg);
console.log("called with", arg, "- got", val);
return val;
};
}
// split up noisy(Boolean)(12); into two steps
var temp = noisy(Boolean);
temp(12);
When noisy(Boolean)
is called, that returns the inner function and for any future invocation of that inner function, the f
argument is set to the Boolean
constructor function.
When that returned function is then called with it's own argument as in temp(12)
above, then it ends up executing Boolean(12)
and returning that (who's value will be true
).
Working demo: http://jsfiddle.net/jfriend00/mkn839gu/
Upvotes: 1