说我有一个水果类,并在构建时检查水果类型:
var fruitType = {
"apple": 0,
"orange": 1
};
fruit = function(name) {
if (name in fruitType) {
this.name = name;
} else {
throw "wrong fruit type";
}
};
但我无法避免在对象构造之后设置属性:
var f = new fruit("apple");
f.name = "orange"; // ok
f.name = "cat"; // expecting this does nothing, f.name is still "orange"
如何检查并保持财产不变?
答案 0 :(得分:1)
使用getter和setter:
this.getValue = function(){
return value;
};
this.setValue = function(val){
value = val;
};
将检查逻辑添加到setter。
答案 1 :(得分:1)
首先使用getter和setter函数,而不是直接使用属性:
var fruitType = {
"apple": 0,
"orange": 1
};
var fruit = function(name) {
this.setName(name);
};
fruit.prototype.getName = function(){
return this.name;
}
fruit.prototype.setName = function(name){
if (name in fruitType) {
this.name = name;
} else {
throw "wrong fruit type";
}
};
您仍然可以直接覆盖f.name
,但只要您保持一致并使用您的制定者,您就不会遇到问题。
var f = new fruit("apple");
f.setName('orange'); // OK
f.setName('toast'); // Throws an error
f.name = 'toast'; // This works, so don't do it!
JSFiddle(感谢黑暗骑士)
如果f.name = 'toast'
对您不起作用很重要,那么您可以为每个水果对象使用单独的函数以及私有范围的name
变量:
var fruitType = {
"apple": 0,
"orange": 1
};
var fruit = function(name) {
this.getName = function(){
return name;
}
this.setName = function(newName){
if (newName in fruitType) {
name = newName;
} else {
throw "wrong fruit type";
}
};
this.setName(name);
};
这样做的缺点是每个水果都需要它自己的函数副本,但它的优点是修改name
变量的唯一方法是使用setter:
var f = new fruit("apple");
f.setName('orange'); // OK
f.setName('toast'); // Throws an error
f.name = 'toast'; // This sets the `name` property to 'toast', but:
f.getName(); // this will still return 'orange'
答案 2 :(得分:0)
谢谢@Paulpro的想法,这是我的版本:
fruit = function(name) {
Object.defineProperty(this, "name", {
get: function() { return this.nameValue; },
set: function(v) {
if (v in fruitType) {
this.nameValue = v;
}
}
});
if (name in fruitType) {
this.name = name;
} else {
throw "wrong fruit type";
}
};