4

I'm learning prototype chains in JavaScript and wrote a demo, but I can not understand the result.

This is my demo:

function A(){}
const c = new A();
A.prototype.sex = "girl";
A.prototype={
  name:"q",
  age:12
};
console.log(A.prototype.name);
console.log(c.name);
console.log(c.sex);

This is the output:

"q"
undefined
"girl"

Why does console.log(c.name) output undefined?

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
zhan mei yang
  • 287
  • 2
  • 5
  • See also [Defining a Javascript prototype](https://stackoverflow.com/questions/17474390/defining-a-javascript-prototype) for why you should not do that – Bergi Mar 10 '17 at 15:17

3 Answers3

3

A is your constructor, that means you put in that function everything you need to performe on the newly created object when you "initialize" it

in your case you do nothing. the constructor has a prototype property which is the object that all the object you will create by new A() will inherit from

if you don't explicitly set a prototype to your constructor so your prototype is an empty object by default.

so at that line : const c = new A(); c inherites an empty object when you set :

A.prototype.sex = "girl";

you are creating a property sex on your empty object and you assign to it "girl"

but that object is the same (same reference) as before you do "new". So c still has a reference to it BUT when you do:

A.prototype={
  name:"q",
  age:12
};

you change the prototype of A i.e you change the reference of A.prototype, but you didn't use new anymore. So there is no object that actually has

{
      name:"q",
      age:12
    }

as prototype. c is still having the former object (remember the empty) object as prototype.

But if you do : const d = new A() then, d.name will existe but d.sex won't

changing the prototype as you did (assigning another reference to the A.prototype) just affects A.prototype not the objects that have been 'instanciated' before that affectation.

Fanyo SILIADIN
  • 802
  • 5
  • 11
1

Below are the steps for constructing a new object, as per the JavaScript spec.

As you can see in steps 5 and 6, the internal prototype of the constructed object is determined and captured during construction.

So the object doesn't maintain a prototype reference to "Whatever .prototype value A has at any given time". It maintains a prototype reference to "the value that A.prototype had when new A() was executed". That's why you are able to modify c's internal prototype by adding new properties to it, but not by replacing A's prototype with a new one.

If you were to execute new A() again after replacing its prototype, the object created at that time would have that new prototype.

  1. Let obj be a newly created native ECMAScript object.
  2. Set all the internal methods of obj as specified in 8.12.
  3. Set the [[Class]] internal property of obj to "Object".
  4. Set the [[Extensible]] internal property of obj to true.
  5. Let proto be the value of calling the [[Get]] internal property of F with argument "prototype".
  6. If Type(proto) is Object, set the [[Prototype]] internal property of obj to proto.
  7. If Type(proto) is not Object, set the [[Prototype]] internal property of obj to the standard built-in Object prototype object as described in 15.2.4.
  8. Let result be the result of calling the [[Call]] internal property of F, providing obj as the this value and providing the argument list passed into [[Construct]] as args.
  9. If Type(result) is Object then return result.
  10. Return obj.
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
JLRishe
  • 99,490
  • 19
  • 131
  • 169
0

1) you create an empty class

2) you add a static property (from the prototype) sex

3) you assign a new prototype to your class, but c keep the old prototype

So 'A' is up to date, but 'c' still get the old prototype, so the name doesn't exist but the sex property which was set before changing the prototype exists, so you find it.

PortePoisse
  • 219
  • 2
  • 10
  • but i delete A.prototype.sex = "girl" this line ,the result is same. ` function A(){} const c = new A(); A.prototype={ name:"q", age:12 }; console.log(A.prototype.name); console.log(c.name); ` the result is: ` "q" undefined ` – zhan mei yang Mar 10 '17 at 14:58
  • Yes because 'c.prototype' is not 'A.prototype' after you set A.prototype={...}. 'c' inherit properties of prototype if you keep the same. So when you added the sex property, the prototype is still the same. But when you completly set a new prototype to 'A', 'c' and 'A' are no more synchronized – PortePoisse Mar 10 '17 at 15:09
  • @PortePoisse You mean `Object.getPrototypeOf(c)` not `c.prototype` – Bergi Mar 10 '17 at 15:24
  • @Bergi yes that was to be shorter ^^ – PortePoisse Mar 13 '17 at 10:45