After correcting the issues in the code (missing semicolons or too many) there appear to be a few closures that get created throughout the script's execution.
First:
function invoker (NAME, METHOD) {
return function(target) { // In the example this is rev
// Begin Scope1 (closure)
var targetMethod = target[NAME]; // NAME is trapped here in Scope1 (defined outside of this function) when the function is executed!
var args = _.rest(arguments);
return function() { //
// Begin Scope2 (closure)
return targetMethod.apply(target, args); // target and args are trapped here in Scope2 (defined in Scope1's function) when the function is executed!
};
};
}
The invoker does nothing until it is called and the first closure (Scope1's that is) does not get created until invoker is actually invoked:
var rev = invoker('reverse', Array.prototype.reverse);
After rev has been initialized by invoker, it has become a variable that contains a function that accepts a single named argument (called target) that when called will look for a function called NAME (in this case 'reverse') on whatever object target is.
When rev is actually called it also returns a function that, when called, will call the target method (reverse in this case) on target (the array passed in). But rev hasn't been called until the next line is run:
var result= _.map([[1,2,3]], rev);
Here is what is happening here: _.map's purpose is to take a list of items and apply a function to each item in this list. The final result will be a new array with the transformed values in it. The line above passes to _.map a list with exactly one item in it; an array. It also passes to _.map a function to transform each item in that list; in this case rev.
So _.map is called and it calls rev on the only item in the list, our [1,2,3] array. The function rev has the effect of returning yet another function that, when called, will remember NAME, target and args. This function now resides inside the first element of the array variable 'result'.
Now for your questions:
The output should be:
[[3,2,1]]
but i cannot prove it.
In the test code there is no output, only a final variable called result. What I think you are looking for is that somewhere in the end there should be a reversed array. You can verify that the original array has been reversed with the following after the call to initialize result:
alert(result[0]().join());
Why is args:
0,1,2,3
args is really a red herring here; _.map passes 3 arguments to its iterator function. The current value (in this case the array [1,2,3], the key or index (in this case 0) and the original list itself. When _.rest is called on arguments, it slices off the first item leaving us with an array containing 0 and [[1,2,3]]. When reverse is called on this array (args) it ends up returning an array that looks like [1,2,3,0] which is these two items reversed. My tests never showed 0,1,2,3. Why is args a red herring here? Because when reverse is called reverse doesn't take any arguments and so args is ignored. If this was a different function on a different object you would probably encounter issues because of the call to _.rest.
Why is console.log(arguments):
[object Arguments]
Because you are basically calling toString() which will print the object's type.
How to print out the result, to see [[3,2,1]]. When I print out
"result", I get:
[object Object]
You can use:
console.log(result[0]().join());
UPDATE: Here is the jsbin link with working code: http://jsbin.com/aYECIDo/5/edit?html,css,js,output
METHODdoesn't seem to be used anywhere in your code. It wouldn't make sense either, since the first argument already seems to be used to the extract the method that should be invoked. You probably should read about theargumentsobject: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/….