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


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

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

    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 的第二个参数可以是类数组对象来实现;

    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()

    // 第一种
    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 循坏

    let i=0, a=Array(N);
    while(i

    (3)for 循环

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

    (4)Array.prototype.fill

    Array(N).fill().map((_, i) => i+1);
    

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

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

    Array(N).join().split(',').map((_, i) => i+1 );
    

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

    (6)扩展运算符

    [...Array(N).keys()].map(x => x + 1);
    
    [...Array(N+1).keys()].slice(1)
    

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

    (7)Uint8Array

    new Uint8Array(5).map((item, i) => i + 1);
    

    性能

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

    结果如下

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

    image

    参考资料

  • 相关阅读:
    课程设计 | 教学设备管理系统
    云通信接口更新迭代——SUBMAIL API V4正式上线
    Lua中文语言编程源码-第十节,更改ltm.c 元格操作函数, 使Lua加载中文库关键词(执行诸如__索引,__新索引,__加等元表操作)
    Spring中获取bean的方式
    懒加载
    STL 迭代器萃取
    腾讯云弹性公网IP是什么?EIP是什么意思?
    Spring-ApplicationContext refresh的流程
    基于Java的插件化集成项目实践
    大数据“杀熟”:我是谁,我在哪,我(被)干了啥?
  • 原文地址:https://www.cnblogs.com/zsxblog/p/17626979.html