javascriptprototypal-inheritancehasownpropertycoding-efficiency

hasOwnProperty returns true, when checked against parent object properties


My JavaScript code:

console.clear();

function BaseClass(nname) {
  var name = nname;

  this.bc_PublicProperty = "DefaultValue_BaseClass";

  this.bc_getName = function GetName() {
    return name;
  };

  this.bc_setName = function SetName(nname) {
    name = nname;
  };
}

function SubClass(nname) {
  BaseClass.call(this, nname);

  this.sc_PublicProperty = "DefaultValue_SubClass";

  this.sc_getName = function GetName() {
    return name;
  };

  this.sc_setName = function SetName(nname) {
    name = nname;
  };
}

SubClass.prototype = Object.create(BaseClass.prototype);
SubClass.prototype.constructor = SubClass;

var bc = new BaseClass("Anton");
var sc = new SubClass("Bernd");

console.log("hasOwnProperty check on subclass object 'sc' returns true for Method 'bc_getName'");

for (var pro in sc) {
  console.log("Is " + pro + " own property of subclass:  --> " + Object.hasOwnProperty.call(sc, pro));

}

I have two objects (BaseClass and SubClass). One inherits from the other using the constructor pattern, as explained on MDN.

Now, when I iterate over all properties of the subclass object, they all return true for hasOwnProperty, even for the parent methods/properties, except constructor.

Does it mean, that it breaks when using the constructor pattern?

When I put public properties and methods in the constructor function, whether in BaseClass or SubClass, they will always be "marked" as own properties/methods. When I instead attach them to the respective prototype, the hasOwnProperty will output "false" for them.

Whether you put the public methods/properties to the prototype or to the constructor function itself, they will all be available for use in the subClass (--> SubClass2, --> SubClass3).

The only thing, that I can think of right now, why you should attach them to the prototype object, is because of efficiency reasons, as explained here, "Defining class methods"-section. In order not to add closures for every constructed instance.

Value Types should be declared on the prototype, but not for instance variables whose initial values are dependent on arguments to the constructor, or some other state at time of construction. You can override both properties/functions irrespective of their place of declaration.

Also setting up getters and setters on the prototype, for instance to set or get a private variable, makes no sense, as the private variable has to be public, in order to be accessible by the getters and setters attached to the prototype.

Therefore it makes no sense to use getters and setters. You can access the public variable directly.

I have to adjust my question a bit now:

When do I need hasOwnProperty, if actually public props/functions should be declared on the prototype, which in turn will all output Object.hasOwnProperty(obj,"prop/func") --> false. Give me a use case, when it makes sense, to use hasOwnProperty.

console.clear();

var l = function(v) {
  console.log(v);
};

function BaseClass(nname) {

  this.bc_nameProp = nname;
  this.bc_ownFunc = function() {
    l("bc_ownFunc of BaseClass called");
  };

  this.bc_getName = function GetName() {
    return this.bc_nameProp;
  };
}

BaseClass.prototype.bc_getName = function GetName() {
  return this.bc_nameProp;
};

BaseClass.prototype.bc_PublicProperty = "DefaultValue_BaseClass";

BaseClass.prototype.bc_setName = function SetName(nname) {
  bc_nameProp = nname;
};

function SubClass(nname) {

  BaseClass.call(this, nname);

  this.sc_setName = function SetName(nname) {
    bc_nameProp = nname;
  };

  this.bc_getName = function GetName() {
    return "xyz";
  };

}

SubClass.prototype = Object.create(BaseClass.prototype);
SubClass.prototype.constructor = SubClass;

SubClass.prototype.sc_getName = function GetName() {
  return this.bc_nameProp;
};
SubClass.prototype.sc_PublicProperty = "DefaultValue_SubClass";

var bc = new BaseClass("Anton");
var sc = new SubClass("Bernd");

l("-----  iterating over BaseClass properties  ------");
l("");
for (var pro in bc) {
  l("Is " + pro + " own property of BaseClass:  --> " + Object.hasOwnProperty.call(bc, pro));

}
l("");
l("-----  iterating over SubClass properties  ------");
l("");
for (var p in sc) {
  l("Is " + p + " own property of subclass:  --> " + Object.hasOwnProperty.call(sc, p));

}

l(bc.bc_getName());
l(sc.bc_getName());
l(sc.sc_getName());


Solution

