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?
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.
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.
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.
__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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With