写点什么

冰与火之歌:JavaScript 的困境与挑战

  • 2019-12-20
  • 本文字数:4713 字

    阅读完需:约 15 分钟

冰与火之歌:JavaScript 的困境与挑战

最近几年以来,伴随着各个端平台的迅猛发展,以 TypeScript、Swift、Kotlin 和 Dart 为代表的新一代应用编程语言纷纷浮现。群雄环伺之下,JavaScript 也在不断演进。在今天正在深圳召开的GMTC2019 全球大前端技术大会上,360 高级前端架构师贺师俊发表《JavaScript 的困境与挑战》的主题演讲,分析 JavaScript 目前面对的问题以及下一步的发展趋势。


JavaScript 的时代变迁

我从 1998 年就开始写JavaScript了,那时候做的是 IE4,在座很多人可能没有用过这个东西。所以我经历了整个时代的变化。


  • 1995 年到 1999 年,是前 ES3 的时代;

  • 2000 年到 2010 年,是 ES3 的时代,我们在整个开发当中使用的都是 ES3 的版本;

  • 2008 年到 2016 年,是 Harmony 时代,今天我们基于 JavaScript 的开发,主要工具也好、方式也好,都是在 Harmony 时代积累下来的;

  • 2014 年到 2020 年,就已经进入了 ES6/Babel 的时代,Babel 在里面扮演了非常重要的角色,使我们可以在生产环境里面去使用 ES6 的特性;

  • 最后一个是我个人的预期:我认为我们下面新的时代,可能就是 TS、JS 共同构成的生态新时代。


在过去十多年里面,我经常出来讲 JavaScript 的内容,2010 年我就讲过 ES5 的话题,我当时对 JavaScript 的发展做了判断:发展方向可能有三个:API 的扩展和标准化;通用化;还有适应于 PITL(programming-in-the-large)。


2014 年我也做过演讲,当时对 ES6 做了一些总结:


  • Module 使得 JS 生态系统能重新统一;

  • Module / Class 等让 JS 更适合大型编程;

  • Promise 等将最佳实践标准化;

  • Generator / Proxy 等提供了现代语言所需的重要设施;

  • Arrow function / Destructring 等不仅是语法糖,而且填了长期以来的一些坑。


在 2015 年到 2017 年,我做过一个演讲,题目叫做《JS——世界第一程式设计语言》。在这个演讲里面,我特别提到:根据当时在推特上的统计,有 33%的人直接在生产环境使用 Babel stage0/1 presets。


传统上 JavaScript 是一个非常难以升级的语言,因为要保持线上兼容性,但是有了 Babel 之后,就变成了永远在使用最新特性。从生态上来讲,JavaScript 有浏览器,有非常多的大公司一起在这个委员会里,有世界上最大的开发者生态。

为什么会觉得 JavaScript 学不动了?

我为什么把这个拿出来说一下呢?之前的演讲,我觉得其实比较乐观,某种意义上是立了 flag。但当时 JS 已经有一些隐忧浮现了,最直接的体现是什么呢?就是所谓 js fatigue——”学不动了“。不单单包括语言,框架、工具也不断地改变,我们会觉得要学的东西很多。


当然如果大家看最近一两年会发现框架也好、工具也好,整个演进已经变慢了,已经稳定了、成熟了,如果今天我还说学不动的话,很多情况下可能会指语言本身。比如 JavaScript 一直在加新语言特性,2015 年之后,每一年都会发一个新的带年份版本的标准,每一年大概会加六到八个新的提案。包括 ES2020 也已经定了,大概会增八到九个新特性。所以这个并没有慢下来。


那为什么我们会有所谓的 JavaScript 学不动的感觉?我理解这个事情是一个边际效用下降。原本你学一个东西马上会给你带来非常大的收益,但是现在你好像每学一个新的框架,或者学一个新的语言特性,在收益上可能要打一个问号。


如果你学的东西并不能给你直接带来一个非常强的收益,包括你在生产环境里面,你觉得也不是很多地方能用到它,那么它的整个性价比可能就会下降,所以你就会发出一个好像学不动的感叹。

2020:JavaScript 的困境与挑战

所以我今天的内容,其实就是在反思,经过狂飙后,我们停下来看一看我们眼前所遇到的问题。在今年 6 月份,也就是在北京站的 GMTC 上我做过演讲,叫做《前端开发编程语言的过去、现在和未来》,讲了 TS、JS 未来面临的挑战。简单来讲就是两句话:TS 背着 JS 的包袱;JS 背着历史的包袱。


