Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference in Prototype Inheritance, Firefox vs Chrome

Tags:

javascript

For the following code:

function Mammal(){
    this.hair = true;
    this.backbone = true;
    return this;
}

function Canine(){
    this.sound= 'woof';
    return this;
}
Canine.prototype = new Mammal(); 

function Dog(name){
    this.tail=true;
    this.name=name;
    return this; 
}
Dog.prototype = new Canine();

var aspen = new Dog('Aspen');

var aspenProto = aspen.__proto__

Firebug (Firefox) wants to tell me aspenProto is Mammal{}, while Chrome is saying Canine{}.

Can anyone tell me why they display different, and if anyone else has ran into this issue?

like image 755
AROE Avatar asked Dec 06 '12 20:12

AROE


People also ask

What is difference between __ proto __ and prototype?

prototype is a property of a Function object. It is the prototype of objects constructed by that function. __proto__ is an internal property of an object, pointing to its prototype.

What is the difference between classical inheritance and prototypal inheritance?

Classical inheritance is limited to classes inheriting from other classes. However prototypal inheritance includes not only prototypes inheriting from other prototypes but also objects inheriting from prototypes.

How does prototypical inheritance work?

Simply put, prototypical inheritance refers to the ability to access object properties from another object. We use a JavaScript prototype to add new properties and methods to an existing object constructor. We can then essentially tell our JS code to inherit properties from a prototype.

Is __ proto __ deprecated?

__proto__ is considered outdated and somewhat deprecated (moved to the so-called “Annex B” of the JavaScript standard, meant for browsers only). The modern methods to get/set a prototype are: Object.


1 Answers

Facts (credits go to @IHateLazy):

aspenProto.constructor is Mammal. This is because the constructor is actually an attribute of Mammal.prototype, set at the method creation time. Canine.prototype.constructor is not Canine, since the prototype (holding the constructor property) was overwritten by new Mammal().

Tests:

aspen.constructor = function Hello(){}; // aspen is Hello in Firebug,
                                        // Dog in Chrome
aspen.constructor.name = "test"         // still Hello in Firebug,
                                        // name is also Hello in both
aspen.constructor = function(){};       // aspen is Object in Firebug
aspen.constructor.name = "test"         // still Object in Firebug
aspen.constructor = null;               // still Object and Dog

({constructor: function Hello(){}})     // Hello in Firebug AND Chrome
({constructor: function (){}})          // Object in both (not surprisingly)
({constructor:{name:"Hi"}})             // "Object" in FB, "Hi" in Chrome

x={constructor:function(){})
x.constructor.name="Hello"              // x is Object in both

x=new Object()
x.constructor=function Hello(){}        // x is Hello in both

new (function(){})()                    // Object in both
new (function(){
  this.constructor=function Hello(){}
})()                                    // Hello in both

Conclusion:

Firebug always relies on the object's own constructor property to name it. If the constructor is a named function, it uses the constructor name (which is not writable - thanks @IHateLazy). If the constructor property is an anonymous function or not a function at all, then Firebug uses "Object" instead.

Chrome holds each object's actual constructor as an internal property. Only if that property is not accessible (the object was not constructed) or is Object, it looks at the object's constructor property. If the constructor is a named function, it uses its internally stored name. If the constructor is not a function or is anonymous it uses the name property.

like image 137
John Dvorak Avatar answered Sep 20 '22 04:09

John Dvorak