Daniel said:
I think I get it now... [This is how I get it:] At the time
of declaring "var MyObject = function(){...", scriptly speaking
(hey, nice phrase
, the function is just a function like any
other function. The fact that it contains a constructor and that
it's gonna "morph" to functionally "become" this constructor is
yet unknown, since at this time all the function does is occupy
memory.
It is getting there but you seem to be seeing a bit too much 'magic'.
"morph" and "become" imply some sort of transformation of the various
objects involved in this process. In practice none of the objects
involved ever change.
I will start by trying to clarify the role of the on-off function call.
Consider:-
function exampleFunction(){
return new Array();
}
var anObject = exampleFunction();
- In this case a function is defined separately and then called, its
return value (a new Array) assigned to the global variable - anObject -.
The assignment of a value to the - anObject - variable is the very last
operation in the process and - anObject - does not know anything abut
what is happening on the right hand side of the assignment operator (-
= -). Now consider:-
var anObject = funciton(){
return new Array();
}();
^- It is the pair of brackets after the function expression that
execute it (in-line and once only).
- The function has changed from a function definition and is now a
function expression but the only consequence of that is that the
resulting function object is now anonymous (as it now has no identifier
by which it can be referenced) and the function object itself is not
created prior to the execution of this line of code. Apart from that
nothing has changed. From the left hand side of the assignment
operator - anObject - sees no difference at all, it ends up holding a
reference to an Array. On the right hand side of the assignment the
process has not changed; a function is being executed and the value that
it returns (the reference to a new Array object) is the result of the
operation and is assigned to the left hand side of the - = -. The
difference is that the code that defines the function is now in-line but
the nature of the objects involved is identical.
The one-off function in my example class script is just a normal
function object, it is executed and it returns a value. That value just
happens to be a reference to a function object.
Function objects do not recognise a distinction between constructor
functions and non-constructors. That distinction is only in the mind of
the code's author, which will influence how they use the function. If
the - new - keyword is used when a function is invoked the interpreter
will internally create an Object and make a reference to that object be
the - this - value during the subsequent execution of the function, and
then, in the absence of any other - return - statements, it will return
that object. If the function is invoked without the - new - keyword
the - this - reference will be determined by the context in which the
function is called and the return value is undefined if no explicit -
return - statement is provided.
function exampleFunction2(){
var a = 'anyThing';
//but no explicit return value.
}
alert( typeof exampleFunction2 ); //not executed and alerts 'function'
alert( typeof exampleFunction2() ); //executed but alerts 'undefined'
alert( typeof new exampleFunction2() ); //called as a constructor and
// alerts 'object'
Obviously invoking a function that has a - return - value with the -
new - keyword is pointless as the Object that is internally constructed
and used as the - this - value is just wasted and gets thrown away at
the end of the function invocation.
function exampleFunction3(){
var a = 'anyThing';
return a;
}
alert( typeof exampleFunction3() ); //executed and alerts 'string'
alert( typeof new exampleFunction3() ); //called as a constructor but
// alerts 'string'
//The internally created object is thrown away.
So a constructor is just a normal function object, it is the use of
the - new - keyword that constructs a new Object and the way that the
function body is written that makes it suitable to be a constructor.
Then, we have the first (and last) execution of *that particular*
function when we (if we read it literally (and I still do that a
lot
) try to instantiate it *as if it were* an object constructor.
Javascript says, "you want an instance of that object?" and checks
to see what "that object" is, i.e. the function is evaluated.
The one-off execution of the outer function does not involve the use of
the - new - keyword so no attempt is made to create an instance of any
object at this point. Just the execution of a function that has a return
value, that happens to be a reference to a function object.
The function starts its work and ends up returning its
inner constructor function, but not just that, because if it
did, you'd end up using the "new" keyword on an object constructor
*function* object, and not an object *constructor*.
JavaScript only has one type of function object, it is the code within
the returned inner function body that makes it appropriate to use it as
a constructor.
No, it uses that one-off thingie to evaluate the function
object to become the object constructor, so that the
assignment argument becomes valid,
The one-off thingie returns a reference to a function object. Nothing
"becomes", the function object referred to is, was and always will be a
function object. It is just a function object that was written to be a
constructor (it contains appropriate code).
and the "test" var becomes an instance of what the MyObject is
*now*, which is the object constructor inside the function is
was before.
There is no "before" for the MyObject variable. The entire right hand
side of the assignment expression has finished prior to MyObject being
assigned the result (the reference to the inner function that can be
used as an object constructor).
I actually understand it as if the constructor inside "MyObject"
effectively hijacks the variable name and reference to "MyObject",
cutting its connection to the public while retaining access to its
properties and methods for its own members (the closure).
There is no "hijacking" of MyObject as it has never been aware of the
execution of the one-off function on the right hand side of the
assignment. It only ever holds a reference to one object, the function
object returned by the one-off function call.
Now, at every new MyObject instantiation, using "new" on "MyObject"
doesn't execute the orginial function (that reference is lost), but
reaches straight inside it to the object constructor class that
provides all its instances with access to its outer function's
resources. (And it can keep track of the counter since
incrementCounter is now an outer function to itself
I would not have put the word "class" at the end of "the object
constructor class" as it seems to confuse the relationship between
classes and their instances. The constructor, when invoked with the -
new -keyword, returns an instance of a Class. So, every new MyObject
instantiation, using "new" on "MyObject" reaches straight inside the
closure formed when the one-off function was executed to the Class
constructor and thus provides all its instances with access to the other
inner functions and variables of the outer function.
You are getting closer and are not that far off now.
..., since English isn't exactly my mother tongue, ...
<snip>
You should not worry about that. To date you have managed to communicate
in English better than many native English speakers that I have known,
and having to read a sentence about the details of a programming
language more than a couple of times before grasping it is something
that I have plenty of experience of.
It also won't take you a fraction of a second to guess how good my
Danish is (hint: zero).
Richard.