很多人认为我只要 TypeScript 就好了,但是大家要理解,TypeScript 在设计目标上要全兼容,所以如果 JavaScript 有什么问题的话,TypeScript 也跑不了。

JavaScript 的新包袱和历史包袱

JavaScript 大家知道,背着历史包袱。历史包袱不仅指老的问题,今天也改不掉,而且更重要的是,因为 JavaScript 的历史包袱导致它有一些新的设计,仍然会增加新的包袱:


第一个,JavaScript 的应用场景非常多,导致 JavaScript 的开发者社区非常复杂,有非常巨大的差异性。当我们要去对 JS 进行改进或者要加入新东西的时候,不同社区的想法、需求可能会不一样。怎么做 tradeoff?非常困难。


另外,还有像委员会语言的弊病,这个不用讳言比如 C++就是明显的委员会的语言,委员会的语言因为参与的人多,不像很多由公司主导的语言,本身的发展比较有秩序。


历史包袱我们可以展开讲一下,历史包袱简单来讲,最基本的就是,因为 JavaScript 用了这么多年,不能破坏它的兼容性,而且在所有语言里面是最没有办法改的——我们有那么多的网站跑到线上,加了任何东西都不能把原本的网站搞挂了,所以只能增加特性解决以前的问题。


比如箭头函数,它加了之后解决了很多以前 ES3 时代的函数里面的问题,也就是增加了一个所谓的 Lexical this,但是不可避免的是使 this 的语义变得更加复杂。


另外一个例子,因为我们这么多年以来,整个 JavaScript 的发展,使得我们在真正的工程当中,会存在几种不同的东西:一个叫工程方案;第二个叫事实标准;第三个才叫真的标准。这三个东西会长期共存,所以使得整个生态里面会有些复杂的问题。


对于历史包袱,我们现在的解决方法是 Polyfill 的方案。Polyfill 有广义 Polyfill 和狭义 Polyfill,到底什么叫 Polyfill?Polyfill 是已经成为了标准了,然后我们把它做出来,在没有实现的浏览器上可以用,这才叫 Polyfill。如果你是一个实验性的实现,你就不应该去修改 global 和 prototype 上的东西,因为它其实会造成很多潜在的问题。但是如果已经是一个标准了,那么去改并没有什么错。但是这个问题就是,很多开发者并不能区分这个,而且在我们的日常当中,当我们讲 Polyfill 的时候也没有刻意区分,但就会在生态中造成这样一个非常严重的问题。

Babel 带来的挑战

接下来讲 Babel,Babel 是对生态非常重要的东西。大家知道我们之前都用 presets,在 v7 的时候被取消了。主要问题是我们会无意中在 Production 中使用了 unstable features,当它发生改变,如果你在生产环节里用的话,对你本身来讲就会是非常大的挑战,对于标准本身来讲也会有很大的挑战。甚至到 stage3 都会有这样的问题。但这个事情是双刃剑,有很多东西你只有在真正的生产环境里面才能得到真的反馈,不是说光写一些 demo 就可以看出来什么问题。


第二个问题是,很多人说我今天写的不是 JavaScript,而是 BabelScript,这些特性是自己定制的语法特性。这里面有个特别的例子,是 babel-plugin-macros,这个插件非常好,原本要单独写插件,现在可以用 macros 去写,它相对是更显性的方式,明确的知道我这里用了自定义的东西。但是本质上,当你导入一个像函数的东西,它其实并不是函数。这个仍然存在一个挑战,对很多开发者来讲,是否理解是函数和不是函数的差异?


再看下 TypeScript,TypeScript 的设计原则是只有到 Stage3 才可以,TypeScript 是从 2012 年就诞生了,2012 年 ES6 还没有定案,所以 TypeScript 当年的很多特性都是 ES6 还没有定案的。如果我们看一下,这是当年 TypeScript 增加的东西,本质上 TypeScript 只是加了类型,但是在当年,因为 2012 年 ES6 还没有定案,除了类型之外,这些东西是加进去的东西。


这些东西稍微看一下,arrow function、class 没有什么问题,es module 就有问题了。它的语法不一样,这已经开始有坑了。decorator 也有问题,这是现在的提案,和 TypeScript 的提案非常不一样,所以 TypeScript 需要一个编译开关才能使用,这也是 decorator 不太好的状态。包括最后这两个,private property 和 public property 语法语义和现在的 stage3 的 class fields 完全不一样,对 TypeScript 来说非常痛苦。


