0

I've got this code piece below:

function me(){
    this.age=30,
    this.say=function(){return 'hello me'}
}
function child(){
    this.hobby='sports'
}
child.prototype=new me();
var son=new child();
son.prototype=new me();
console.log(son.age);//30
console.log(son.__proto__.age);//30
console.log(son.constructor.prototype.age);//undefined
console.log(son.constructor.prototype.say())//exception

The printing result was, only the first 2 log prints out "30", all others prints out "undefined", and the last line even throws exception in runtime.

(1) I was expecting that all of them should give me output. Why the 3rd line prints 'undefined"?

(2) I expect that both "proto" and "constructor.prototype" has same effect, but actually not.

Troskyvs
  • 7,537
  • 7
  • 47
  • 115

1 Answers1

1

son.constructor === me, and me.prototype does not have properties age and say. Note that son.__proto__.hasOwnProperty("constructor") === false.

You are assigning objects to the prototype which do not have a constructor property themselves, this produces somewhat unintuitive results when accessing son.constructor. It is son.__proto__.__proto__.constructor, which is probably not what you intended.

Example showing this behavior:

function A() {}
function B() {}
console.log("Automatically added: " + A.prototype.constructor.toString());
A.prototype = new B();
let a = new A();
console.log("a constructor: " + a.constructor.toString());
if (a.constructor
    && !a.hasOwnProperty("constructor")
    && !a.__proto__.hasOwnProperty("constructor"))
  console.log("constructor property of a is further up the prototype chain!");

Also note that you assign new me() to two different objects as prototype, which is unnecessary and also probably not what you want.

Finally here is a working example:

function me(){
    this.age=30,
    this.say=function(){return 'hello me'}
}
function child(){
    this.hobby='sports'
}
child.prototype=new me();
child.prototype.constructor = child;
var son=new child();

console.log(son.age);
console.log(son.__proto__.age);
console.log(son.constructor.prototype.age);
console.log(son.constructor.prototype.say())
ASDFGerte
  • 4,695
  • 6
  • 16
  • 33
  • Thanks, just one question, why we need ‘child.prototype.constructor = child'. I suppose when creating an object, a constructor property is automatically assigned to it, right? – Troskyvs Aug 10 '16 at 02:44
  • When declaring a function, `prototype.constructor` is automatically added, see [spec](http://www.ecma-international.org/ecma-262/7.0/#sec-makeconstructor). When overwriting `prototype`, this is afaik not automatically readded. – ASDFGerte Aug 10 '16 at 03:12
  • When using `new` on a function, the object located in `prototype` will be added to the returned object's internal `[[Prototype]]` property, which is exposed through `__proto__`, which however should be used with care [mozilla doc](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/proto) – ASDFGerte Aug 10 '16 at 03:18