微信号:gh_bd8d6a989787

介绍:介绍各种前端技巧,帮助提高前端开发的速度,逐渐做到分分钟完成开发.

未来的JavaScript还缺少哪些特性?(1)

2019-04-08 08:30 web前端程序员

近年来,JavaScript的规模有了很大的增长。这篇博客文章主要探讨了它还缺少什么特性。

备注:

  1. 我只列出了我认为最重要的一些缺失的特性。其他许多特性也很有用,但是增加过多也存在风险。

  2. 我的选择是主观的。

  3. 这篇博文中提到的几乎所有事情都在TC39(Technical Committee 39,是一个推动JavaScript发展的委员会。)的规划范围之内。也就是说,它还可以作为一个可能的未来JavaScript的预览。

有关前两个问题的更多想法,请参见有关“语言设计”一节。

  • 1. 值

  • 1.1. 按值比较对象

目前,JavaScript仅按值比较原始值,如字符串(通过查看它们的内容):

相比之下,对象是通过标识符进行比较的(一个对象只严格等于它自己):

如果有一种方法可以创建按值比较的对象,那就太好了:

另一种可能性是引入一种新的类(具体细节待定):


备注: 将类标记为值类型的类似于decorator的语法是基于一个草案提案

1.2. 将对象放入数据结构中

由于对象是通过标识符进行比较的,所以将它们放入(非弱类型的)ECMAScript数据结构中没多大意义,比如Map:

这个问题可以通过自定义值类型来解决。或者,可以定制集合元素和映射键的管理。例如:

  • 通过哈希表映射: 需要一个操作来检查等式,另一个操作来创建哈希代码。如果您使用哈希代码,那么您会希望对象是不可变的。否则,很容易破坏数据结构。

  • 通过排序树映射: 需要一个比较两个值的操作,以管理它存储的值。

1.3. 大整数

JavaScript的数字总是64位(双精度),这就为正整数提供了53位增加位。这意味着超过53位之后,您就不能再表示任何的数字了:

对于某些用例,这是一个相当大的限制。现在有一个关于BigInt的提案,它的精度会随需要的增加而增加:

BigInt也支持casting(截断),它会返回一个固定位数的值:

1.4. 小数计算

JavaScript的数字是64位浮点数(双精度浮点数),基于IEEE 754标准。假设它们的表示是二进制,那么在处理分数时,会得到舍入误差:

这在科学计算和金融技术(fintech)中尤其是个问题。10进制数字的提案目前处于0阶段。它们可能最终被这样使用(注意小数的后缀m):

1.5. 对值进行分类

目前,在JavaScript中对值进行分类非常麻烦:

  1. 首先,您必须决定是使用typeof还是instanceof

  2. 其次,typeof有一个众所周知的怪癖,它会将null分类为“object”。我认为将函数归类为“function”'也是一种怪癖。


3.instanceof不适用于来自其他领域(框架等)的对象。

可以通过库来解决这个问题(一旦有时间,我将创建一个概念证明)。

2. 函数式编程  

2.1 Do-表达式 

C风格的语言对表达式和语句之间的区分不是很清楚:

特别是在函数式语言中,一切都是表达式。Do-表达式允许您在所有表达式上下文中使用语句:

switch也可以在do-expression中工作:

Do-expression有助于消除立即调用函数表达式(IIFEs)的最后一个主要用例: 将“静态”数据附加到函数。

举个例子,这段代码使用了一个IIFE来这样做:

使用一个do-expression,您就不需要IIFE了:

2.2. 匹配: 一个析构switch

在JavaScript中直接处理对象是很容易的。但是,没有基于对象结构的内置开关用例(switching over cases)方法。这看起来会像这样(来自提案的例子):

可以看到,新的case语句在某些方面类似于switch,而不是使用析构来选择case。当处理嵌套数据结构(例如在编译器中)时,这种功能就非常有用。 这个模式匹配提案目前处于第1阶段。

2.3. 管道操作符