然后我们再来看一个例子,叫做 ESLint。它采用的方针更加保守了,它只是在 Stage4 的时候才会做跟这些新特性有关的新规则。这种方式也避免了前面很多问题。


ESLint 会导致两个问题:第一个我们很多人已经在做更早的 Stage3 的东西,但 Stage3 的东西也需要保护,而且更需要保护;第二个问题就是,在制订标准的时候,缺乏 lint 社区的反馈。


有一个有趣的事情是,在整个 ES6 的发展当中,很多的提案是遵循一个叫做 Maximally Minimal 的设计哲学,最大化的最小化,我们只加那些最最重要的东西,如果翻译过来的话叫先解决温饱再考虑小康,所以 ES6 很多东西确实解决痛点,但很多时候 ES6 的东西并不能完全满足你的所有需要。


比如 ES6 加了 Map 和 Set,但这两 API 只能满足你最基本的需求。所以这也是一个双刃剑,好的地方是,我们只有通过这样的设计,才能在当时那么快的把 ES6 做出来,否则可能永远都做不出来。到底怎么样才是真正满足所有人需求?这个事情定义不清楚。


今天来讲,我们会发现,很多时候我们温饱都已经解决了,现在大家讨论的都是小康问题。怎么让特性用得更好更爽。但这个问题就是前面讲的,因为开发者社区非常复杂,每个人的需求都不一样,最大的问题是谁能代表开发者?这其实一个非常难以回答的问题。


举个例子——Map.prototype.upsert(),看名字猜得出来吗?估计猜不太出来。我个人认为只有非常有经验的开发者,才可能比较需要这个东西。一般的开发者其实是不是真的需要,要打个问号。同时对新手来讲,理解的成本也比较高。所以这里有个问题,我们怎么衡量成本和收益?其实是非常困难的。


最后,我讲一下有争议的事,比如说我们现在对 Top-level Await、Class fields 这两个提案都不太满意,当然我们技术上可以有很多的讨论,但实际上这个事情一句话讲就是改革进入深水区,就是好做的都做完了,剩下的都是难搞的。这两个其实都是 ES6 时代遗留至今的问题。


最后再举一个例子——Pipeline Operator。现在 Pipeline 有两种不同的竞争提案,第一种叫 F# Style,另外一种方式叫 Smart style。所以这其实是两难选择,我们是希望更符合 FP 的主流还是更普适现有整个 JavaScript 的生态,这是非常难做的选择。


还有 Binary AST,也是一个提案,它相当于字节码,它有个很大的好处就是整个加载速度会非常快的提升。所以这样一个提案肯定是我们所有人都很喜欢的,特别是做 Web 的人会非常喜欢。但是这个现在也处于一个比较难推进的状态,为什么呢?讲一个很简单的原因就是,当你有了 Binary AST 之后,所有语言特性都得考虑,在这里面怎么把它加进去,字节码里面怎么把它加进去,所以困难程度直接翻番了。


大家看到很多问题都是有两面性,这是改革进入深水区遇到的很多问题。包括不同平台的需求,比如 Web 和 Node 的平台,这两个平台的需求不一样。


还有性能和动态性的矛盾,我们做一个东西既希望性能好,又希望符合 JavaScript 的传统,这里面最简单的例子就是 decorator。所以会遇到非常多的矛盾问题。

JavaScript 的转折点:未来何去何从?

讲了这么多,可能最重要的问题就是:到底我们整个发展有没有 Roadmap?答案是没有。这就是委员会里面的一个问题,进一步来讲,它也没有明确的主导者,如果没有 Roadmap,全局上怎么解决这个事情就不好说了。


所以我们今天进展到这样一个地步——JavaScript 是非常成功的语言,但到现在是一个转折点,我们要停下来看一看:它再往下怎么样发展才会更好?


嘉宾介绍:


贺师俊(网名 Hax),360 高级前端架构师,十多年来一直活跃在前端和 JavaScript 社区。对多项 Web 标准有微小贡献,对 Groovy 语言并间接对 Swift 语言有微小贡献,近年来参与了诸多 ECMAScript 新草案的讨论。2019 年 7 月起成为 360 的 TC39 代表。


2019-12-20 18:087091

评论 1 条评论

发布
用户头像
三大框架趋于稳定
2020-01-15 10:15
回复
没有更多了
发现更多内容

非常全面的 SpringBoot 保姆级笔记,面面俱到,太牛了

做梦都在改BUG

