Hello,
Sam Kong said:
I got recently intrigued with JavaScript's prototype-based
object-orientation.
However, I still don't understand the mechanism clearly.
[Q1]
What's the difference between the following two?
(1)
function C(){
this.name = "Unknown"
}
(2)
function C(){
}
C.prototype.name = "Unknown"
when you will instanciate an object
foobar = new C();
with (1) the property "name" will be explicitly copied into the instance
with (2) the property "name" will be inherited by delegation
meaning the instance "foobar" does not have a copy of the property "name"
but can access it following the prototype chain
if you create 10 instances
wiht (1) you have 10 different "name" properties
with (2) the "name" property is shared by every instances
[Q2]
There's no notion of Class in JavaScript and everything is an object.
no but you have notion of constructors which can "emulate" classes
cf ECMA-262 4.2.1
"ECMAScript does not contain proper classes such as those in C++, Smalltalk,
or Java, but rather, supports constructors which create objects by executing
code that allocates storage for the objects and initialises all or part of
them by assigning initial values to their properties. All constructors are
objects, but not all objects are constructors. Each constructor has a
Prototype property that is used to implement prototype-based inheritance and
shared properties. Objects are created by using constructors in new
expressions; for example, new String("A String") creates a new String
object. Invoking a constructor without using new has consequences that
depend on the constructor. For example, String("A String") produces a
primitive string, not an object."
see
http://www.ecma-international.org/publications/standards/Ecma-262.htm
How many objects are created in the following code including the
objects implicitly created in the behind?
function C(){
}
function D(){
}
D.prototype = new C
var obj = new D
for the segment of code above
4 if you consider the creation of a prototype property as
not-an-object-instanciation
function are objects, once you declare one you create an object
when you use the "new" keyword you instanciate an object
5 if you consider that the creation of the prototype property is an object
instanciation
function C in the behind automatically define a "prototype" property
which is equivalent to
C.prototype = Function.prototype;
see ECMA-262 13.2 Creating Function Object
"
[...]
4. Set the [[Prototype]] property of F to the original Function prototype
object as specified in section 15.3.3.1.
[...]
9. Create a new object as would be constructed by the expression new
Object().
10. Set the constructor property of Result(9) to F. This property is given
attributes { DontEnum }.
11. Set the prototype property of F to Result(9). This property is given
attributes as specified in section 15.3.5.2.
[...]
NOTE A prototype property is automatically created for every function,
to allow for the possibility that the function will be used as a
constructor.
"
and
just writing
function C() {
}
DO create
C.prototype = new Object();
[Q3]
I saw some codes like "this.base = SomeClass".
When is it needed?
Is it different from ClassName.prototype = new ParentClassName?
could you provide some code constructs ?
I will try to "guess"...
usually when you want to inherit a constructor
you can do
function A(){
}
function B(){
}
B.prototype = new A();
but doing that you override the original B "prototype" property
and so you override also the "constructor" property contained in "prototype"
foo = new A();
//foo.constructor == A
bar = new B();
//bar.constructor == A, and not B
to correct this behaviour you can reassign the constructor property after
overriding the prototype
function B(){
}
B.prototype = new A();
B.prototype.constructor = B;
so now when you instanciate an objet with the B constructor function
bar = new B();
//bar.constructor == B
for the "this.base = SomeClass".
I suppose you seen that in that context to emulate superClass constructor
call
function A( x ){
this.x = x;
}
function B( x, y ){
this.base = A;
this.base( x );
this.y = y;
}
B.prototype = new A();
in this case "this.base" allow to execute A constructor inside the B
constructor
but with the B function scope, so the "x" is created in the context of B and
not A
alternatively you can also do that
function B( x, y ){
A.call( this, x ); // equivalent to "super( x )"
this.y = y;
}
B.prototype = new A();
[Q4]
What's the difference between prototype and __proto__?
first let's define a context
function A(){
}
foobar = new A();
in the context of "foobar"
foobar.prototype does NOT exist
foobar.constructor is a pointer to A constructor function (hence the name)
foobar.__proto__ is a pointer to A.prototype object
in the context of "A"
A.prototype is an instancied object
(see above "9. Create a new object as would be constructed by the expression
new Object().")
here what we obtain with JSDB (
www.jsdb.org)
------------------------------------
function A()
{
}
foobar = new A();
println( foobar.constructor === A ); //true
println( foobar.prototype === undefined ); //true
println( foobar.__proto__ === A.prototype ); //true
println( foobar.constructor.prototype === A.prototype ); //true
println( "--" );
println( (A.prototype).constructor === A ); //true
println( (A.prototype).prototype === undefined ); //true
println( (A.prototype).__proto__ === Object.prototype ); //true
println( (A.prototype).constructor.prototype === A.prototype ); //true
println( "--" );
println( A.constructor === Function ); //true
println( A.prototype !== undefined ); //true
println( A.__proto__ === Function.prototype ); //true
println( A.constructor.prototype === Function.prototype ); //true
println( "--" );
println( foobar instanceof A ); //true
println( A instanceof Function ); //true
println( A.prototype instanceof Object ); //true
------------------------------------
there are 3 different objects
A is a Function object
A.prototype is an Object object
foobar is an A object
each object as its own constructor property pointing to the function who
created it
each objects as its own __proto__ property pointing to the
function.prototype who created it
(except if you override the prototype doins something as, A.prototype = new
B() )
A is a "special case" because it's a Function object
so a prototype property is automatically assigned him
by default this property is a simple Object object
for hosts implementing __proto__
you can see __proto__ as the "visible" or "accessible" constructor prototype
zwetan