• 机构投资者应合理审慎报价 2019-07-16
  • “2018上影之夜”姜文等为“谢晋经典电影回顾展”揭幕 2019-07-10
  • 交大钱学森学院举行毕业典礼 14毕业生赴世界排名前百大学读研 2019-07-10
  • 西安市:构建“五方联动”社会治理新格局 2019-06-23
  • IP定向--云南频道--人民网 2019-06-23
  • 育儿十大坎 新手妈妈快快get起来 2019-06-21
  • 吉林:让更多农村孩子参加少年宫活动 2019-06-21
  • 美国发起贸易战,我们要让世界知道美元、美债并不可靠 2019-06-05
  • 紫光阁中共中央国家机关工作委员会 2019-05-31
  • 监察体制改革后 湘西半年72名公职人员主动交代问题 2019-05-12
  • 媒体宣传报道重庆日报 王国平:扮靓重庆两江四岸” 让城市有机更新 2019-04-26
  • 我相信“交警雨中护送高考生”是真,“交警雨中护送高考生”反被该高考生家长投诉是假。 2019-04-16
  • 14名消防员日巡逻28公里 洗冷水澡 2019-04-10
  • 靶壕有了“蓝军”,百发百中的“神枪手”练起来 2019-04-10
  • 不是秀强大了,别人就会来做朋友,这逻辑不对 2019-04-01
  • 频道栏目
    神奇公式秒杀全国11选5 > 程序开发 > web前端 > HTML/CSS > 正文
    What'sNewinJavaScript-ThinkJS-SegmentFault思否
    2019-05-11 22:05:10           
    收藏   我要投稿

    \

    前几天 Google IO 上 V8 团队为我们分享了《What's New in JavaScript》主题,分享的语速很慢推荐大家可以都去听听就当锻炼下听力了??赐曛笪艺砹艘桓鑫淖职姘镏蠹铱焖倭私夥窒砟谌?,嘉宾主要是分享了以下几点:

    JS 解析快了 2 倍 async 执行快了 11 倍 平均减少了 20% 的内存使用 class fileds 可以直接在 class 中初始化变量不用写在 constructor 里 私有变量前缀 string.matchAll 用来做正则多次匹配 numeric seperator 允许我们在写数字的时候使用 _ 作为分隔符提高可读性 bigint 新的大数字类型支持 Intl.NumberFormat 本地化格式化数字显示 Array.prototype.flat(), Array.prototype.flatMap() 多层数组打平方法 Object.entries() 和 Object.fromEntries() 快速对对象进行数组操作 globalThis 无环境依赖的全局 this 支持 Array.prototype.sort() 的排序结果稳定输出 Intl.RelativeTimeFormat(), Intl.DateTimeFormat() 本地化显示时间 Intl.ListFormat() 本地化显示多个名词列表 Intl.locale() 提供某一本地化语言的各种常量查询 顶级 await 无需写 async 的支持 Promise.allSettled() 和 Promise.any() 的增加丰富 Promise 场景 WeakRef 类型用来做部分变量弱引用减少内存泄露

    Async 执行比之前快了11倍

    神奇公式秒杀全国11选5 www.2zfa.com 开场就用 11x faster 数字把大家惊到了,也有很多同学好奇到底是怎么做到的。其实这个优化并不是最近做的,去年11月的时候 V8 团队就发了一篇文章 《Faster async functions and promises》,这里面就非常详尽的讲述了如何让 async/await 优化到这个速度的,其主要归功于以下三点:

    TurboFan:新的 JS 编译器 Orinoco:新的 GC 引擎 Node.js 8 上的一个 await bug

    2008年 Chrome 出世,10年 Chrome 引入了 Crankshaft 编译器,多年后的今天这员老将已经无法满足现有的优化需求,毕竟当时的作者也未曾料想到前端的世界会发展的这么快。关于为何使用 TurboFan 替换掉 Crankshaft,大家可以看看《Launching Ignition and TurboFan》,原文中是这么说的:

    Crankshaft 仅支持优化 JavaScript 的一部分特性。它并没有通过结构化的异常处理来设计代码,即代码块并没有通过try、catch、finally等关键字划分。另外由于为每一个新的特性Cranksshaft都将要做九套不同的框架代码适应不同的平台,因此在适配新的Javascript语言特性也很困难?;褂蠧rankshaft框架代码的设计也限制优化机器码的扩展。尽管V8引擎团队为每一套芯片架构维护超过一万行代码,Crankshaft也不过为Javascript挤出一点点性能。
    via:《Javascript是如何工作的:V8引擎的内核Ignition和TurboFan》

    而 TurboFan 则提供了更好的架构,能够在不修改架构的情况下添加新的优化特性,这为面向未来优化 JavaScript 语言特性提供了很好的架构支持,能让团队花费更少的时间在做处理不同平台的特性和编码上。从原文的数据对比中就可以看到,仅仅是换了个编译器优化就在 8 倍左右了…… 给 V8 的大佬们跪下了。

    \

    而 Orinoco 新的 GC 引擎则是使用单独线程异步去处理,让其不影响 JS 主线程的执行。至于最后说的 async/await 的 BUG 则是让 V8 团队引发思考,将 async/await 原本基于 3 个 Promise 的实现减少成 2 个,最终减少成 1 个!最后达到了写 async/await 比直接写 Promise 还要快的结果。

    我们知道 await 后面跟的是 Promise 对象,但是即使不是 Promise JS 也会帮我们将其包装成 Promise。而在 V8 引擎中,为了实现这个包装,至少需要一个 Promise,两个微任务过程。这个在本身已经是 Promise 的情况下就有点亏大发了。而为了实现 async/await 在 await 结束之后要重新原函数的上下文并提供 await 之后的结果,规范定义此时还需要一个 Promise,这个在 V8 团队看来是没有必要的,所以他们建议规范去除这个特性。

    最后的最后,官方还建议我们:多使用 async/await 而不是手写 Promise 代码,多使用 JavaScript 引擎提供的 Promise 而不是自己去实现。

    Numeric Seperator

    随着 Babel 的出现,JS 的语法糖简直不要太多,Numeric Seperator 算是一个。简单的说来它为我们手写数字的时候提供给了分隔符的支持,让我们在写大数字的时候具有可读性。

    \

    其实是个很简单的语法糖,为什么我会单独列出来说呢,主要是因为它正好解决了我之前一个实现的痛点。我有一个需求是一堆文章数据,我要按照产品给的规则去插入广告。如图非红框是文章,红框处是广告。由于插入规则会根据产品的需(心)求(情)频繁变化,所以我们最开始使用了两个变量进行标记:

    const news = [1, 3, 5, 6, 7, 9, 10, 11];
    const ads = [2, 4, 8, 12];

    \

    当位置发生变化的时候我们就需要同时对两个变量进行修改,这样导致了维护上的成本。所以我想了一个办法,广告的位置标记为 1,文章的位置标记为 0,使用纯二进制的形式来表示个记录,这样子就变成了:

    +---+---+---+
    | 0 | 1 | 0 |
    +---+---+---+
    | 1 | 0 | 0 |
    +---+---+---+
    | 0 | 1 | 0 |
    +---+---+---+
    | 0 | 0 | 1 |
    +---+---+---+
    
    1 011 010 100 010 001
    // 首位为常量 1
    // 2-4 位记录一行多少条
    // 后续按照新闻和广告的位置进行记录

    最后我们使用一个变量 0b1011010100010001 就完成了两种信息的记录。这样做将很多数据集成在了一起解决了我们之前的问题,但是它带来了新的问题,大家也可以看到注释中按照空格劈开的话大家看的还比较明白,但是在段头将空格去除之后在阅读程度上就造成了非常大的困难了。而数字分隔符这个语法糖正好就能解决这个问题,0b1_011_010_100_010_001 这样阅读起来就好很多了。

    Promise

    虽然在大部分的场景 async/await 都可以了,但是不好意思 Promise 有些场景还是不可替代的。Promsie.all() 和 Promise.race() 就是这种特别的存在。而 Promise.allSettled() 和 Promise.any() 则是新增加的方法, 相较于它们的前辈,这俩拥有忽略错误达到目的的特性。

    我们之前有一个需求,是需要将文件安全的存储在一个存储服务中,为了灾备我们其实有两个 S3,一个 HBase 还有本地存储。所以每次都需要诸如以下的逻辑:

    for(const service of services) {
      const result = await service.upload(file);
      if(result) break;
    }

    但其实我并不关心错误,我的目的是只要保证有一个服务最终能执行成功即可,所以 Promise.any() 其实就可以解决这个问题。

    await Promise.any( services.map(service => service.upload(file)) );

    Promise.allsettled() 和 Promise.any() 的引入丰富了 Promise 更多的可能性。说不定以后还会增加更多的特性,例如 Promise.try(), Promise.some(), Promise.reduce() ...

    WeakRef

    WeakRef 这个新类型我最开始是不太理解的,毕竟我总感觉 Chrome 已经长大了,肯定会自己处理垃圾了。然而事情并没有我想的那么简单,我们知道 JS 的垃圾回收主要有“标记清除”和“引用计数”两种方法。引用计数是只要变量多一次引用则计数加 1,少一次引用则计数减 1,当引用为 0 时则表示你已经没有利用价值了,去垃圾站吧!

    在 WeakRef 之前其实已经有两个类似的类型存在了,那就是 WeakMap 和 WeakSet。以 WeakMap 为例,它规定了它的 Key 必须是对象,而且它的对象都是弱引用的。举个例子:

    //map.js
    function usageSize() {
      const used = process.memoryUsage().heapUsed;
      return Math.round(used / 1024 / 1024 * 100) / 100 + 'M';
    }
    
    global.gc();
    console.log(usageSize()); // ≈ 3.23M
    
    let arr = new Array(5 * 1024 * 1024);
    const map = new WeakMap();
    
    map.set(arr, 1);
    global.gc();
    console.log(usageSize()); // ≈ 43.22M
    
    arr = null;
    global.gc();
    console.log(usageSize()); // ≈ 43.23M
    //weakmap.js
    function usageSize() {
      const used = process.memoryUsage().heapUsed;
      return Math.round(used / 1024 / 1024 * 100) / 100 + 'M';
    }
    
    global.gc();
    console.log(usageSize()); // ≈ 3.23M
    
    let arr = new Array(5 * 1024 * 1024);
    const map = new WeakMap();
    
    map.set(arr, 1);
    global.gc();
    console.log(usageSize()); // ≈ 43.22M
    
    arr = null;
    global.gc();
    console.log(usageSize()); // ≈ 3.23M

    分别执行 node --expose-gc map.js 和 node --expose-gc weakmap.js 就可以发现区别了。在 arr 和 Map 中都保留了数组的强引用,所以在 Map 中简单的清除 arr 变量内存并没有得到释放,因为 Map 还存在引用计数。而在 WeakMap 中,它的键是弱引用,不计入引用计数中,所以当 arr 被清除之后,数组会因为引用计数为0而被回收掉。

    正如分享中所说,WeakMap 和 WeakSet 足够好,但是它要求键必须是对象,在某些场景上不太试用。所以他们暴露了更方便的 WeakRef 类型。在 Python 中也存在 WeakRef 类型,干的事情比较类似。其实我们主要注意 WeakRef 的引用是不计引用计数的,就好理解了。例如 MDN 中所说的引用计数没办法清理的循环引用问题:

    function f(){
      var o = {};
      var o2 = {};
      o.a = o2; // o 引用 o2
      o2.a = o; // o2 引用 o
    
      return "azerty";
    }
    
    f();

    如果试用 WeakRef 来改写,由于 WeakRef 不计算引用计数,所以计数一直为 0,在下一次回收中就会被正?;厥樟?。

    function f() {
      var o = new WeakRef({});
      var o2 = o;
      o.a = o2;
    
      return "azerty";
    }
    
    f();

    在之前的一个多进程需求中,我们需要将子进程中的数据发送到主进程中,我们使用的方式是这样写的:

    const metric = 'event';
    global.DATA[metric] = {};
    
    process.on(metric, () => {
      const data = global.DATA[metric];
      delete global.DATA[metric];
      return data;
    });

    代码就看着比较怪,由于 global.DATA[metric] 作为强引用,如果直接在事件中 return global.DATA[metric] 的话,由于存在引用计数,那么这个全局变量是一直占用内存的。此时如果使用 WeakRef 改写一下就可以减少 delete 的逻辑了。

    const metric = 'event';
    global.DATA[metric] = new WeakRef({});
    
    process.on(metric, () => {
      const ref = global.DATA[metric];
      if(ref !== undefined) {
        return ref.deref();
      }
      return ref;
    });

    后记

    除了我上面讲的几个特性之外,还有很多其他的特性也非常一颗赛艇。例如 String.matchAll() 让我们做多次匹配的时候再也不用写 while 了!Intl 本地化类的支持,让我们可以早日抛弃 moment.js,特别是 RelativeTimeFormat 类真是解放了我们的生产力,不过目前接口的配置似乎比较定制化,不知道后续的细粒度需求支持情况会如何。

    参考资料:

    《ES proposal: numeric separators》 《内存管理》 《ES6 系列之 WeakMap》
    点击复制链接 与好友分享!回本站首页
    相关TAG标签
    上一篇:10个有趣的javascript和css库(2019年最新)-CSS技术学习-SegmentFault思否
    下一篇:最后一页
    相关文章
    图文推荐
    点击排行

    关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 神奇公式秒杀全国11选5

    版权所有: 神奇公式秒杀全国11选5--致力于做实用的IT技术学习网站

  • 机构投资者应合理审慎报价 2019-07-16
  • “2018上影之夜”姜文等为“谢晋经典电影回顾展”揭幕 2019-07-10
  • 交大钱学森学院举行毕业典礼 14毕业生赴世界排名前百大学读研 2019-07-10
  • 西安市:构建“五方联动”社会治理新格局 2019-06-23
  • IP定向--云南频道--人民网 2019-06-23
  • 育儿十大坎 新手妈妈快快get起来 2019-06-21
  • 吉林:让更多农村孩子参加少年宫活动 2019-06-21
  • 美国发起贸易战,我们要让世界知道美元、美债并不可靠 2019-06-05
  • 紫光阁中共中央国家机关工作委员会 2019-05-31
  • 监察体制改革后 湘西半年72名公职人员主动交代问题 2019-05-12
  • 媒体宣传报道重庆日报 王国平:扮靓重庆两江四岸” 让城市有机更新 2019-04-26
  • 我相信“交警雨中护送高考生”是真,“交警雨中护送高考生”反被该高考生家长投诉是假。 2019-04-16
  • 14名消防员日巡逻28公里 洗冷水澡 2019-04-10
  • 靶壕有了“蓝军”,百发百中的“神枪手”练起来 2019-04-10
  • 不是秀强大了,别人就会来做朋友,这逻辑不对 2019-04-01
  • 华东15选5加奖 羽毛球网如何安装图解 内蒙古时时彩最快开奖 香港六合彩官网 3d澳客网专家杀号 趣玩十三水 新快3游戏下载 6粒复式二中二多少组 北京快中彩基本走势图 特码部三肖中特会员料 河北十一选五基本走势图 qq刮刮乐活动 极速快乐十分遗漏 福建时时彩诈骗团伙 快中彩玩法