3

In going through some exercises about functional programming, and returning a closure, came across this example, and cannot figure out how it works:

function invoker (NAME, METHOD) {
  return function(target) { 
    var targetMethod = target[NAME];
    var args = _.rest(arguments);
    return function() { return targetMethod.apply(target, args);});
  };
};

The test:

var rev = invoker('reverse', Array.prototype.reverse);
var result= _.map([[1,2,3]], rev);

The output should be:

[[3,2,1]]

but i cannot prove it.

Specific questions: Why is args:

0,1,2,3

Why is console.log(arguments):

[object Arguments]

How to print out the result, to see [[3,2,1]]. When I print out "result", I get:

[object Object]
1
  • 1
    Just FYI, METHOD doesn'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 the arguments object: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…. Commented Dec 3, 2013 at 23:44

2 Answers 2

1

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

Sign up to request clarification or add additional context in comments.

7 Comments

I added this to see if I could see the reversed array: console.log('result: ' + result[0]().join()); but it doesn't work
Everytime you call result[0]() it will reverse again. I'm guessing you are calling it twice? Here is my code at jsbin: jsbin.com/aYECIDo/5/edit?html,css,js,output
@Mike...did this script work for you, I think I verified that the result is empty, I used JSON.stringify(result[0]); ?
I added the link to my jsbin to the end of my post.
I'll see why mine is not working, thx again for the time and effort, i appreciate it
|
1

Use console.log and a modern browser with actual development tools.. like chrome, or firefox+firebug. Then you should be able to see in the console the result. Or, when you print it out in HTML, serialize it using JSON.stringify. Example: document.write(JSON.stringify(result)).

That should write out a JSON representation of what you're seeing.

Regarding the [1,2,3] look at the .apply function in the MDN.

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply

Apply takes a first argument of scope, and an array of arguments to cause the function to be called with.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.