未来的4种革命性JavaScript功能

自ECMAScript 6(ES6)标准发布以来,JavaScript迅速,动态地发展了。由于现在每年都会发布新版本的ECMA-262标准,并且由于所有浏览器制造商的辛勤工作,JS已成为世界上最受欢迎的编程语言之一。



我最近写了关于ES2020中引入的新功能的文章...尽管其中一些机会很有趣,但没有一个机会值得称为“革命性”。鉴于JS规范最近经常更新的事实,这是可以理解的。事实证明,使用该标准的人很少有机会不断地向语言中引入一些特殊的东西,例如ES6模块或箭头函数。 但这并不意味着某些新事物最终不会出现在该语言中。事实上,这就是我今天要谈的。从长远来看,我想谈谈四种可能被称为革命性的可能性。他们现在处于流程的不同阶段







提案协调。一方面,这意味着我们可能永远不会在JavaScript中看到它们,也看不到它们;另一方面,此类句子的出现使我们希望,尽管有一天,我们仍会以该语言与它们相遇。



装饰工



我们将从可能是该语言中最常要求提供的功能开始,围绕该功能已经引起了很多关注。几年前,他们几乎到处都在写关于她的文章。我们在谈论装饰



您可能已经熟悉装饰器。特别是如果您使用TypeScript编写。从本质上讲,它是一个元编程概念,旨在使开发人员能够将自己的功能“注入”到类,其各自的字段和方法中,最终使类成为可编程的。



看下面的例子:



function sealed(constructor: Function) {
  Object.seal(constructor);
  Object.seal(constructor.prototype);
}

@sealed
class Greeter {
  greeting: string;
  constructor(message: string) {
    this.greeting = message;
  }
  greet() {
    return "Hello, " + this.greeting;
  }
}


在这里,我决定谨慎行事,并给出了使用TypeScript装饰器的示例。我这样做主要是为了展示总体思路。在以上代码片段中,我们创建了一个装饰器sealed并将其应用于class Greeter。如您所见,装饰器只是一个函数,可以访问要应用它的类的构造函数(这是目标)。我们使用对构造函数的引用,以及Object.seal()使类不可扩展的方法。



为了将装饰器应用于类,我们@在类声明之前用图标写装饰器的名称。结果是类声明的前面出现了类型设计@[name],在我们的例子中,它看起来像@sealed



您可以通过在启用该选项的情况下编译此TS代码experimentalDecorators并尝试更改类原型来检查装饰器的功能



Greeter.prototype.test = "test"; // ERROR


因此,您现在应该对为什么需要装饰器有了一个大致的了解。但是,我想在这里谈一个困难的问题。它涉及装饰提案的批准状态。



我决定使用TypeScript演示装饰器是有充分的理由的。关键是几年前就提出了在JavaScript中嵌入装饰器的建议。现在,它仅是协议第2阶段中的“第二阶段”。此提议中装饰器的语法和功能都在不断变化。但这并不能阻止JS社区使用此概念。为了确信这一点,看一下像TypeScript或Angular v2 +这样的大型开源项目就足够了。



没错,随着时间的推移,随着提案的发展,所有这些都会导致与规范不兼容相关的问题。即,自提出提案以来,装饰器规范已经发展了很多,但是许多项目仍未实现它。上面显示的TypeScript示例演示了该提案的较旧版本的实现。关于Angular,甚至关于Babel,也可以这样说(尽管就Babel而言,我们可以说正在努力实现该规范的更新版本)。通常,使用decorator适合链接的关键字和语法的句子的较新版本尚未发现任何明显的用途。



底线是装饰器有可能改变我们编写代码的方式。即使装饰者仍处于早期阶段,这些变化也已经显现出来。但是,考虑到当前的状况,装饰者只会使社区变得支离破碎,而且我相信他们还没有准备好进行认真的使用。我建议那些对装饰感兴趣的人稍等一下,然后再将其投入生产。但是,我的建议不适用于那些使用装饰器的框架(例如Angular)的框架。



境界



现在,让我们放慢一点,并谈谈一个不像装饰器那么复杂的功能。我们在谈论领域



您可能已经处在需要运行自己的代码或第三方代码的情况下,但同时又以这种代码不会影响全局环境的方式进行操作。许多库,尤其是浏览器库,都是通过global对象工作的window。结果,如果项目使用了太多不受开发人员控制的库,它们可能会相互干扰。这可能导致错误。



当前浏览器解决此问题的方法是使用元素<iframe>,在某些特殊情况下-使用网络工作者。在Node.js环境中,使用模块vm子进程可以解决相同的问题。 Realms API旨在解决此类问题。



该API旨在允许开发人员创建称为作用域的单独的全局环境。每个此类区域都有其自己的全球实体。看下面的例子:



var x = 39;
const realm = new Realm();

realm.globalThis.x; // undefined
realm.globalThis.x = 42; // 42
realm.globalThis.x; // 42

x; // 39


在这里,我们Realm使用适当的构造函数创建一个新对象。从现在开始,我们可以通过属性globalThis(在ES2020中引入)完全访问新范围及其全局对象。在这里,您可以看到主要“孵化器”的变量与我们创建的范围中的变量分开。



