Are getters and setters the only way to avoid prototype mutations?

I have a JavaScript object and I want to extend it. The problem is that variables change from one scope to another.

First, I am making a prototype Mammal and it has a name, this name can be printed with the function whoAmI

var Mammal = ( function () {

    var whoAmI = function () {
        console.log("I am " + this.name);
    };

    return {
        name : "mammal",
        whoAmI : whoAmI
    };

})();

      

Then I create a Dog that also has a name. Its name can be printed directly from whoAmI

or from a function state

.

var Dog = ( function (mammal) {
    mammal.name = "dog";

    mammal.state = function () {
    mammal.whoAmI();
    console.log("I am happy");
    };

    return mammal;

})(Object.create(Mammal));

      

But when I want to instantiate Dog and set its name externally, there seem to be two variables name

, one in Dog and one in the newly created variable shipo

.

var shipo = Object.create(Dog);
shipo.name = "Shipo"
shipo.state(); // it name is dog
shipo.whoAmI(); // it name is Shipo
// mutation? :(

      

I can solve this by doing a getter and setter function on a variable name

, as defined by Mammal ... but I hate using getters and setters, my code will be shorter if the variables can be publicly set and ended up without those ugly functions ...

Are getters and setters the only way to prevent such mutations?

+3


source to share


1 answer


The fix is ​​very simple in this case: just call this.whoAmI()

instead mammal.whoAmI()

to access the current object instead of its prototype property:

var Dog = ( function (mammal) {
    mammal.name = "dog";
    mammal.state = function () {
        this.whoAmI();
        console.log("I am happy");
    };
    return mammal;
})(Object.create(Mammal));

      

will give the expected output:

I am Shipo
I am happy
I am Shipo



Here's a simplified diagram of the inheritance chain:

+--------------+       +--------------+   
| Mammal       |  +--> | Dog          |
+--------------+  |    +--------------+
| __proto__    |--+    | __proto__    |
+--------------+       +--------------+
| name: mammal |       | name: dog    |
| whoAmI()     |       | state()      |
+--------------+       +--------------+

      

It is easy to see from this table that if an instance Dog

calls a method state

, you want to be called on the current object this

so that it can select this.name

, not mammal.name

.

+3


source







All Articles