M
Michael Winter
[snip]
Yes, as it explains some of the behaviour you will observe...
....but you probably can get away with ignoring some of the detail, at
least to start with.
Probably the most important bit of information is what the
activation/variable object holds:
- The formal (named) arguments for the function.
- The arguments object.
- Local variables.
- Inner functions defined with
function identifer(...) {...}
or
var identifier = function(...) {...};
In the latter case: an expression assigned to a local variable.
with the most significant being the last item: inner functions. Why? Well,
consider this (admittedly bad) example:
function MyObject() {
/* Define an inner function. Will become
* a property of the activation object.
*/
function myInner() {
return this;
}
/* Define method for the new object. Will
* become a property of that object.
*/
this.myMethod = function() {
return this;
};
/* A test method. It will return an
* object containing two properties:
*
* inner - the result of a call to myInner
* outer - the result of a call to myMethod
*/
this.test = function() {
return {
inner : myInner(),
outer : this.myMethod()
};
};
}
var myObject = new MyObject(),
result = myObject.test();
alert(result.outer == myObject); // true
alert(result.inner == myObject); // false
Notice that although both functions return the this operator, only the
method, myMethod, actually returns a reference to the object, myObject.
The reason is when a function is called, the caller provides the value of
the this operator based on *how* that function is called.
If a method is called as a method:
obj.method()
then the this operator will refer to object (obj, above). However, if a
method is called as a property of the global object (a global function),
or as a property of an activation object (an inner function), then the
this operator will refer to the global object. So, if you go back to the
last line in the example and change it to:
alert(result.inner == window); // or == this);
the message will show true.
I hope that made sense. It seemed a little awkward to explain.
The final point to remember about the activation object is that when a
closure is formed, whether it refers to local variables or functions, or
not, the entire activation object (in fact the entire scope chain) and all
of its properties will be kept in memory. This can be important because if
these properties reference other objects, those objects won't be
considered "collectable" by the garbage collector so you'll keep them in
memory, too. Therefore, it's a good idea to destroy any references you
won't need:
ref = null;
This is also covered in the article, but I thought I'd give it a quick
mention here.
[snip]
If I did a poor job of explaining anything above, even if you understood
my point, do tell me. I'll either have another crack at it (if you want me
to), or I'll try to remember for any future explanations.
Mike
Reading the article below, (linked to from Cornford's site) I'm curious
if there is ever a time when a Javascript programmer needs to know
anything about the Activation object? Has there ever been a time when
you yourself have needed to use your knowledge of it in any way?
Yes, as it explains some of the behaviour you will observe...
Can I ignore this bit?
....but you probably can get away with ignoring some of the detail, at
least to start with.
Probably the most important bit of information is what the
activation/variable object holds:
- The formal (named) arguments for the function.
- The arguments object.
- Local variables.
- Inner functions defined with
function identifer(...) {...}
or
var identifier = function(...) {...};
In the latter case: an expression assigned to a local variable.
with the most significant being the last item: inner functions. Why? Well,
consider this (admittedly bad) example:
function MyObject() {
/* Define an inner function. Will become
* a property of the activation object.
*/
function myInner() {
return this;
}
/* Define method for the new object. Will
* become a property of that object.
*/
this.myMethod = function() {
return this;
};
/* A test method. It will return an
* object containing two properties:
*
* inner - the result of a call to myInner
* outer - the result of a call to myMethod
*/
this.test = function() {
return {
inner : myInner(),
outer : this.myMethod()
};
};
}
var myObject = new MyObject(),
result = myObject.test();
alert(result.outer == myObject); // true
alert(result.inner == myObject); // false
Notice that although both functions return the this operator, only the
method, myMethod, actually returns a reference to the object, myObject.
The reason is when a function is called, the caller provides the value of
the this operator based on *how* that function is called.
If a method is called as a method:
obj.method()
then the this operator will refer to object (obj, above). However, if a
method is called as a property of the global object (a global function),
or as a property of an activation object (an inner function), then the
this operator will refer to the global object. So, if you go back to the
last line in the example and change it to:
alert(result.inner == window); // or == this);
the message will show true.
I hope that made sense. It seemed a little awkward to explain.
The final point to remember about the activation object is that when a
closure is formed, whether it refers to local variables or functions, or
not, the entire activation object (in fact the entire scope chain) and all
of its properties will be kept in memory. This can be important because if
these properties reference other objects, those objects won't be
considered "collectable" by the garbage collector so you'll keep them in
memory, too. Therefore, it's a good idea to destroy any references you
won't need:
ref = null;
This is also covered in the article, but I thought I'd give it a quick
mention here.
[snip]
If I did a poor job of explaining anything above, even if you understood
my point, do tell me. I'll either have another crack at it (if you want me
to), or I'll try to remember for any future explanations.
Mike