代码之家  ›  专栏  ›  技术社区  ›  Simon Bruneaud

类枚举设置器,约定javascript

  •  0
  • Simon Bruneaud  · 技术社区  · 7 年前

    嗨,我有以下课程:

    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() 但我不知道这种二传手的正确命名。

    2 回复  |  直到 7 年前
        1
  •  1
  •   webketje    7 年前

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

    下面是web FTP客户端上载对象的“代码演变”示例。注意,有许多不同的可能路径。这个例子的唯一目的是证明最佳实践不仅仅是偏好问题。

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

    然后,您意识到需要一个progressbar视图来在设置状态时进行更新,因此您需要一个专门的setter:

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

    然而,稍后您决定需要显示通知,但仅当状态设置为“完成”时。或者你发现自己需要一种速记方法,因为你必须打字 upload.setState('done') upload.setStateDone() 更容易(参见jQuery $.get vs $.ajax

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

    注意,您可以选择一致的API而不是方便性(例如,我确实更喜欢 $.收到 $.ajax $(elem).on('click',.. $.click 因为它所做的只是预先填充“click”字符串)。

    setter仍然存在一个问题:如果您设置了无效的状态,例如“whatever”,它将附加类“state whatever”,因此您需要更新 setState

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

    设置状态 . 为了避免硬依赖,您使用依赖注入,而不是引用全局 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
    
        2
  •  1
  •   Isidrok    7 年前

    我会选择第二种选择,因为:

    1. 避免使用硬核字符串(“state”),我认为这总是好的。
    2. 如果您决定更改行为,您愿意更改setPending函数还是更改每个set调用?