Reputation: 773
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
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
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
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
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
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
Reputation: 685
You just use this like this:
collide(node)(quad, x1, y1, x2, y2);
Upvotes: 0