How to inherit correctly in javascript?-Collection of common programming errors
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.
-
apply
is 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 passthis
to yourObject1
function (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
:Object1("test");
When we execute
new Object1("test")
we get back an object that looks like this:Object { prop1="p1 test", prop2="p2 test"}
But when we execute
Object1("test")
we get backundefined
… and on the object equal tothis
(most likelywindow
in the case of browser JavaScript) we find two new variables …prop1
andprop2
.The key here is that:
Object1("param") !== new Object1("param");
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 invokingObject1
when you callObject1.apply(this)
.The second version (
new Object1("param")
) executes a function as a constructor – that is, it creates a new object and setsthis
to be that new object. If we were to use the sameapply
function 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.
Originally posted 2013-11-09 23:09:22.