Passing "extra" arguments to a function stored in a variable - Javascript - 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!

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

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.

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/

Related

Confused about execution context in JS

// Replace the method named m of the object o with a version that logs
// messages before and after invoking the original method.
function trace(o, m) {
// Remember original method in the closure
var original = o[m];
// Define the new method
o[m] = function() {
// Log message
console.log(new Date(), "Entering:", m);
// Invoke original
var result = original.apply(this, arguments);
// Log message
console.log(new Date(), "Exiting:", m);
return result;
};
}
Hello! The code example given above is from my coding book. It tries to illustrate a practice called “monkey-patching” using the apply function in JavaScript. I'm really confused about the nature of the line where the original function is invoked:
var result = original.apply(this, arguments); // Invoke original.
As far as I understand, the call to the original function could also be written without the help of apply(), since the thisarg is this, which is to say that the execution context remains unchanged: the original object.
The second point of confusion is where the hell the argumentsargument for apply() comes from? Yes, I know that it is an object generated at every function invocation that is used to access the function arguments - but this line is inside an anonymous function without any arguments. I don't have a clue and am grateful for any hint.
Thank you in advance!
Your first question: Why is apply necessary?
If you invoke original directly in the anonymous function, this inside original is sure to refer to global (undefined in strict mode). The anonymous function, on the other hand, is declared as a method of o, so if you invoke as o.m(), this inside the anonymous function should refer to o. Passing o to original is desired because it preserved the semantic.
In addition to binding this, apply can also convert an array of arguments to individual parameters.
function toBeCalled(x,y){
console.log('x is: '+x+" y is:"+y)
}
function x (){
toBeCalled(arguments)
toBeCalled.apply(this,arguments)
}
x('aa','bb','vv')
//x is: [object Arguments] y is:undefined
//x is: aa y is:bb
See the difference?
Second question: Where is arguments from?
In JavaScript, arguments is a built-in variable within the scope of a function. The value of arguments can only be determined when the function is invoked, it is not fixed at all.
function x (){
console.log(arguments)
}
x('aa','bb','vv')
x("ff","dd")
x(1123)
arguments is assigned a value when x is invoked, it is dynamic.

How does this function modify the other? (Higher Order Functions)

