我遇到了一些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对象相同的函数作为参数时,一切都按预期工作。
有人知道为什么会发生这种情况以及可以采取哪些措施来解决这个问题?
答案 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);