首先,我认为这个问题不是意见,而是
基于需求
. 如果你说它是基于偏好的,那意味着你根本没有遇到建立最佳实践以避免的问题。考虑到这一点,第一个最佳做法是尽可能简单。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