Javascript prototype

Hi,
I have a question on setting the prototype of a Function.
The following code is working as expected:
It returns true.


var monkey = {
    hair : true,
    feeds : 'bananas',
    breathes: 'air'
};

function Human(name){
    this.name = name;
    
};
Human.prototype = monkey;

var david = new Human('David');

monkey.isPrototypeOf(david);

However, I use this.prototype = monkey in Human function, the code returns false.


var monkey = {
    hair : true,
    feeds : 'bananas',
    breathes: 'air'
};

function Human(name){
    this.name = name;
    this.prototype = monkey;
};

var david = new Human('David');
monkey.isPrototypeOf(david);

I am not very clear why I am not able to refer prototype using ‘this’ in the second case?
Could someone please share your idea?

Thanks
David

All objects automatically inherit their prototype from their constructor, so even if you set it from within, it will revert back to the constructor afterwards.

You will need to set the prototype from outside of the constructor.

The way the prototype chain is established is by a secret property on the object, named proto. You can’t play with it except for in firefox. I think it only makes sense that isPrototypeOf() reads that hidden property. That’s why this works in firefox.


var monkey = {
    hair : true,
    feeds : 'bananas',
    breathes: 'air'
};

function Human(name){
    this.name = name;
    this.__proto__ = monkey;
};

var david = new Human('David');
monkey.isPrototypeOf(david);

I’m not sure if I’m right, but this post sums my understanding of it.

I’m still getting to grips with it myself, but the proto link is key. As crmalibu has mentioned

It’s worth experimenting with the proto to figure out what’s going on.

When you make a new instance like david from your Human constructor you end up with a new object with it’s own name property and a secret proto property which points to the Human constructor’s prototype.

A bit of experimenting

function Human(name){
    this.name = name;
};
// Note set outside of the constructor
Human.prototype.getName = function(){return this.name};

var david = new Human('David');
console.log(Human.prototype.isPrototypeOf(david)); // true

// david doesn't have a prototype object.
console.log(david.prototype); // Undefined. no prototype
// david does have a __proto__ link though
// david's __proto__ link points to the Human constructor's prototype object
console.log(david.__proto__); // Object {getName = function(){....}}
// which inturn has a link to the constructor through the constructor property
console.log(david.__proto__.constructor); // Human(name){.....}
// the Human's prototype in turn has a __proto__ pointing back to Object.prototype
console.log(david.__proto__.__proto__); // Object {}

// Let's introduce monkey to the mix
var monkey = {
    hair : true,
    feeds : 'bananas',
    breathes: 'air'
};
// change the Human prototype to monkey
Human.prototype = monkey;

console.log(david.prototype); // still undefined
console.log(david.__proto__); // Surprise. Still points to the old prototype Object {getName......

var paul = new Human('Paul');
console.log(paul.prototype); // still undefined
// paul's __proto__ link points to monkey
console.log(paul.__proto__); //Object {hair: true, feeds: 'bananas', breathes: 'air'}

RLM

The purpose of a constructor’s prototype is to define default values for its children, that the constructor itself doesn’t define.

david.constructor points to Human, and Human.prototype contains the default values for david.

proto is a shortcut from david straight to his constructors default values.

david.constructor points to Human

This is a tad confusing to me, because it insinuates that david has it own constructor property. As far as I can see when you use david.constructor it requires a lookup via the proto chain to find a constructor property. Well atleast that’s how it appears to me.

I.e.

function Human(name){
    this.name = name;
};
Human.prototype.getName = function(){return this.name};
 
var david = new Human('David');

// looks up the constructor property
console.log(david.constructor); //Human(name)

// finds it via it's __proto__ link
console.log(david.__proto__.constructor); //Human(name)

// this is where it is
console.log(Human.prototype.constructor); //Human(name)

function AnotherConstructor(){};

//change the Human.prototype.constructor to another object
Human.prototype.constructor = AnotherConstructor; 

console.log (david.constructor); // AnotherConstructor()

This image should help, where:

[list][]Monkey = A
[
]Human = B
[*]david = X[/list]

This image should help

That’s exactly what was needed. Well done:tup:

Actually given monkey is an object literal should’nt it be more like this?

* Monkey = A
* Human = B
* david = X


var monkey = {
    hair : true,
    feeds : 'bananas',
    breathes: 'air'
};

console.log(monkey.prototype); //undefined
console.log(monkey.constructor); //Object{}
console.log(monkey.__proto__); //Object{}

RLM

Hmm, interesting. What I get is:

monkey.prototype // undefined
monkey.constructor // function Object()
monkey.constructor.prototype // Object, or {}
monkey.proto // function Empty()
monkey.proto.constructor // function Object()
monkey.proto.constructor.prototype // Object or {}

I’ll have to sleep on this.

I missed the function object

Testing again with console.log


var monkey = {
    hair : true,
    feeds : 'bananas',
    breathes: 'air'
};

console.log(monkey.prototype); // undefined
console.log(monkey.constructor); // function Object([native code])
console.log(monkey.constructor.prototype); // Object {}
console.log(monkey.__proto__); // Object {}
console.log(monkey.__proto__.constructor); // function Object([native code])
console.log(monkey.__proto__.constructor.prototype); // Object or {}

I can see a pattern forming here.

console.log(monkey.prototype); // undefined
console.log(monkey.constructor); // function Object([native code])
console.log(monkey.constructor.prototype); // Object {}
console.log(monkey.constructor.prototype.constructor); // function Object([native code])
console.log(monkey.constructor.prototype.constructor.prototype); // Object {}
console.log(monkey.constructor.prototype.constructor.prototype.constructor); // function Object([native code])
console.log(monkey.constructor.prototype.constructor.prototype.constructor.prototype); // Object {}
console.log(monkey.constructor.prototype.constructor.prototype.constructor.prototype.constructor); // function Object([native code])

Right after a lot of console.logging this is what I’ve come up with. Apologies for my lack of diagrammatical skills.

var monkey = {
    hair : true,
    feeds : 'bananas',
    breathes: 'air'
};
console.log(Function); // function Function([native code])
console.log(Function.prototype); // function(){}
console.log(Function.prototype.__proto__); // Object{}
console.log(Function.prototype.__proto__.constructor); // function Object([native code])

console.log(Function.__proto__); // function(){}
console.log(Function.__proto__.constructor); // function Function([native code])
//It appears Function's proto just points to it's prototype

console.log(Object); // function Object([native code])
console.log(Object.prototype); // Object {}
console.log(Object.prototype.__proto__); // null
console.log(Object.prototype.constructor);
console.log(Object.__proto__); // function(){}
console.log(Object.__proto__.constructor); //function Function([native code])
// The above suggest that Object's __proto__ links to the Function.prototype
// The Object's prototype is a dead end.

console.log (monkey.__proto__); //Object.prototype
console.log (monkey.__proto__.__proto__); //null
console.log (monkey.__proto__.constructor); // function Object([native code])
console.log (monkey.__proto__.constructor.__proto__); // function(){}
console.log (monkey.__proto__.constructor.__proto__.constructor); // function Function([native code])