外在决定是否需要了解内在,内在决定是否会一票否决外在。内外结合,好上加好。
1.前言
开发 API 的时候,把参数的名字和位置确定下来,函数定义就可以说是完成了。因为 API 使用者来说,只需要知道如何传递参数,以及函数将返回什么样的值就够了,无需了解内部。所以参数多多少少影响了 API 的一个灵活程度和使用复杂程度。在设计 API 的时候,应该怎么设计参数,下面就简单的写下,如果大家有不同的想法,欢迎在评论区留言。
下面使用的例子,除了原生了 JQuery 的 API。其他的例子都是取自自己封装的一个常用函数库 ecDo 。欢迎提建议和 star。
2.什么时候该设置参数
其实什么时候设置参数并没什么什么说法,规范。只要觉得用参数会使得 API 的使用会更加的简单和灵活就用了。
设置参数,可能一开始不会有很好的灵感,但是在使用过程中,用得难受了,自然会像办法优化。
比如 有
ecDo.count(array|string,item)
这个 API 就是统计一个数组的每个元素的出现次数或者字符串每一个字符的个数。
这很容易实现,代码也贴下
count(arr) {
let obj = {}, k, arr1 = []
//记录每一元素出现的次数
for (let i = 0, len = arr.length; i < len; i++) {
k = arr[i];
if (obj[k]) {
obj[k]++;
} else {
obj[k] = 1;
}
}
//保存结果{el-'元素',count-出现次数}
for (let o in obj) {
arr1.push({el: o, count: obj[o]});
}
return arr1;
},
let strTest1='abbccc'
console.log(ecDo.count(strTest1));
//result:[{el: "a", count: 1},{el: "b", count: 2},el: "c", count: 3}]
复制代码
但是有些时候,开发者并不需要知道所有元素的个数,比如就需要知道
'a'
的出现次数,这个情况直接返回
'a'
的个数就行了,不需要像上面例子一样,返回一个数组。这样用起来会舒服一些,改起来也很简单,只要增加一个参数,一个判断即可。
count(arr,item) {
//重复代码略
return item?obj[item]:arr1;
},
let strTest1='abbccc'
console.log(ecDo.count(strTest1),'a');
//result:1
复制代码
还有一个常用的 API 是
ecDo.clearKeys(obj)
--清除对象中值为‘空’(null, undefined和'')的属性。
这个也很容易实现,
clearKeys(obj) {
let _newPar = {};
for (let key in obj) {
if (obj[key]===0||obj[key]===false||obj[key]) {
_newPar[key] = obj[key];
}
}
return _newPar;
},
ecDo.clearKeys({1:0,2:2,3:''})
//result:{1: 0, 2: 2}
复制代码
想必大家也发现这样写法太不灵活了,如果下次要把
0
和
false
的属性也清空呢?如果下次要把值为
'--'
的属性也清空呢?这样就做不到了,所以还要改一下,增加一个参数 clearValues - 待清空的值。
要使用的一个函数
clearKeys(obj, clearValues = [null, undefined, '']) {
clearValues.forEach((item, index) => {
clearValues[index] = Number.isNaN(item) ? 'NaN' : item
});
let _newPar = {};
for (let key in obj) {
//checkValue 看下面定义
if (!checkValue(obj[key], clearValues)) {
_newPar[key] = obj[key];
}
}
return _newPar;
},
ecDo.clearKeys({a:'',b:0,c:11})
//result:{b: 0,c: 11}
ecDo.clearKeys({a:'',b:0,c:'--'},['--',''])
//result:{b: 0}
ecDo.clearKeys({a:'',b:0,c:11,d:false},[0,''])
//result:{c: 11,d: false}
ecDo.clearKeys({a:NaN,b:2,c:undefined},[NaN,undefined])
//result:{b: 2}
复制代码
checkValue 函数
function checkValue(val, vals) {
let _val = val;
if (Number.isNaN(val)) {
_val = 'NaN'
}
return vals.indexOf(_val) !== -1;
}
复制代码
这样以来,想清除任何值的属性,这里都可以实现。
3.参数数量和前置
这两个注意点可以说是平常接触最频繁的,也是最无可辩解的。
首先参数的数量,在不影响 API 使用的情况下肯定是能少就少,越少越好。因为参数的越少,API 的记忆成本越低,调用也更加便利。
参数能少就少,越少越好,是有前提的--不影响 API 的使用。如果多个参数, API 使用能更方便,灵活,简单。多个参数就多个参。
然后参数的前置性,就是参数相关性越高,越不能省略的,就越要放在前面。虽然可以把可省略参数放后面,但是这样问题可能会很多。
4.使用对象作为参数
什么时候该使用对象作为函数的参数,暂时发现是两种情况。