getter和setter是避免原型突变的唯一方法吗?

时间:2015-01-05 21:42:45

标签: javascript

我有一个JavaScript对象,我想扩展它。问题是它的变量从一个范围变异到另一个范围。

首先,我创建了一个Mammal原型,并且他有一个名字,这个名字可以用whoAmI函数打印

var Mammal = ( function () {

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

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

})();

然后,我创造了一只狗,它也有一个名字。它的名称可以直接从whoAmIstate函数打印。

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

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

    return mammal;

})(Object.create(Mammal));

但是当我想创建一个Dog实例并从外部设置他的名字时,似乎有两个name变量:一个在Dog中,另一个在新创建的变量中shipo

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

我可以通过在Mammal定义上为name变量实现getter和setter函数来解决这个问题......但是我讨厌使用getter和setter,如果变量可以公开,我的代码会更短在没有这种丑陋功能的情况下设定并获得......

getter和setter是防止这种突变的唯一方法吗?

1 个答案:

答案 0 :(得分:3)

在这种情况下,修复非常简单:只需调用this.whoAmI()而不是mammal.whoAmI()来访问当前对象而不是其原型属性:

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

会给出预期的结果:

  

我是石浦   我很高兴   我是Shipo

以下是继承链的简化方案:

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

从此表中可以很容易地看到,如果Dog调用state方法的实例,您希望在当前this对象上调用它,以便它可以选择向上this.name,而不是mammal.name