Reputation: 29519
I want to understand about variables, that has been used in returning function. This is example code
Prototype = {}
Prototype.F =
{
bind: function()
{
var args = arguments, __method = args.shift(), object = args.shift();
return function()
{
return __method.apply(object, args.concat(arguments));
}
}
}
function ObjectA()
{
...
this.addListener = Prototype.F.bind(this.eventSource.addListener,
this.eventSource);
...
}
var a = ObjectA();
a.addListener(this); // assuming 'this' here will point to some window object
As I understand the returning function in bind() is not evaluated until it's called in the last line. It's ok to accept. So addListener will hold a function body containing 'apply'.
But what I don't understand, when addListener is called, what kind of parameters it is going to have? particularly _method and args will always be uninitialized?
Upvotes: 0
Views: 201
Reputation: 11238
in the scope of a function, arguments
is an array-like object which contains the values provided when the function is called, whether or not the function definition has parameters defined.
so for this call:
Prototype.F.bind(this.eventSource.addListener, this.eventSource);
which leads to this:
var args = arguments, __method = args.shift(), object = args.shift();
arguments
contains 2 items: whatever this.eventSource.addListener
and this.eventSource
point to when the function is called. that collection of 2 items is copied to args, and then the items are moved from the colleciton to __method
and object
.
since the call bind
actually generates another function, the arguments
instance in the new function will be different- it'll have the parameters provided at the time of that call. the original arguments
from the call to bind
are saved in args
and combined with arguments
from the later function call.
Upvotes: 0
Reputation: 1075587
The function that bind
returns is a closure over the arguments to the bind
function, and so the __method
argument will be the first argument to bind
(in your example call, that will be the this.eventSource.addListener
function).
Closures are basically functions that have data bound into them intrinsically. Here's a simpler example:
function makeAlert(msg) {
return function() {
alert(msg);
}
}
var myalert = makeAlert("Hi there!");
myalert(); // Alerts "Hi there!"
The function returned by makeAlert
"closes over" (retains access to) the things in scope within the makeAlert
function call that created it, including the msg
argument. That's why when we call the function later, it still has msg
even though the call to makeAlert
has long since completed. More about closures here.
A key thing to remember about closures is that they retain access to everything that's in scope where they're defined, not just the things they they're obviously using. So for instance:
function init() {
var data;
data = /* ...build some really big array of data...*/;
document.getElementById('foo').onclick = function() {
this.style.display = "none";
};
}
Even though the event handler has nothing to do with the big data array, it keeps a reference to it, and so keeps that data in memory after the call to init
has completed. This is because the link that it has is to a behind-the-scenes object (loosely called the "variable object") that is a container for all of the arguments and local variables in scope where it's defined. (In this particular case, if you don't need all that data, just set data
to undefined
at the end. The event handler will still have a reference to data
, but that reference isn't holding the array anymore, so the array's memory can be reclaimed.)
Upvotes: 1
Reputation: 25157
_method and args will be always initialized, because you are defining them when you first call
this.addListener = Prototype.F.bind(this.eventSource.addListener, this.eventSource);
There, you'll get that _method will be that this.eventSource.addListener
, and args will be those both arguments.
Upvotes: 0