Java spring 微服务 Spring Boot 框架

分布式事务的21种武器 - 7

俞凡

架构 云原生

文心一言 VS 讯飞星火 VS chatgpt (23)-- 算法导论4.2 5题

福大大架构师每日一题

福大大 文心一言 讯飞星火

C语言编程—数组

芯动大师

Office 2021和 Office 365 有什么不同之处?office 2021 和 365 区别是什么

Rose

Office 365 Office 2021 office下载

DR5白金版 for mac(PS一键磨皮插件Delicious Retouch)支持ps2022 v5.0汉化版

Rose

DR5白金版 PS一键磨皮插件 dr5插件 汉化版PS插件 dr5插件教程

学懂缓存雪崩,缓存击穿,缓存穿透仅需一篇,基于Redis讲解

Java你猿哥

Java redis 缓存击穿 缓存雪崩 Redis缓存穿透

利用springboot初始化机制三种实现策略模式的应用

Java你猿哥

Java spring Spring Boot 设计模式 ssm

Java面试很难?啃完阿里老哥这套Java架构速成笔记,我都能拿30K

做梦都在改BUG

阿里巴巴工程师1480道Java面试题及答案整理( 2023年 整理版)

Java你猿哥

Java MySQL redis JVM java面试

Java面试集锦

源字节1号

微信小程序 开源 软件开发 后端开发

基于Redis讲解,学懂缓存雪崩,缓存击穿,缓存穿透

做梦都在改BUG

Java redis 缓存穿透 缓存击穿 缓存雪崩

工厂+策略在springboot项目中的使用场景

做梦都在改BUG

Java Spring Boot 工厂模式 策略模式

深度学习进阶篇-预训练模型[4]:RoBERTa、SpanBERT、KBERT、ALBERT、ELECTRA算法原理模型结构应用场景区别等详解

汀丶人工智能

自然语言处理 深度学习 预训练模型 Transformer BERT

Parallels Desktop如何退出账号?PD18虚拟机退出账号方法

Rose

pd18虚拟机 PD如何退出账号 Parallels Desktop下载 Parallels破解版 Mac虚拟机下载

关于Spring Cloud Alibaba,看阿里这篇笔记真香

Java你猿哥

分布式事务 微服务 Spring Cloud 服务治理 Spring Cloud Aliababa

国外顶级架构师编写2580页DDD领域驱动设计笔记,看到内容后破防了

做梦都在改BUG

Java 架构 领域驱动设计 DDD

阿里“妈宝级”之作,Kubernetes原理剖析与实战应用手册,太全了

做梦都在改BUG

Java Kubernetes k8s

使用Go语言实现门面模式:简化复杂子系统的访问

Jack

iOS MachineLearning 系列(19)—— 分析文本中的问题答案

珲少

AE模板:短信消息聊天对话气泡动画Smart Text Message

Rose

AE模板下载 Smart Text Message 对话框气泡生生成器插件

爆肝了!阿里最新版的这份Spring Security源码手册,狂揽GitHub榜首

做梦都在改BUG

Java spring spring security Spring Security OAuth

软件测试/测试开发丨Web自动化 PageObject 设计模式

测试人

程序员 软件测试 自动化测试 测试开发 Web自动化测试

简直人生外挂,直接涨薪25K,跪谢这份Java性能调优实战宝典

做梦都在改BUG

Java 性能优化 性能调优

五十万字总结!2023最新Java面试八股汇总(含答案,收藏版)

采菊东篱下

Java 面试

耗时一周整理的牛客网上最火Java面试八股文,面试必备

架构师之道

Java 面试

2023-05-27:给你一个只包含小写英文字母的字符串 s 。 每一次 操作 ,你可以选择 s 中两个 相邻 的字符,并将它们交换。 请你返回将 s 变成回文串的 最少操作次数 。 注意 ,输入数据

福大大架构师每日一题

Go 算法 rust 福大大

Maven Cannot resolve plugin org.apache.maven.plugins

Andy

photoshop神经滤镜是什么,神经滤镜功能揭秘~

Rose

photoshop神经滤镜 Neural Filters插件 ps滤镜下载 PS2023破解

CMake构建指南:如何提高C/C++项目的可维护性

小万哥

Linux 程序员 C/C++ 后端开发 cmake

阿里巴巴Java开发手册(华山版)

Java你猿哥

Java MySQL ssm JAVA开发 Alibaba

冰与火之歌:JavaScript 的困境与挑战_大前端_贺师俊_InfoQ精选文章