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

最近几年以来,伴随着各个端平台的迅猛发展,以 TypeScript、Swift、Kotlin 和 Dart 为代表的新一代应用编程语言纷纷浮现。群雄环伺之下,JavaScript 也在不断演进。在今天正在深圳召开的 GMTC2019 全球大前端技术大会上,360 高级前端架构师贺师俊发表《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 有浏览器,有非常多的大公司一起在这个委员会里,有世界上最大的开发者生态。

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

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

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

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

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

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

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 是对生态非常重要的东西。大家知道我们之前都用 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。所以会遇到非常多的矛盾问题。

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

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

嘉宾介绍:

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

JavaScript简介:从概念、特点、组成和用法全面带你快速了解JS

“这里是云端源想IT,帮你轻松学IT”

嗨~ 今天的你过得还好吗?

我们总是先扬起尘土

然后抱怨自己看不见

– 2024.04.15 –

JavaScript,简称JS,是一种轻量级的解释型编程语言,它是网页开发中不可或缺的三剑客之一,与HTML和CSS并肩作战,共同构建起我们浏览的网页。

今天我们就来了解一下JavaScript,看看它在我们的web前端开发中扮演着什么样的角色。

JavaScript(简称“JS”)是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。它以其作为开发Web页面的脚本语言而闻名,但也被广泛应用于非浏览器环境中。

JavaScript是一种基于原型编程、多范式的动态脚本语言,支持面向对象、命令式、声明式和函数式编程范式。

JavaScript最初由Netscape公司的Brendan Eich于1995年为网景导航者浏览器设计并实现。由于Netscape与Sun的合作,Netscape管理层希望该语言在外观上看起来像Java,因此得名为JavaScript。

JavaScript的标准是ECMAScript。截至2012年,所有浏览器都完整地支持ECMAScript 5.1,旧版本的浏览器至少支持ECMAScript 3标准。

2015年6月17日,ECMA国际组织发布了ECMAScript的第六版,正式名称为ECMAScript 2015,但通常被称为ECMAScript 6或ES2015。

JavaScript目前是互联网上最流行的脚本语言。这门语言不仅可用于HTML和Web开发,还可以广泛用于服务器、PC、笔记本电脑、平板电脑和智能手机等设备。

动画效果:

让你的网页动起来,比如轮播图、下拉菜单等。

表单验证:

在数据提交到服务器之前,进行即时的客户端验证。

异步请求:

通过AJAX技术,实现页面的局部更新,无需刷新整个页面。

交互式游戏:

创建复杂的网页游戏,或是简单的互动元素。

Web API:

利用浏览器提供的API,访问地理位置、摄像头、本地存储等。

跨平台应用:

使用如React Native、Electron等框架,开发跨平台的移动应用和桌面应用。

后端开发:

Node.js的出现让JavaScript也能在服务器端大展拳脚。

  • ECMAScript,描述了该语言的语法和基本对象。
  • 文档对象模型(DOM),描述处理网页内容的方法和接口。
  • 浏览器对象模型(BOM),描述与浏览器进行交互的方法和接口

3.1 ECMAScript:

ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会)在标准ECMA-262中定义的脚本语言规范。这种语言在万维网上应用广泛,它往往被称为JavaScript或JScript,但实际上后两者是ECMA-262标准的实现和扩展。

简单来说:

  • ECMAScript JavaScript是的核心,是规范标准。
  • 描述了语言的基本语法(var、for、if、array等)和数据类型(数字、字符串、布尔、函数、对象(obj、[]、{}、null)、未定义)。

3.2 DOM

文档对象模型 (DOM) 是HTML和XML文档的编程接口。它提供了对文档的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容。

DOM 将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。

简言之,它会将web页面和脚本或程序语言连接起来。

可以理解为:

DOM Document Object Model文档对象模型,可以去操作网页

Document(文档)

指的是XML和HTML的页面,当你创建一个页面并且加载到Web浏览器中,DOM就在幕后悄然而生,它会把你编写的网页文档转换成一个文档对象。

Object(对象)

  • js对象大致可以分为以下三种:
  • 用户定义对象,例如:var obj = {}
  • 内置对象,无需创建,可直接使用,例如:Array、Math和Data等
  • 宿主对象,浏览器提供的对象,例如:window、document