目前,针对管道操作符有两项相互竞争的提案。这里,我们来看一下Smart Pipelines  (另一个提案称为F# Pipelines)。

管道操作符的基本思想如下。考虑一下以下嵌套函数调用。

然而,这种表示法通常不会反映我们是如何考虑计算步骤的。直觉上,我们把它们描述为:

  • 从值x开始。

  • 然后对它应用f()。

  • 然后对结果应用g()。

  • 然后对结果应用h()。

  • 然后将结果赋给y。

管道操作符让我们更好地表达这种直觉:

换句话说,下面两个表达式是等价的。

此外,管道操作符支持partial application (偏函数应用)(类似于函数的.bind()方法):下面两个表达式是等价的。

管道操作符的一个重要好处是,您可以像使用方法一样使用函数—而不需要更改任何原型:

最后,我们来看一个更长的例子(摘自提案,并稍作修改):

3. 并发

JavaScript对并发性的支持总是有限的。并发进程的实际标准是Worker API,它可以在web浏览器和Node.js中使用(在v11.7和更高版本中没有标识)。

从Node.js来使用它看起来如下。

唉,worker线程运行起来是相对重量级的——每个线程都有自己的范围(全局变量等)。我希望在未来看到一个更轻量级的构造。

4. 标准库 

JavaScript明显落后于其他语言的一个方面是它的标准库。将其最小化是有意义的,因为外部库更容易演化和适应。当然,有一些核心功能是很有用的。

4.1. 模块代替命名空间对象  

JavaScript的标准库是在该语言拥有模块之前就创建的。因此,函数是放在命名空间对象中的,比如Object、Reflect、MathJSON:

  • Object.keys()

  • Reflect.ownKeys()

  • Math.sign()

  • JSON.parse()

如果这个功能可以放在模块中,那就太好了。它将必须通过特殊的URL访问,例如使用伪协议std:

这样的好处是:

  • JavaScript将变得更加模块化(这可以加快启动时间,减少内存消耗)。

  • 调用导入的函数比调用存储在对象中的函数要更快。

4.2. 迭代器助手 ( 同步和异步)  

迭代器的好处包括按需计算值和支持多个数据源。然而,JavaScript目前只提供了很少的工具来处理迭代器。例如,如果您想过滤,映射或缩减一个迭代器,您必须把它转换成一个数组:

如果JavaScript有处理迭代器的工具函数,您可以直接过滤迭代器:

下面是一些迭代器工具函数的例子:

备注:

  • 有关迭代器的工具函数示例,请参考Python的迭代工具

  • 对于JavaScript,用于迭代器的每个工具函数都应该有两个版本:一个用于同步迭代器,另一个用于异步迭代器。

4.3. 不可变数据

如果有更多对非破坏性数据转换的支持就好了。有两个相关的库是:

  • Immer相对较轻量级,可以处理普通对象和数组。

  • Immutable .js更强大、更重量级,并且有自己的数据结构。

4.4. 更好地支持日期时间

JavaScript对日期时间的内置支持有很多怪癖。这就是为什么当前的建议是除了最基本的任务外,所有任务都使用库。

值得庆幸的是,一个更好的日期时间API( temporal)正在开发中:

5. 可能不需要的特性

5.1. 自判断链接的优缺点

自判断链接是提出的一个相对流行的特性。下面两个表达式是等价的。

这个特性对于属性链特别方便:

然而,这个功能也有缺点:

  • 深度嵌套结构更难管理。

  • 在访问数据时表现得如此宽容,隐藏了一些问题,这些问题将在很长一段时间后暴露出来,会变得很难调试。

自判断链接的另一种替代方法是在一个单独的地方提取一次信息:

  • 您可以编写一个助手函数来提取数据。

  • 或者您可以编写一个函数,其输入是深度嵌套的数据,其输出是更简单的标准化的数据。

使用任何一种方法,都可以来执行检查,如果出现问题,可以尽早中断。

延伸阅读:

  • Carl Vitullo 的 “过度防御性编程” 

  • Cory House发布在 Twitter上的帖子

5.2. 我们需要运算符重载吗?  

运算符重载的早期工作目前正在进行中,但有中缀函数应用就已经足够了(不过,目前还没有对此的提案):

中缀函数应用的好处是:

  • 您可以创建JavaScript已经支持的操作符之外的操作符。

  • 与普通函数应用相比,嵌套表达式更容易保持可读性。

这是一个嵌套表达式的例子:

有趣的是,管道操作符也有助于可读性:

英文原文:http://2ality.com/2019/01/future-js.html

译者:一瞬
 
web前端程序员 更多文章 预加载、预取和其他<link>标记 JavaScript生态系统总览(1) 我并不讨厌箭头函数 你不需要jQuery 来,写微信小程序,赚3240元酬金
猜您喜欢 2014 年最后一期源创会(广州)开始报名【开源中国准备自曝家丑了】 Python制作快递查询系统,再一次感受到了Python的强大! 【活动最后一周】5月31日前做好新招牌,额外送2345公益彩票+实物礼包! GopherCon China 2016晚场见闻 很多初创公司,一聊到财务就有点懵