Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javascript two variables with same name co-exist in same object?

I'm trying my best to understand javascript. Here is a simple experiment in Chrome console which gets me very confused:

var foo=function(){this.p=1;}
foo.prototype.p=2;
var bar=new foo();
//foo{p:1,p:2} <- this is the output of Chrome console, from the last command above

The output of Chrome is what confuses me. It seems like bar is an object with 2 parameters, p:1 and p:2. Does this mean bar has 2 p??? What is the reasoning behind this?

like image 876
Xun Yang Avatar asked Feb 16 '23 07:02

Xun Yang


1 Answers

Chrome DevTools console's inline (non-extended) object representation currently does not display any difference between own properties and inherited prototype properties.

Now let's break what's going on into smaller steps.

new foo() creates a new object whose internal proto property points to foo.prototype. This means this object can access all properties defined in foo.prototype. It's called prototype chain.

Now when you set a property of the same name in the object, it "shadows" the prototype's property by the same name, turning the latter inaccessible through regular property access (see @loxxy's answer using Object.getPrototypeOf(obj) to access the shadowed prototype property).

Once you add a function to the object or its prototype, the console allows you to display the extended object representation, which does differ own properties from prototype properties. In the next example I've added a q method to the prototype to allow this behavior. The properties inherited from the prototype are shown inside the object's proto internal property:

enter image description here


If you just want to have the number of instanced objects in the constructor's prototype, you can use:

var foo = function() {
    Object.getPrototypeOf(this).p++;
}
foo.prototype.p = 0;

console.log(new foo()); //{p: 1}
console.log(new foo()); //{p: 2}

Or without the ES5 dependency:

var foo = function() {
    foo.prototype.p++;
}
foo.prototype.p = 0;

console.log(new foo()); //{p: 1}
console.log(new foo()); //{p: 2}
like image 157
Fabrício Matté Avatar answered Feb 17 '23 20:02

Fabrício Matté