从Element日期组件源码中学到的两个工具方法

最近翻到 ElementUI 的日期组件源码,看到一些处理日期的工具方法,挺有意思,平常没有注意到,特此记录下来。

获取当前日期的前一天,后一天

js 复制代码
export const prevDate = function(date, amount = 1) {
  return new Date(date.getFullYear(), date.getMonth(), date.getDate() - amount);
};

export const nextDate = function(date, amount = 1) {
  return new Date(date.getFullYear(), date.getMonth(), date.getDate() + amount);
};

这里获取当前日期的前一天用的是 date.getDate() - 1 而不是 date.getTime() - 24 * 60 * 60 * 1000 是为了避免在夏令时转换时导致的错误。

在某些国家,比如英国,每年都会实行夏令时制。

夏令时,又称作Daylight Saving Times(DST),是为了节省能源而人为规定的时间制度,夏天天亮得早,所以大家早起一个小时,就能多享受日光,从而减少用电量。冬天晚起一个小时,早上就能将将赶上天亮。
每年夏天的时候,英国都要把时间往前调一个小时,变成+1。比如:每年在三月最后一个周日的夜晚,时间会神奇地从00:59直接变成02:00。这就是夏令时的时间变化

所以在夏令时起止当天如果用 date.getTime() (+)- 24 * 60 * 60 * 1000 获取前一天后一天可能会导致错误。

创建包含 1-N 的数组

Element 的做法是利用 Function.prototype.apply 的第二个参数可以是类数组对象来实现;

js 复制代码
export const range = function(n) {
  return Array.apply(null, {length: n}).map((_, n) => n);
};

上面的 Array.apply(null, {length: n}) 将会创造 n 个值为 undefined 的数组,再利用 map 函数一个个改变数组值;

还有很多种实现方法,而且有比上面执行速度更快的方法;

(1)Array.from()

js 复制代码
// 第一种
Array.from(Array(N), (_, i) => i+1)

// 第二种
Array.from({length: N}, (_, i) => i + 1)

// 第三种
Array.from({length:N}, Number.call, i => i + 1)

Array.from() 可以通过 可迭代对象 和 类数组对象(带有 length 属性和索引元素的对象) 来创建数组; 并且如果 类数组对象 只有length属性没有索引元素,那么创建的数组值都为 undefined 参考

Array.from() 的第二个参数为一个可选的 mapFn,类似于数组 map 函数;但不同的是Array.from()mapFn 会对空槽元素执行回调函数 ;上面方式的比 Array.apply(null, {length: n}).map((_, n) => n); 的优势是不会创建中间数组;

第三种方法,第三个参数是一个函数,会被 Number.call 当作 this 调用

(2)while 循坏

js 复制代码
let i=0, a=Array(N);
while(i<N) a[i++]=i;

(3)for 循环

js 复制代码
var foo = [];

for (var i = 1; i <= N; i++) {
   foo.push(i);
}

(4)Array.prototype.fill

js 复制代码
Array(N).fill().map((_, i) => i+1);

Array.from() 类似,Array(N).fill() 也会创建 N 个值为 undefined 的数组;

(5)Array(N).join().split(',')

js 复制代码
Array(N).join().split(',').map((_, i) => i+1 );

Array(N) 会创建 N 个空槽组成的数组,空槽既不是 undefined,也不是空字符串;并且 map 也不会对空槽元素执行回调函数,所以需要通过 Array(N).join().split(',') 将会得到 N 个字符串组成的数组;

(6)扩展运算符

js 复制代码
[...Array(N).keys()].map(x => x + 1);

[...Array(N+1).keys()].slice(1)

[...Array(N)] 扩展运算符会将空槽元素转化为 undefined

(7)Uint8Array

js 复制代码
new Uint8Array(5).map((item, i) => i + 1);

性能

对以上方式进行性能测试,测试工具是 jsbench ,测试的的浏览器版本是谷歌 115.0.5790.110(正式版本) (64 位)

结果如下

设置初始值 N 为 1000000,ops 为每秒操作数,图中结果按照从高到低排序;while 循环最快

参考资料

相关推荐
徊忆羽菲20 分钟前
Echarts3D柱状图-圆柱体-文字在柱体上垂直显示的实现方法
javascript·ecmascript·echarts
轻语呢喃30 分钟前
JavaScript :字符串模板——优雅编程的基石
前端·javascript·后端
coding随想43 分钟前
JavaScript中的BOM:Window对象全解析
开发语言·javascript·ecmascript
難釋懷44 分钟前
TypeScript-webpack
javascript·webpack·typescript
Rockson1 小时前
使用Ruby接入实时行情API教程
javascript·python
前端小巷子2 小时前
Web开发中的文件上传
前端·javascript·面试
上单带刀不带妹3 小时前
手写 Vue 中虚拟 DOM 到真实 DOM 的完整过程
开发语言·前端·javascript·vue.js·前端框架
前端风云志3 小时前
typescript结构化类型应用两例
javascript
gnip4 小时前
总结一期正则表达式
javascript·正则表达式
爱分享的程序员4 小时前
前端面试专栏-算法篇:18. 查找算法(二分查找、哈希查找)
前端·javascript·node.js