Yan Yi
Yan Yi

Reputation: 773

Javascript functions returning functions with parameters

There are several posts around regarding a function returning another function, like this post here. However, what happens when the returned function contains parameters?

I'm confused as to how the return function is called, and where it gets its input arguments from. This is an example taken from a d3 collision feature.

For example,

force.on("tick", function(e) {
  var q = d3.geom.quadtree(nodes), //q is a quadtree factory
      i = 0, //counter variable
      n = nodes.length; //number of nodes

  while (++i < n) 
    q.visit(collide(nodes[i]));  ///////// collide function called here /////////

); });


function collide(node) {  
  var r = node.radius + 25, 
      nx1 = node.x - r,
      nx2 = node.x + r,
      ny1 = node.y - r,
      ny2 = node.y + r;

/////// How does the below function work?
/////// Arguments quad, x1, y1, x2, y2 are not passed, 
//////  but the code works

  return function(quad, x1, y1, x2, y2) {

    if (quad.point && (quad.point !== node)) {
           //do something

        }
        return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1; 
      };
}

Upvotes: 0

Views: 3034

Answers (6)

Yan Yi
Yan Yi

Reputation: 773

Understanding javascript closures helped me gain insight into the process of a function returning a function. For those who are still confused, check out these two links which explains the concept really well:

http://www.w3schools.com/js/js_function_closures.asp

http://bost.ocks.org/mike/chart/

Upvotes: 0

Sampath Liyanage
Sampath Liyanage

Reputation: 4896

The function returned by calling collide(nodes[i]) is a callback function for the visit function. The callback function is executed inside the visit function. The visit function provides the proper parameters.

However we are not free to choose parameters here. The parameter that should be used has been predefined by the writer of visit function (The parameters for visit function are documented here).

Eg:

//arguments of calc function are a function and two numbers
    function calc(callback,x,y){
        callback(x,y);  //the callback function is called with 2 parameters here.
                        //So the 1st argument to the calc function (callback) should also accept two arguments
    }
    
    calc(function(a,b){  //calling calc function with arg1 = "function to calculate sum", arg2 = 1, arg3 = 2
       document.write(a+b);
    },1,2);

Upvotes: 2

Guffa
Guffa

Reputation: 700880

The value of the expression collide(nodes[i]) is the function returned from collide. It's not called right there, but the function is passed into the visit method.

Later on the visit will call the function created in collide, that's when the parameters are provided to the function. Something like:

visit: function(collideFunc){

  // ...

  var collided = collideFunc(quad, x1, y1, x2, y2);

  // ...

}

Upvotes: 1

Nick Tomlin
Nick Tomlin

Reputation: 29271

A returned function is simply that, a function. So the arguments to quad are defined when it is invoked. The outer function just serves as a "wrapper" for the values of nx and ny

A simpler, extremely contrived example:

function wrapName (personName) {
  return function greet (greeting) {
    return greeting + ' ' + personName;
  };
}

// greetBobWith is now the returned function, which accepts a `greeting` param
// but still has a reference to `personName`
var greetBobWith = wrapName('bob');

greetBobWith('Hello!'); // "Hello! Bob"
greetBobWith('Happy Holidays'); // "Happy holidays, Bob"

Upvotes: 4

ateich
ateich

Reputation: 520

The function collide returns an anonymous function. This anonymous function is not immediately invoked. It will only be invoked if the returned function is saved as a variable, and that variable is then invoked.

Example:

//declare quad, x1, y1, x2, y2 here or in a parent scope
var returnedFunction = collide(someNode);
var returnedBool = returnedFunction(quad, x1, y1, x2, y2);

function collide(node) {  
  var r = node.radius + 25, 
  nx1 = node.x - r,
  nx2 = node.x + r,
  ny1 = node.y - r,
  ny2 = node.y + r;

    /////// How does the below function work?
    /////// Arguments quad, x1, y1, x2, y2 are not passed, 
    //////  but the code works

      return function(quad, x1, y1, x2, y2) {

        if (quad.point && (quad.point !== node)) {
           //do something

        }
        return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1; 
      };
    }

Upvotes: 1

Seva Arkhangelskiy
Seva Arkhangelskiy

Reputation: 685

You just use this like this:

collide(node)(quad, x1, y1, x2, y2);

Upvotes: 0

Related Questions