0

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

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"

如何进行检查并保持属性不变?

4

3 回答 3

1

使用 getter 和 setter:

this.getValue = function(){
    return value;
};

this.setValue = function(val){
    value = val;
};

将您的检查逻辑添加到设置器。

于 2013-09-13T07:47:49.877 回答
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

于 2013-09-13T07:48:17.133 回答
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";
  }
};
于 2013-09-13T09:23:07.823 回答