Class 枚举 setter、约定 javascript

Class enumeration setter, convention javascript

嗨,我有以下 class:

const MyClass = function MyClass() {
  this.state = null;
}

MyClass.prototype.set = function(key, value) {
    this[key] = value;
}

以及另一个模块中的以下枚举:

const enumeration = {
    ACTIVE: 'active',
    PENDING: 'pending',
    DONE: 'done'
}

我想知道处理枚举属性(在此处说明)setter的最佳实践/约定是什么

我可以这样做:

let myClass = new MyClass();
myClass.set('state', enumeration.PENDING);

但是有点冗长,我需要了解 myClass 模块和 enum 模块。
另一个想法是这样做:

const MyClass function MyClass() {
    this.state = null;
}

MyClass.prototype.setPending = function() {
    this.state = enumeration.PENDING;
}

并允许调用 myClass.setPending() 但是我不知道这种 setter 的正确命名。

我会选择第二个选项,因为:

  1. 避免使用硬核字符串 ('state'),我认为这总是好的。
  2. 缩短写入和读取的调用时间。
  3. 如果您决定更改行为,您是更愿意更改 setPending 函数还是每个 set 调用?

我认为第三点是最重要的一点,尽量让你的代码尽可能的可维护。

首先,我认为这个问题不是基于意见,而是基于需要。如果您说它是基于偏好的,那意味着您根本没有遇到最佳实践要避免的问题。考虑到这一点,第一个最佳实践是使其尽可能简单。 API 的发展方式取决于应用程序的具体需求以及您发现最合适需求的能力。

下面是网络 FTP 客户端上传对象的示例 "evolution of code"。请注意,有很多不同的可能路径。此示例的唯一目的是证明最佳实践不仅仅是偏好问题。

你从这个开始:

function Upload(state) {
  this.state = state || 'pending';
  this.elem = document.createElement('div');
}
new Upload().state = 'active';

然后你意识到你需要一个进度条视图来在设置状态时更新,所以你做了一个专门的 setter:

Upload.prototype.setState = function(value) {
  this.state = value;
  this.elem.className = 'state-' + this.state;
};

但是后来您决定需要显示通知,但仅当状态设置为 'done' 时。或者,也许您发现自己需要一种 shorthand 方法,因为您必须经常输入 upload.setState('done') 并且发现输入 upload.setStateDone() 更容易(参见 jQuery 的 $.get$.ajax).

Upload.prototype.setStateDone = function() {
  this.setState('done');
  // code to execute only when the state changes to 'done'
};

请注意,您可以更喜欢一致的 API 而不是方便(例如,我确实更喜欢 $.get 而不是 $.ajax 因为使用后者会产生很大的开销,但我更喜欢使用 jQuery 的 $(elem).on('click',.. 优于 $.click 因为它所做的只是预填充 'click' 字符串)。

setter 仍然存在问题:如果您设置了无效状态,例如'whatever',它会附加 class 'state-whatever',所以你更新 setState

Upload.prototype.setState = function(value) {
  if (['active', 'pending', 'done'].indexOf(value) > -1)
    this.state = value;
  this.elem.className = 'state-' + this.state;
};

问题是,你的状态是硬编码在一个方法中,你想在其他组件中重复使用它们,所以你定义了一个状态映射并调整了 setState。为了避免硬依赖,您使用依赖注入而不是在构造函数中引用全局 states 映射:

var states = {
  ACTIVE: 'active',
  PENDING: 'pending',
  DONE: 'done'
};

function Upload(state, states) {
  this.states = states;
  this.state = state || this.states.PENDING;
  this.elem = document.createElement('div');
}

Upload.prototype.setState = function(value) {
  var states = Object.keys(this.states).map(function(key) {
     return key.toLowerCase();
  });
  if (states.indexOf(value) > -1) {
    this.state = value;
  this.elem.className = 'state-' + this.state;
};

旁注中,最基本形式的 setter 只是一个将 属性 设置为对象值的函数。你做得有多具体,取决于你硬编码到 setter.

中的参数数量
function createSetter(context, prop, val) {
  switch (arguments.length) {
     case 0:
       return function(p, v) { this[p] = v; };
     case 1:
       return function(p, v) { this[p] = v; }.bind(context);
     case 2:
       return function(v) { this[prop] = v; }.bind(context);
     case 3:
       return function() { this[prop] = val; }.bind(context);
  }
}

var genericSetter = createSetter(); // any prop/val, implicit this context,
    boundSetter = createSetter({}); // any prop/val, fixed context
    propSetter = createSetter({'hello': 'world'}, 'hello') // fixed prop, any val, defined context
    propValSetter = createSetter({'hello': 'world'}, 'hello', 'dude') // fixed prop, fixed val, fixed context