My understanding is that “hasOwnProperty” returns true if the object has a given member without check the prototype chain. But when I inherit fro other object, I see all members in the last object itself.
Consider the following example:
var Object1 = function (param) {
this.prop1 = "p1 " + param;
this.prop2 = "p2 " + param;
};
var Object2 = function (param) {
Object1.apply(this, arguments);
this.prop3 = 'p3' + param;
};
Object2.prototype = new Object1();
var b = new Object2('this is Object 2');
for (var v in b)
print(v + ": " + b[v] + (b.hasOwnProperty(v)?' (own)':' (inherited)'));
This code prints:
--prop1: p1 this is Object 2 (own)
--prop2: p2 this is Object 2 (own)
--prop3: p3this is Object 2 (own)
If I take a look on the debugger I see:
b
Object2
prop1: "p1 this is Object 2"
prop2: "p2 this is Object 2"
prop3: "p3this is Object 2"
__proto__: Object1
But, id I remove the apply line, all makes more sense, but base object it is not initialized:
--prop3: p3this is Object 2 (own)
--prop1: p1 undefined (inherited)
--prop2: p2 undefined (inherited)
Now I see in the debugger:
b
Object2
prop3: "p3this is Object 2"
__proto__: Object1
prop1: "p1 undefined"
prop2: "p2 undefined"
__proto__: Object
As far as I know, apply it’s like … execute the super class constructor, so super members are initialized correctly, but apparently that changes the shape of the child object.
Why is this happening? What is the correct way -or at least the less messy- to inherit in JS?
I am taking a look to some information about it, and apparently each developer has different feelings about how to do it.
Regards.
applyis not at all like executing the super class constructor. As a construct, it executes any function in the scope of the first provided argument. When you passthisto yourObject1function (which you execute as a function, not as a constructor), you are passing through the scope in which your second function (Object2) is being executed.To see what’s happening, try executing
Object1("param")withoutnew:When we execute
new Object1("test")we get back an object that looks like this:But when we execute
Object1("test")we get backundefined… and on the object equal tothis(most likelywindowin the case of browser JavaScript) we find two new variables …prop1andprop2.What happened?
The key here is that:
The first version (
Object1("param")) executes a function (Object1) in some already existing scope (in browser JavaScript the most common scope is the top-level scope wherethis === window.) This is the way you are invokingObject1when you callObject1.apply(this).The second version (
new Object1("param")) executes a function as a constructor – that is, it creates a new object and setsthisto be that new object. If we were to use the sameapplyfunction to demonstrate this we would writeObject1.apply({});For one of the most definitive answers I have ever seen on the subject of how to do OOP-like programming right in a JavaScript environment, see Bobince’s answer to this question.