5

我在使用 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 对象相同的函数作为参数时,一切都按预期工作。

有人知道为什么会发生这种情况以及可以采取哪些措施来纠正这种情况?

4

2 回答 2

5

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

您调用该函数的唯一一次是创建一个实例prototype作为SpecializedControl. 因此,每次setNameSpecializedControl实例调用时,都会更新该单个变量。

因此,由于get/setName引用该变量的方法在所有SpecializedControl实例的原型链中,它们都将观察到相同的name.


setName,你应该做...

this.name = newName;

getName,你应该做...

return this.name;
于 2012-06-12T22:23:59.153 回答
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);​
于 2012-06-12T22:32:26.960 回答