JavaScript:将继承的类添加到数组不起作用

时间:2012-06-12 22:11:15

标签: javascript arrays inheritance prototype

我遇到了一些JavaScript问题。我有以下代码:

<html>
<head>
<title>Test</title>
<script  type="text/javascript">
function Control(){
    var name;

    this.setName = function(newName){
        name = newName;
    };

    this.getName = function(){
        return name;
    };
}

function SpecializedControl(){
}
SpecializedControl.prototype = new Control();

function Form(){
    var formControls = [];

    this.addControl = function(control){
         formControls.push(control);

         alert(formControls[0].getName());
    };
}

var form = new Form();

var control1 = new SpecializedControl();
control1.setName("Control1");
form.addControl(control1);

var control2 = new SpecializedControl();
control2.setName("Control2");
form.addControl(control2);

</script>
</head>
<body>
</body>
</html>

SpecializedControl继承自Control类。

Form类中的addControl函数只是将控件添加到数组中。

问题在于,当我添加多个SpecializedControl时,数组中的值是一种覆盖,这意味着当我访问数组中的第一个项目时,应该是“Control1”,我得到“Control2”。 Control1不再在数组中。

当我使用与Control对象相同的函数作为参数时,一切都按预期工作。

有人知道为什么会发生这种情况以及可以采取哪些措施来解决这个问题?

2 个答案:

答案 0 :(得分:5)

您的get/setName函数正在获取/设置name构造函数本地的Control变量的值。

您调用该函数的唯一时间是创建一个实例作为prototype的{​​{1}}对象。因此,每次从SpecializedControl实例调用setName时,都会更新该单个变量。

因为引用该变量的SpecializedControl方法位于所有get/setName个实例的原型链中,所以它们都会观察到相同的SpecializedControl


name中,你应该......

setName

this.name = newName; ,你应该......

getName

答案 1 :(得分:5)

数组中的值未被覆盖;问题是两个控件共享相同的name变量。因为Control函数只执行一次,所以只声明了一个name变量。

您有两个主要选项来解决此问题。 (1)使name一个特定于每个单独控件的实例变量(例如this._name)。 (2)从Control构造函数内部执行SpecializedControl函数。 (实际上,IMO,对于一个平衡和彻底的继承模型,你应该做一些这两种方法)。

以下是三种有效的解决方案。前两个分别使用选项(1)和(2)。第三种方法结合了两种方法,就是我这样做的方式(但需要joi)。

选项1:

function Control(){

    this.setName = function(newName){
        this._name = newName;
    };

    this.getName = function(){
        return this._name;
    };
}

选项2:

function SpecializedControl(){
    Control.apply(this, arguments);
}

选项3:

var Control = joi.Unit.sub(function() {

    function constructor() {
        this.base();
    }

    constructor.prototype = {
        '#name': null,
        setName: function(name) {
            this['#name'] = name;
        },
        getName: function() {
            return this['#name'];
        }
    };

    return constructor;

}());

var SpecializedControl = Control.sub(function() {

    function constructor() {
        this.base();
    }

    return constructor;

}());

var Form = joi.Unit.sub(function() {

    function constructor() {
        this.base();
        this['#formControls'] = [];
    }

    constructor.prototype = {
        '#formControls': null,
        addControl: function(control) {
            this['#formControls'].push(control);
            alert(this['#formControls'][0].getName());
        }
    };

    return constructor;

}());

var form = new Form();

var control1 = new SpecializedControl();
control1.setName("Control1");
form.addControl(control1);

var control2 = new SpecializedControl();
control2.setName("Control2");
form.addControl(control2);​