What is this code doing? How is it executing? What is x equal to?
Another useful type of higher-order function modifies the function value it is given:
function negate(func) {
return function(x) {
return !func(x);
};
}
var isNotNaN = negate(isNaN);
show(isNotNaN(NaN));
The function negate() returns a Function object that, when called, will return !func(x); for whatever argument x is passed. This Function object is being stored in the variable isNotNaN with func bound to the built-in function isNaN(). In the next line the function object stored in isNotNaN is being called with the argument NaN (a JavaScript keyword). It is at this point that x becomes bound to NaN. The return value is passed to the function show() (which isn't shown here).
For more info, read up on JavaScript functions here and consult the docs for JavaScript's Function object and function expression.
EDIT: Why do this? Sometimes it's useful to have a function that inverts a given boolean function. For instance, suppose you have some complex predicate and you want to filter an array for all elements for which the predicate is false. You can use negate() to turn the predicate function into a function that evaluates to true for those elements and just use Array.prototype.filter() to do the job. Think of it as a utility function that saves you having to write a lot of function(x) { return !predicate(x); } every time you want the inverse of a boolean-valued function. It's kind of trivial, but a lot of JS libraries (e.g., underscore.js, jquery, etc.) have a boatload of utility functions like this.
P.S. I would have written it more generally:
function negate(func) {
return function() {
return !func.apply(null, arguments);
};
}
That way, it can be used with boolean-valued functions of an arbitrary number of arguments.

Verifying my understanding of the scope chain

(Question 1)
In Flanagan's JS Definitive Guide, he defines the Function method bind() in case it's not available (wasn't available n ECMAScript 3).
It looks like this:
function bind(f, o) {
if (f.bind) return f.bind(o); // Use the bind method, if there is one
else return function() { // Otherwise, bind it like this
return f.apply(o, arguments);
};
}
He illustrates the use of it with an example (which I have modified to change the 3rd line from f.bind(o)):
function f(y) { return this.x + y; } // This function needs to be bound
var o = { x : 1 }; // An object we'll bind to
var g = bind(f, o); // Calling g(x) invokes o.f(x)
g(2) // => 3
When I first saw this, I thought "Wouldn't arguments refer to the arguments variable within the bind function we're defining? But we want the arguments property of the function we eventually apply it to, like g in the example above..."
I verified that his example did indeed work and surmised that the line return f.apply(o, arguments) isn't evaluated until var g = bind(f, o) up above. That is, I thought, when you return a function, are you just returning the source code for that function, no? Until its evaluated? So I tested this theory by trying out a slightly different version of bind:
function mybind2(f, o) {
var arguments = 6;
return function() { // Otherwise, bind it like this
return f.apply(o, arguments);
};
}
If it's simply returning tbe unevaluated function source, there's no way that it stores arguments = 6 when later evaluated, right? And after checking, I still got g(2) => 3. But then I realized -- if it's just returning unevaluated code, how is the o in return f.apply(o, arguments) getting passed?
So I decided that what must be happening is this:
The o and the arguments variables (even when arguments equals 6) are getting passed on to the function. It's just that when the function g is eventually called, the arguments variable is redefined by the interpreter to be the arguments of g (in g(2)) and hence the original value of arguments that I tried to pass on was replaced. But this implies that it was sort of storing the function as text up until then, because otherwise o and arguments would have simply been data in the program, rather than variables that could be overwritten. Is this explanation correct?
(Question 2) Earlier on the same page, he defines the following function which makes use the apply method to trace a function for debugging:
function trace(o, m) {
var original = o[m]; // Remember original method in the closure.
o[m] = function() { // Now define the new method.
console.log(new Date(), "Entering:", m); // Log message.
var result = original.apply(this, arguments); // Invoke original.
console.log(new Date(), "Exiting:", m); // Log message.
return result; // Return result.
};
}
Wouldn't the this here refer to the function that we're defining, rather than the object o? Or are those two things one and the same?
Question 1
For your first question, let's simplify the example so it's clear what being done:
function bind(func, thisArg) {
return function () {
return func.apply(thisArg, arguments);
};
}
What happens here is that a closure is created that allows the access of the original function and the value of this that is passed. The anonymous function returned will keep the original function in its scope, which ends up being like the following:
var func = function () {};
var thisArg = {};
func.apply(thisArg, [/*arguments*/]);
About your issue with arguments, that variable is implicitly defined in the scope of all functions created, so therefore the inner arguments will shadow the outer arguments, making it work as expected.
Question 2
Your problem is to your misunderstanding of the late binding of this -- this is one of the more confusing things about JavaScript to people used to more object-oriented languages that also have their own this keyword. The value of this is only set when it is called, and where it is called defines the value of this when it is called. It is simply the value of the parent object from where it is at the time the function is called, with the exception of cases where the this value is overridden.
For example, see this:
function a() {return this;};
a(); // global object;
var b = {};
b.a = a;
b.a(); // object b
If this was set when the function was defined, calling b.a would result in the global object, not the b object. Let's also simplify what happens with the second function given:
function trace(obj, property) {
var method = obj[property]; // Remember original method in the closure.
obj[property] = function () { // Now define the new method.
console.log(1); // Log message.
// Invoke original method and return its result
return original.apply(this, arguments);
};
}
What happens in this case is that the original method is stored in a closure. Assigning to the object that the method was originally in does not overwrite the method object. Just like a normal method assignment, the principles of the this value still work the same -- it will return the parent object, not the function that you've defined. If you do a simple assignment:
var obj = {};
obj.foo = function () { return this; };
obj.foo(); // obj
It does what was expected, returns the parent object at the time of calling. Placing your code in a nested function makes no difference in this regard.
Some good resources
If you'd like to learn more about writing code in JavaScript, I'd highly recommend taking a look at Fully Understanding the this Keyword by Cody Lindley -- it goes into much more detail about how the this keyword behaves in different contexts and the things you can do with it.
But this implies that it was sort of storing the function as text up until then, because otherwise o and arguments would have simply been data in the program, rather than variables that could be overwritten. Is this explanation correct?
No. this and arguments are just special variables which are implicitly set when a function is executed. They don't adhere to normal "closure rules". The function definition itself is still evaluated immediately and bind returns a function object.
You can easily verify this with:
var g = bind(f, o);
console.log(typeof g);
Here is a simpler example which doesn't involve higher order functions:
var arguments = 42;
function foo() {
console.log(arguments);
}
foo(1, 2);
I think you see that the definition of foo is evaluated like you'd expect. Yet, console.log(arguments) logs [1, 2] and not 42.
Wouldn't the this here refer to the function that we're defining, rather than the object o? Or are those two things one and the same?
this never refers to the function itself (unless you explicitly set it so). The value of this is completely determined by how the function is called. That's why this is often called "the context". The MDN documentation provides extensive information about this.
Reading material:
MDN - this
MDN - arguments

Why can we subsitute "foo" for "function (x) { return foo(x); }"

I was looking for lesser knows facts about JavaScript and I came across this piece, can anyone explain why the below code
function (x) { return foo(x); }
can be substituted with
foo
Tried to figure this out with the little knowledge of JavaScript which I had, but I didn't find the reason. Can anyone explain it?
Because
var bar1 = function (x) { return foo(x); };
var bar2 = foo;
And then
bar1(5);
bar2(5);
The first one will execute a function that will call foo(5), the second one will call foo(5) directly. Same end result.
The first is a function that takes one argument and returns whatever the result of foo with that argument is. The second is a function which takes one argument (presumably) and returns whatever the result of foo with that argument is (because it is the foo function).
The long version is just a wrapper around foo which doesn't add anything.
function(x){return foo(x);} actually is a nameless function which passes x to the function foo. The nameless function will return the result of foo(x) on the line return foo(x)
which is the same as calling foo(x) at the first place not form inside another function.
This code snippet assumes that foo is already a function in the current scope.
When you want to pass foo as a callback, you can do so directly:
function ITakeACallback(callback) {
callback(42); // and call it
}
ITakeACallback(foo);
So what you did here was pass to ITakeACallback an argument that happens to be a callable function; ITakeACallback indeed calls it.
Of course we can pass any callable function:
ITakeACallback(function(x) { return foo(x); });
This time we passed a function that accepts an argument, calls foo with that argument and returns the result. This is a roundabout way of calling foo directly, but the end result is the same.

How come func is called from a function?

function negate(func) {
return function(x) {
return !func(x);
};
}
var isNotNaN = negate(isNaN);
show(isNotNaN(NaN));
This is from a javascript book I'm reading. func is used as a function with the argument x and the negate sign preceding it. How come?
The negate function accepts a function as an argument and returns a new function it creates that, when called, will call the original function with the argument you give it, negate that function's return value, and return that negated value.
negate is used to create a function we assign to isNotNaN that, when called, will call isNaN with whatever argument you pass it and negate the result.
So when you call isNotNaN with NaN, isNotNaN calls isNaN(NaN), which returns true. isNotNaN then negates that, getting false, and returns that value.
Using functions that work on functions is a concept that everyone struggles with at first, so don't beat yourself up. But once grokked, it can be a incredibly powerful tool.
One of the staples of functional programming, that is also valid in JavaScript, is that functions are no different from other primitives, like numbers. They are, in layman's terms, things you can do stuff with. Numbers can be added, subtracted, negated, and functions can be applied, combined, convoluted.
So we can have a function called add that will add two numbers, and we can have a function combine that combines two functions, like this:
//add is a function with two parameters that are numbers
//add's result is a number
var add = function (first, second){
var result = first + second
return result;
}
//combine is a function with two parameters that are functions with one parameter
//combine's result is a function with one parameter
var combine = function (first, second){
var result = function(x) { return first(second(x)); }
return result;
}
As you can see, these two methods are more or less identical in structure. They will be called like this:
add(1, 2); //result is 3
var double = function (x) {return x*2};
var square = function (x) {return x*x};
// result is a function that returns a double of the square
var squareAndDouble = combine(double, square);
squareAndDouble(3); //result is 18
So now, let's deconstruct your example:
function negate(func) {
return function(x) {
return !func(x);
};
}
This is a function called negate that takes a parameter called func. func is a function of one parameter and it's result is a boolean. That's needed in order for func(x) to be a legal expression, and why !func(x) is legal.
In the body of negate a new function is constructed. This function does not have a name, nor does it need one, because we are constructing and returning it. Whoever calls the negate function should take care of the naming (I'll call it the result function). Essentially, this is an equivalent form of the negate function, one that I personally prefer in my code:
function negate(func) {
var result = function(x) {
return !func(x);
};
return result;
}
The result function will take a single parameter called x, and it will return the value of the !func(x) expression, essentially negating the value returned from func, i.e. if func(x) returns a truthy value, the result will be false, and vice versa.
That is why, when we call the negate function, providing it with the [isNaN][1] function (that does indeed take a single parameter, and returns a boolean value), we get back a function that does the opposite of isNaN. That (nameless) function is accommodated in the isNotNaN variable.
Now, since that variable holds a function, we can execute is just like a normal function, and isNotNaN(NaN)) will return false.
isNotNan(Nan) => !isNaN(NaN) => !true => false

Categories

Resources