When I asked this question, I was of the opinion, that when using classical inheritance in JavaScript, I can differentiate which properties/functions of my subclass directly belong to it, using hasOwnProperty. Which is not possible, as all the properties/functions of the parent prototype are copied to the prototype of the SubClass:

SubClass.prototype = Object.create(BaseClass.prototype);

All properties/functions attached to prototypes return "false", when using hasOwnProperty.

And if you have public properties/functions declared in the constructor functions of BaseClass and SubClass, all these properties return "true", when calling hasOwnProperty for these properties on the subclass.

These are copied to the SubClass using this statement:

BaseClass.call(this, nname);

So using hasOwnProperty while iterating over all properties of an obj of type SubClass, will output false for all properties/functions declared on prototype level and true for all properties/functions declared on constructor function level.

Now, I understand why using hasOwnProperty in this use case makes no sense.


Solution

  • Check that you're calling BaseClass.call(this) on SubClass's constructor, meaning that you're adding BaseClass properties and functions to the SubClass instance, because this is an instance of SubClass.

    This is why hasOwnProperty returns true for all properties.

    Wrong prototypes...

    At the end of the day, you're not taking advantage of prototypes in JavaScript.

    Functions that must be part of any instance of some prototype should be defined in the prototype itself.

        var A = function() {};
    
        A.prototype = {
           doStuff: function() {}
        };
    

    Actually, the only benefit of defining functions during construction-time is that you ensure that an object will always define some functions/properties, but you're ensuring this once the object has been already created.

    For me, there's a very small difference between the following ways of defining properties:

    var A = function() {};
    var instance = new A();
    instance.text = "Hello, World!";
    
    // or...
    
    var A = function() {
        this.text = "Hello, World!";
    };
    
    var instance = new A();
    

    The first code sample defines a text property after the constructor has been called while the second one does it inside the constructor, but in both cases either this or instance are references to the same object (i.e. the instance of A).

    With prototypes you ensure that all objects created from some constructor function will share the same members, and these members will be inherited and consumed using prototype chain.

    About the OP's update...

    The OP said a lot of things, but summarizing said:

    [...] I have to adjust my question a bit now: When do I need hasOwnProperty, if actually public props/functions should be declared on the prototype, which in turn will all output Object.hasOwnProperty(obj,"prop/func") --> false. Give me a use case, when it makes sense, to use hasOwnProperty.

    You're going in the wrong way... Why asking yourself when you need hasOwnProperty? Ask yourself when you need simple objects with less reusability or when you need actual reusability. hasOwnProperty has nothing to do with this issue.

    When you use a literal object (i.e. ones declared as is with {} syntax)? When you need dictionaries, argument maps, value objects... Here you like hasOwnProperty because usually your code receiving arguments will look like this:

    function X(uri, options) {
       if(typeof options != "undefined") {
           // For example, we set a default value if options has no
           // mimeType property...
           options.mimeType = options.hasOwnProperty("mimeType") ? options.mimeType : "application/json";
       }
    }
    

    When do you use complex objects using prototypes? When you define behavior and you need to reuse it across your application or even multiple applications, and also you need to add more behavior on top of generic requirements (hello inheritance).

    About why using hasOwnProperty...

    The OP said:

    But why would you use "hasOwnProperty" here, if you want to check the existence of an property? Shouldn't it be: options.mimeType = options.mimeType || "application/json";

    There's a lot of code on the Internet doing the `options.mimeType =

    options.mimeType || "application/json", right, because in JavaScript undefinedevaluates tofalse(ifoptionsdoesn't own amimeTypeproperty returnsundefined`).

    In my humble opinion, I would use hasOwnProperty because it returns a boolean either if it exists or it exists and it has undefined as the value.

    For example, options could be defined as { mimeType: undefined } and sometimes you want to know if the property exists even if it has undefined as value. The undefined as false treats the case of if it's undefined, either if it exists or not, do X, and hasOwnProperty is I want to be sure it has the property or not.

    So why would I use options.hasOwnProperty over other approaches?. Easy: because, since language gives a tool to verify if a property exists in some object, why do I need a trick? object.hasOwnProperty returns true or false, and I'm sure the property exists or not, even if the property has undefined value.

    With options.hasOwnProperty("mimeType") I can throw an Error if it exists and it has an undefined value. Why do I prefer this? Because I like the fail-fast concept: if you gave me the property with undefined value I tend to think that there's some bug in your code. Define it or not, my friend!