Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript does not call prototype method

I try to override a method and script is:

function wrapper(target) {
    target.doABC = function () {
        alert('in wrapper');
    };
    return target;
}

function Model() {
    wrapper(this);
}

Model.prototype.doABC = function () {
    alert('in Model');
};

var a = new Model();
a.doABC();

The result is 'in wrapper'. I don't know why?

like image 348
Thu Quoc Nguyen Avatar asked May 06 '16 04:05

Thu Quoc Nguyen


2 Answers

Any JavaScript object has own and inherited properties. Own are those defined directly on the instance and inherited are taken from the prototype object.
When using a property accessor, JavaScript first searches in object's own properties list. If the property is not found, it searches in object's prototype chain.

In your example, the wrapper() method defines on object instance an own property doABC, which is a function that alerts 'in wrapper'. Even if the object has a prototype with the same property doAbc that alerts 'in Model', JavaScript anyway will use the own property.

function wrapper(target) {
    // Define an own property "doABC"
    target.doABC = function () {
        alert('in wrapper');
    };
    return target;
}

function Model() {
    wrapper(this);
}

// Define an inherited property "doABC"
Model.prototype.doABC = function () {
    alert('in Model');
};

var a = new Model();

//Use the own property "doABC". The inherited "doABC" is ignored.
a.doABC(); 

As an addition, the own property can be removed using delete operator. After deletion, the object will use the inherited property.

// delete the own property "doABC"
delete a['doABC'];

// the inherited "doABC" will be used. Alerts "in Model"
a.doABC();

Check the complete working demo.

like image 58
Dmitri Pavlutin Avatar answered Oct 13 '22 14:10

Dmitri Pavlutin


Let me see if I can explain:

You have two separate versions of doABC here.

Your target.doABC creates a function specific to that instance of your Model and each Model get its own doABC.

Because Model has a doABC, the JavaScript engine has no need to look 'up the chain' for something else, hence it will never look for the Model.prototype.doABC version.

You can see this by adding these lines:

Model.prototype.doXYZ = function () {
    alert('in Model');
};

and calling

a.doXYZ();

Since a doesn't have its own doXYZ then, and only then, will it look up the chain and see the method in the prototype.

like image 27
Jeremy J Starcher Avatar answered Oct 13 '22 13:10

Jeremy J Starcher