Bluey
Bluey

Reputation: 53

Passing "extra" arguments to a function stored in a variable - Javascript

I'm new to Javascript, I'm self-teaching, so this might be an obvious area, but no matter how I phrase the question I can't really seem to get my head around this one issue. At the moment I'm reading through http://eloquentjavascript.net/chapter6.html (which was on mozilla's MDN). I've come across this a couple of times now, I would just like a simple break down if possible.

function negate(func) {
  return function(x) {
    return !func(x);
  };
}
var isNotNaN = negate(isNaN);
show(isNotNaN(NaN));

I don't understand how at the very last step isNotNaN (a variable) is passing an 'extra argument' (NaN) to the function stored in isNotNaN (negate(isNaN). "show(isNotNaN(NaN));"

I came across this same problem when the concept of enclosure was trying to be explained. But I don't get where this argument "NaN" is going in the above function, as it seems to me like the last statement ends up something like:

show(negate(isNaN, NaN));

I would be happy to provide more details. This concept of passing an extra argument to a variable already holding a function with an argument confuses the hell out of me!

Upvotes: 1

Views: 905

Answers (3)

Andy E
Andy E

Reputation: 344567

There's no "extra" argument. The negate() function itself returns a function defined as a function expression, which can then be called with any number of original (not extra) arguments passed. A closure is used for the returned function to keep a reference to isNaN as func.

var isNotNaN = negate(isNaN);

At this point, isNotNaN contains a reference to the function

function(x) {
    return !func(x);
};

Again, func here refers to the isNaN argument passed to the negate function, which is the immediate parent in the scope chain. The result is similar, but not the same as

var isNotNaN = function (x) {
    return !isNaN(x);
};

The reason it is not the same is, if we change the value of isNaN, the behaviour of this function will change. In the example you posted, however, the value of func is equal to the original value of isNaN and cannot be changed by anything outside of its scope thanks to the closure.

Essentially, you can pass in any function and get a new function that returns the negated result of the original function in return. For example:

var isNotArray = negate(Array.isArray);
isNotArray(12);
//-> true

Upvotes: 3

Johan
Johan

Reputation: 35194

Perhaps this example can clear some things out for you regarding closures:

function foo(x){

    function bar(y){
        return x+y;
    }

    return bar;
}

var fooRef = foo(1); // fooRef references foo() with x set to 1

console.log(fooRef(2), foo(1)(2)); // 3, 3

http://jsfiddle.net/ePwy8/

Upvotes: 0

vdubus
vdubus

Reputation: 456

In fact, negate(isNaN) simply return a function to the variable isNotNaN. This function take a parameter (named x in your case), then execute the function isNaN on the parameter before negating it and returning the result.

Upvotes: 0

Related Questions