如何在设置属性时检查值是否有效

时间:2013-09-13 07:43:40

标签: javascript oop

说我有一个水果类,并在构建时检查水果类型:

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"

如何检查并保持财产不变?

3 个答案:

答案 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'

JSFiddle

答案 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";
  }
};