Reputation: 31
Can someone explain this?
function Foo() {
this.x = 1;
this.y = 2;
}
function FooProto() {
this.arrow = 1;
this.bow = 1;
}
document.writeln(Foo.prototype); // [object Object]
document.writeln(Foo.prototype.constructor); // function Foo() { x =1; y=2; }
My understanding here is: Foo.prototype is an Object whose constructor property is Function Foo. Foo.[[Prototype]] is Function.Prototype
obj = new Foo;
document.writeln(obj.constructor); // function Foo() { x =1; y=2; }
document.writeln(obj.constructor.prototype); // [object Object]
Foo.prototype = FooProto;
document.writeln(Foo.prototype); // function FooProto() { arrow = 1; bow = 2; }
document.writeln(Foo.prototype.constructor); // function Function() { [native code] }
Question 1: How did the look up using [[Prototype]] happen here. I would appreciate if someone can explain this to me.
document.writeln(obj.constructor); // function Foo() { x =1; y=2; } .. no change
document.writeln(obj.constructor.prototype); // function FooProto() { arrow = 1; bow = 2; }
anotherObj = new Foo;
document.writeln(anotherObj.constructor); // function Function() { [native code] }
document.writeln(anotherObj.constructor.prototype); // function Empty() {}
Question 2: Same question as Question 1. How did the Javascript interpreter perform the lookup?
Upvotes: 3
Views: 391
Reputation: 100
There're two concepts of prototype in Javascript. (I take it as a name collision in language design.)
The prototype in the "prototype chain".
It is a inside property as mentioned in the last answer. The prefered way to access it is Object.getPrototypeOf
.
var a = {};
Object.getPrototypeOf(a); // Object {}
Object.getPrototypeOf(Object.getPrototypeOf(a)); // null, the top of prototype chain.
Object.getOwnPropertyNames(Object.getPrototypeOf(a)); // the methods inherited
Every constructor (I think acutally every function declared) has a own property "prototype". It come to use in the new
operator.
The
new
operator does 2 steps.
- First is to create an object whose prototype (the 1st one, saying, [[Prototype]]) is assigned as the constructor's prototype (the 2nd one).
- Second is to run the constructor (looking up from
prototype.constructor
) with taking the created object as implicit argumentthis
.
Now to your case:
The first obj
was created with its property [[Prototype]] (proto in some engines) assigned as Foo.prototype.
obj.constructor === obj.__proto__.constructor === Foo.prototype.constructor === Foo
obj.constructor.prototype === Function.prototype
Note that the constructor is also a Function object.
Then you changed the prototype of Foo
. This changed the obj.constructor.prototype
but not obj.constructor
which has a different reference. The anotherObj
had a new [[Prototype]] from the following new
operator.
This question has been here for years. Following readers may be also confused as me. I recommendated the newly published book Speaking JavaScript from Dr. Axel Rauschmayer :
Terminology: The Two Prototypes
Upvotes: 0
Reputation: 69934
When explaining prototype-based code, it is much simpler to use Object.create
to explain stuff. Object.create
is a function that receives a prototype object and creates a new instance object that has the prototype object as its [[prototype]]
When looking up properties in an object is work like this:
Every object has its own and immutable [[prototype]] property inside. This property is secret and hidden, unless you are in Firefox, where you can get it via __proto__
.
When reading a property up we first search for it in the object itself and if we don't find it there we recursively search for the object's [[prototype]].
When writing a property we always write an own-property (we never mutate the [[prototype]], even if it also has the property we are setting).
proto = {a:1};
child1 = Object.create(proto);
child2 = Object.create(proto);
child1.a = 2;
console.log(proto.a); //1
console.log(child1.a); //2
console.log(child2.a); //1
When creating a function
Whenever we create a function object in Javascript, it comes with a prototype
property already filled in. This prototype
is an object (inheriting from Object.prototype) and has the constructor
property set to the corresponding function.
When instantiating an object using a function constructor (new Foo)
A new object is created with the functions prototype
as its [[prototype]] and the function is run o the object to initialize it.
I don´t really want to explain what is going on in the first case, since the
Foo.prototype = FooProto;
part doesn't really make sense and is probably not what you wanted to do (remember that prototypes should be objects, not functions)
As for the second case, changing the prototype
property of the constructor function will only affect the future instances (anotherObj). The [[prototype]] property of the already created objects is secret and immutable so there is nothing you can do to change them.
Upvotes: 5