DOM中主要关注的就是document,document对象的主要功能就是处理网页内容。

Model(模型)

代表着加载到浏览器窗口的当前网页,可以利用JavaScript对它进行读取。

3.3 BOM

浏览器对象模型,操作浏览器。

Browser Object Model 浏览器对象模型提供了独立与内容的、可以与浏览器窗口进行互动的对象结构,BOM由多个对象构成,其中代表浏览器窗口的window对象是BOM的顶层对象,其他对象都是该对象的子对象。

JavaScript是一种功能强大的编程语言,它的特点主要包括以下几点,在这里大家只需要了解一下就可以了。

  • 客户端脚本语言:JavaScript通常在用户的浏览器上运行,用于实现动态内容和用户界面的交互性。
  • 弱类型语言:JavaScript不要求开发者在编程时明确指定变量的类型,类型会在运行时自动转换。
  • 面向对象:JavaScript支持面向对象的编程模式,允许创建对象和定义它们之间的交互。
  • 事件驱动:JavaScript能够响应用户的操作(如点击、输入等),这使得它非常适合构建交互式的Web应用。
  • 跨平台:JavaScript代码可以在几乎所有的现代浏览器上运行,无论是Windows、macOS还是Linux操作系统。
  • 动态性:JavaScript是一种动态语言,可以在运行时改变其结构和行为。
  • 可扩展性:JavaScript可以通过添加新的函数和属性来扩展其内置对象的功能。
  • 宽松语法:JavaScript的语法相对宽松,使得编程更加灵活,但也可能导致错误。
  • 单线程与异步处理:JavaScript在浏览器中是单线程执行的,但它通过事件循环和回调函数等机制实现了异步处理。
  • 基于原型的继承:不同于传统的类继承,JavaScript使用的是基于原型的继承方式。
  • 核心组成部分:JavaScript的核心由ECMAScript、DOM(文档对象模型)和BOM(浏览器对象模型)组成。
  • 多范式:JavaScript支持多种编程范式,包括过程式、面向对象和函数式编程。

总的来说,JavaScript的这些特点使其成为了Web开发中不可或缺的一部分,同时也适用于服务端编程(如Node.js)和其他非浏览器环境。

你是不是厌倦了一成不变的编程模式?想要突破自我,挑战新技术想要突破自我,挑战新技术?却迟迟找不到可以练手的项目实战?是不是梦想打造一个属于自己的支付系统?那么,恭喜你,云端源想免费实战直播——《VUE3+SpringBoot搭建移动支付功能(第1期)》即将开启,点击前往查看!云端源想-热门直播课

1、页内样式:

在HTML文件中,可以在<head>或<body>标签中添加<script>标签,然后在<script>标签中编写JavaScript代码。这种方式适合较小的脚本或者是测试阶段的代码。

例如:

2、页外样式:

步骤一:在js文件夹中创建一个Xxx.js文件。

步骤二:在Xxxx.js文件中编写JavaScript代码。

步骤三:在HTML文件的<head>标签中通过<script src=\”Xxxx.js\”></script>进行引入。

例如:

需要注意的是,引入时路径要正确,如果是当前目录则直接写文件名,如果是上级目录则需要使用./来指定路径。

  • 页外样式写到<head>中,可以让它早点加载、早点完成。
  • 而页内样式写到<body>结束标签之前,可以让HTML代码先渲染内容,然后再执行JavaScript代码。

随着Web技术的发展,JavaScript也在不断进化。ES6引入了类、模块、箭头函数等新特性,未来的JavaScript将更加强大、简洁。作为前端开发的基石,也是全栈开发的重要工具,JavaScript的重要性不言而喻。

现在,你是否已经迫不及待想要开启自己的JavaScript学习之旅了呢?记住,每一位大师都是从基础开始的,不要害怕犯错,因为每一个错误都是通往成功的阶梯。

拿起你的键盘,打开你的浏览器,让我们一起在JavaScript的海洋中遨游,发现编程的无穷魅力吧!

我们下期再见!

END

文案编辑|云端学长

文案配图|云端学长

内容由:云端源想分享

本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com

点赞 0
收藏 0

文章为作者独立观点不代本网立场,未经允许不得转载。