携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情
方法说明
同Math.ceil方法一样,lodash里的ceil方法可以根据精度向上舍入,不同于原生的Math.ceil,lodash的ceil方法可以接收两个参数,第一个参数为数据源,第二个参数为可选参数,表示保留的位数。
两个参数以及返回值的数据类型均为数字类型。
具体用法如下:
_.ceil(4.006);
// => 5
_.ceil(6.004, 2);
// => 6.01
_.ceil(6040, -2);
// => 6100
虽然官网说明中指定的第一个参数为数字类型,但是我们依旧可以传入非数字类型:
_.ceil('1',2)
// => 1
_.ceil('1.3',2)
// => 1.3
_.ceil('1.3442',2)
// => 1.35
_.ceil('1.344s',2)
// => NaN
_.ceil([1,2,3],2)
// => NaN
可见其内部也是做了很多兼容处理。
源码实现
第一步,在没有精度的情况下(即没有第二个参数),我们直接调用原生的ceil方法即可:
function ceil(number){
return Math.ceil(number)
}
第二步,当存在精度参数的时候,我们要根据精度参数进行处理:
function ceil(number,precision){
if(precision){
let pair = `${number}e`.split('e')
const value = Math.ceil(`${pair[0]}e${+pair[1] + precision}`)
pair = `${value}e`.split('e')
return +`${pair[0]}e${+pair[1] - precision}`
}
return Math.ceil(number)
}
在这里的精度处理很巧妙,上述代码正是lodash里ceil方法对于精度的处理,我们可以看到其先是将源数字直接转换为字符串,然后拼接上字符串e。
在js中,大数据会通过科学计算法计数,带参数e,而我们通过字符分割也可以很好的处理大数字的参数部分,而无论我们传入的参数是否是大数字(大数字带e),我们取分割后的首个索引对应的值就是正确的。
输出结果则通过隐式类型转换。
上述代码正是ceil实现的核心,源码部分依旧通过工厂函数创建,并附带部分处理逻辑,在工厂函数里则通过保存Math身上的方法,在内部进行调用。(为什么是工厂函数?因为这部分的代码逻辑可以在后续的某些方法中复用。)
同时在实现上,依旧需要进行严谨性判断处理,精度范围限制在292位。
precision = precision == null ? 0 : (precision >= 0 ? Math.min(precision, 292) : Math.max(precision, -292))
下面为ceil全部的源码实现:
function createRound(methodName) {
const func = Math[methodName]
return (number, precision) => {
precision = precision == null ? 0 : (precision >= 0 ? Math.min(precision, 292) : Math.max(precision, -292))
if (precision) {
let pair = `${number}e`.split('e')
const value = func(`${pair[0]}e${+pair[1] + precision}`)
pair = `${value}e`.split('e')
return +`${pair[0]}e${+pair[1] - precision}`
}
return func(number)
}
}
const ceil = createRound('ceil')
export default ceil
小结
lodash源码对于实现ceil方法,是在原生的Math.ceil方法进行拓展,增加了精度控制处理。
源码实现上依旧遵循工厂函数返回,严谨性判断等。
此部分代码的核心在于精度控制处理,采用转字符串配合参数e切割处理,十分巧妙。