总体而言,Realms API被计划为一种非常简单的机制,但它是一种有用的机制。该API有一组非常特定的用例。它并不能为我们提供更高的安全性,也不能提供多线程代码的功能。但这完美地完成了主要任务,并提供了创建隔离环境的基本功能,而又不会在系统上造成不必要的负载。



目前,Realms API提案处于协商的第二阶段。当它最终达到标准时,人们希望它会在依赖于全局范围的“繁重”库中,在线沙盒代码编辑器中,针对各种应用程序中使用测试。



做表情



与大多数编程语言的语法一样,JavaScript语法包括语句和表达式。这些构造之间最明显的区别是,表达式可以用作值(即可以将它们分配给变量,传递给函数等),而语句不能这样使用。



由于这种区别,表达式是更简洁,更紧凑的代码的首选。在JavaScript中,如果您分析函数表达式的流行性(包括箭头函数,函数声明和函数语句),就可以看到这一点。如果我们比较遍历数组的方法(例如forEach())的循环。比较三元运算符和语句时,更高级的程序员也是如此if目前正处于谈判阶段1



do-expression提案旨在进一步增强JS表达式的功能。顺便说一句,不要将“ do-expression”的概念与循环混淆do…while,因为它们是完全不同的东西。



这是一个例子:



let x = do {
  if (foo()) {
    f();
  } else if (bar()) {
    g();
  } else {
    h();
  }
};


这是do-expression子句的语法。总的来说,我们前面有一段包装在构造中的JS代码do {}。此构造中的最后一个表达式作为整个do表达式的最终值“返回”。



使用IIFE(立即调用函数表达式)可获得相似(但不完全相同)的效果。但是对于do表达式,它们的紧凑语法似乎非常吸引人。在这里,具有类似的功能,您不需要return或任何丑陋的辅助结构,例如(() => {})()... 这就是为什么我相信一旦表达式成为标准,它们对JavaScript的影响将与箭头函数相当。可以说,便捷的表达方式和友好的语法看起来很诱人。



模式匹配



这次机会是本材料中的最后一个机会,但其重要性远非最后一次。这是一个旨在将模式匹配机制引入语言的提议



您可能熟悉JS指令switch它与相似if-else,但是其选项略有限制,并且它当然更适合组织许多替代方案之一的选择。看起来是这样的:



switch (value) {
  case 1:
    // ...
    break;
  case 2:
    // ...
    break;
  case 3:
    // ...
    break;
  default:
    // ...
    break;
}


我个人认为一条指令switch比一条指令弱if,因为它switch只能将传递给它的值与特定值进行比较。可以绕开此限制,但我不知道为什么。此外,该指令还switch带有辅助元素。特别是,我们正在谈论说明break



模式匹配机制可以被认为是一种功能更强大,基于表达式且可能更通用的语句版本switch。模式匹配机制不仅可以简单地比较值,还可以使开发人员针对高度可定制的自定义模式(模板)进行值比较。这是一个代码段,展示了所建议的API的示例:



const getLength = vector => case (vector) {
  when { x, y, z } -> Math.hypot(x, y, z)
  when { x, y } -> Math.hypot(x, y)
  when [...etc] -> vector.length
}
getLength({x: 1, y: 2, z: 3})


它使用了一种非常不常见的JavaScript语法(尽管它基于RustScala等语言中发现的语法),它与我们已经知道的指令具有一些共同的特征switch。这里,取代的关键字,一个字switch被用于case将标记,其中所述值被检查的块的开头。然后,在块内,使用关键字when,我们描述了用来验证值的模板。模板的语法类似于该语言中已经可用的对象解构机制的语法。您可以将值与包含选定属性的对象进行比较,可以将它们与对象以及许多其他实体的属性值进行比较。要了解有关此机制的更多信息,请参阅文档。



在模板描述之后,有一个箭头(“扁平箭头” ->)指向表达式(透视中-甚至指向不同的值),当找到与模式的匹配项时应对其进行评估。



我相信JS中这种功能的存在将使我们可以编写新一代代码。但是,现在提出的语法对我来说有点麻烦,因为它在语言中引入了许多全新的构造。而且该提案仍处于批准的第一阶段,这使我认为它仍有改进的余地。该功能看起来非常有前途,但是要使其成为正式的JS规范,还有很长的路要走。



结果



这结束了我有关JavaScript革命性功能的故事,我们将来可能会在该语言中看到它。还有其他类似的可能性,例如关于外部标准库流水线运算符的建议。但是我只选择了对我来说最有趣的东西。请记住,这些机会仍处于建议阶段。它们可以随着时间而改变。否则,它们可能永远都没有成为标准。但是,无论如何,如果您想和其他人一起利用这些机会,我建议您仔细看看Babel等项目... 这些项目催生了许多JS建议(尤其是与语法有关的建议)。这样,任何人都可以在出现在语言实现中之前就试用最新功能。



您最想念JavaScript哪些功能?






All Articles