简体   繁体   中英

constructor and prototype

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?

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.


  1. 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)

  2. 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.

    • Note that if you want to dynamically change the prototype and existing objects (monkey-patching) you can do that by writing and overwriting values in the existing prototype object instead of replacing it with a new one.

There're two concepts of prototype in Javascript. (I take it as a name collision in language design.)

  1. 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 
  2. 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.

  1. First is to create an object whose prototype (the 1st one, saying, [[Prototype]]) is assigned as the constructor's prototype (the 2nd one).
  2. Second is to run the constructor (looking up from prototype.constructor ) with taking the created object as implicit argument this .

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM