Question

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.

Was it helpful?

Solution

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 pass this to your Object1 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") without new:

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 back undefined ... and on the object equal to this (most likely window in the case of browser JavaScript) we find two new variables ... prop1 and prop2.

What happened?

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 where this === window.) This is the way you are invoking Object1 when you call Object1.apply(this).

The second version (new Object1("param")) executes a function as a constructor - that is, it creates a new object and sets this to be that new object. If we were to use the same apply function to demonstrate this we would write Object1.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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top