使用简单的JavaScript,我们为什么应该抵制ES6的一些特性


发布者 newghost  发布时间 1393255666000
关键字 心得体会  分享 
(作者:青竹 目前供职于SAP)

更新: 2014年2月28日

作为一名专职的JavaScript开发者,我会密切关注有关JS最新动态,不过最近看过ECMAScript 6的一些新的语法后。我认为ES委员会已经偏离正确的轨道,正在将JavaScript引向错误的方向,很可能又在重复ES4的老路。

JavaScript的简单


长久以来,我一直认为当今JavaScript的广泛应用一部分原因是源于她的“简单”。

一定程度上也可以叫作“简陋”,因为她并不能让程序员很“舒服”的写代码。我曾经从事过很长时间的C#和Java的开发,一度认为JavaScript的讲法极其糟糕,跟很多人一样对这种语言非常不屑,甚至觉得她并不能称之为语言,到处都是坑:浏览器兼容,异步回调,继承机制,域,类型转换……

(注*参见  JavaScript就是一种垃圾语言 ;  Javascript诞生记-C和Self语言一夜情的产物 )

但自从Node.JS的横空出世,重新审视这门语言,你会发现这种简陋却可以让解释器很“舒服”地运行代码。在各种评测中,看到JavaScript虚拟机比Java虚拟机快个一两倍,甚至几倍已经不是什么新鲜事了。

这种性能的提升正是源自于她的简单,基于原型的超简面向对象实现方法;天生异步,没有复杂线程间的互锁和互斥;没有不可控的线程数量对CPU和内存的额外消耗,远小于各种主流编程语言的关键字的数量,以及灵活的闭包而形成的多样的代码组织形式,都决定了JavaScript是一种灵活高效的语言。

(注*参见 Web服务性能测试:Node完胜Java )

JavaScript的开放


目前JS被Node及其他平台采用的另一个原因是因为她的开放,目前JS引擎多达4,5种,这种局面也将长期持续下去,这些引擎相互之间在不断竞争,终究会不断提升JS的运行速度。

不光是Node,Java也早已内置了JavaScript的运行环境;最新的QT和Gnome也准备将JavaScript视为首选开发语言;微软在Win8也采用了WinJS技术;SAP最新推出的基于内存的数据库HANA,其中的XSEngine也正是由JS驱动的,与NodeJS的异步单线程不同,由于写法过于灵活,且程序流并不是很容易控制,XSEngine将其改造成同步多线程的形式,这一点其实已经有些违背JS的核心特性,但可以尽可能地保证ERP软件的正确性,降低ERP实施过程中的风险。

JS标准不是由一家公司制定的,也不存在专利问题。相对于使用Oracle的Java,微软的.NET,JavaScript的成本和风险似乎要低的多,这也是这些大公司选择基于JS技术,构建自己的JS平台的原因。

为什么要抵制ES6的部分标准


“简单”是JavaScript的立足之本。作为新的"C语言运行环境",“网页中的汇编语言”,理应追求性能第一,书写舒适第二。一些高级语言特性完全可以通过二次编绎到JavaScript来实现,其实CoffeeScript和TypeScript正是这么做的。这是一个很好的分工,语法语义应尽量保持接近底层,用最简单的方式实现,而不应添加过多的,复杂的,重复的特性添加入JavaScript核心,否则只会走Java越来越臃肿的老路。

我们都知道ECMAScript4,是一个著名的失败的标准。据说最初由Adobe撰写,后被ECMAScript委员会采纳,这其中有多少故事我们不得而知。我曾经也从事过一段时间的AS3的开发,一度被其优美,严谨的语法所迷住,其实当实并没有意识到,这样全新的语法体系对于浏览器来说可能过于复杂了,可能也正因为如此,其并没有在一款浏览器上真正实施过,同样这也可能是导致Flash Player越来越不稳定的原因。

现在翻开ES6的新特性,这些被遗弃的部分似乎又回来了,下面是我不太喜欢的几条(仅代表个人观点):

以下特性,部分截自此幻灯片:ECMAScript 6 需翻墙。

1. 看上去很美的类继承

class MetaLanguage extends Language {
  constructor(x, y, z, version) {
    super(x, y, z);
    this.version = version;
  }
  summary() {
    return version;
  }
}

看这段是不是觉得有点眼熟?为嘛这段跟微软的TypeScript的长得这么像?我们暂不去揣测标准制定者跟微软有何关系,但一下子用了这么多关键字,浏览器知道吗?

这一点已经其实已经颠覆了JavaScript的基础,采用基于类的对象模型(代码风格),代替原型模型实现面向对象;原型系统不预先设定基类,通过克隆/共享原型实现继承,过程简单,而且性能很好,可以看一看同是基于原型的语言Lisaac:

举例来说 Lisaac 产生的代码速度几乎跟C一样快。测试是由 MPEG-2 编码器的 Lisaac 版本得出的,它由一个C语言版本复制而来。测试显示,Lisaac版本比 C 版本慢1.9%,但代码行数少了37%。然而C语言并非面向对象语言,而是一个过程式语言。Lisaac 跟 C++ 版本相比可能更说明问题。
——  摘自 WiKi百科

本人还是比较喜欢原型链式写法,宁愿自己累点也不愿让JS引擎多一丁点负担,而且这样写起来非常自由,通过Function.prototype或Object.create可以组织出来多种继承形式,甚至我可以需要的时侯指定,动态改变对象的基类(prototype),信手捻来,不受拘束;

其次模拟的继承必竟不如extends来得方便,这样可以在一定程度上防止过度面向对象,避免过度设计。本人坚持反对在框架级别滥用面向对象,滥用设计模式,崇尚简约自然的代码组织形式。(注:之前另一篇反模式的文章  他们为什么说面向对象有问题,探讨面向对象的一些缺陷

2. 新的function表达形式

let empty = ->;
let square = (x) -> x * x;

$("#shopping-chart").on('click', (event)=>
  this.customer.purchase(this.chart);
);

[1, 2, 3].map{|x| x * x}; //[1, 4, 9]
照抄Ruby/Python的表达式,似乎还有Lambda的影子。由于JavaScript是非编绎性语言,这样的改动势必将JS引擎复杂化;目前与JS相似的但更简单的脚本语言nginx_lua在性能上已经超越了node.js,照这样下去不断复杂化与膨胀的JS语法体系终将成为性能的更大拖累。作为C和"汇编”级别的JavaScript应该保持本色,保持底层语法简单,这样才能不断优化。这种高级语言的特性完全可以通过TypeScript和CoffeeScript类似方式来实现。

3.再来点Java和Node的模块管理

module DBLayer {
  export function query(s) { ... }
  export function connection(..args) { ... }
}
import DBLayer.*;

module CanvasLib = require('http://../canvas.js');
import CanvasLib.{Triangle, rotate};

我不太清楚在语言核心中设置如此“高级”的模块管理器是否合适,如果前端全部使用这种单个文件同步加载方式,就不知道会给性能带来多大的损失了。

目前的前端的模块加载方式非常成熟,且各种方案均可以通过BUILD工具自动合并,压缩分散的JS文件,尽可能地提高前端性能。

模块管理是非常顶层的层次需求,应该第三方来完成,这样才能满意不同人的需要,一旦采用这种模块管理,你可能就真的没得选了,

结论

我坚信大道至简,JavaScript应该有自己的风格,应该更加自信,应该追求实现最简,而非书写最简。语言的核心特性应该是稳定的,灵活的,最大程度减少语法限制,这样才能组合出自由多样的用法,这样才能有效地控制语言的复杂度,从而确保运行时能获得最佳性能。

我一度以为我只是为数不多反ES6这些特性的程序员,其实有些国外程度员很早就已经提出异议了,参见Thoughts on ECMAScript 6 and new syntax 观其评论,反对这些“Bad new syntax”特性的人者居多。

总而言之,ES6也提出了一些好的部分。但很多地方似乎“借鉴”了一点Java,一点.Net,一点TypeScript,一点CoffeeScript,一点Ruby/Python…… 我不是很明白他们要制定出一个什么东西,我们应该欢迎那些简单,实用的新特性,但标准并不应该让语言变得更复杂,尤其是一个四不像的东西。但幸亏JavaScript是一个公开,开放的,由大家共同维护的平台,这些过于颠覆的新特性可能会再次重蹈ES4的覆辙,再次被遗弃。









回复 (26)
  • #
  • #1 kaka 1397743954330

    部分同意,既然已经用了这么久,就不要变了吧……

  • #2 留井 1393305526000
    我觉得下面两个也没什么用, string.startsWith() string.contains() 可以用一种indexOf来直接实现……
  • #3 yyfearth 1393312733000
    如果你地址
  • #4 yyfearth 1393313630000
    不好意思刚才留言没弄好 ES6的出现实在属于没办法,是对JS的一次拯救。由于HTML5带起来的Single Page App之风,JS从此走向AS那样的RIA之路,Web 平台已经在Google的带领下几乎成了一个操作系统平台。 JS应用难免的走向越来越复杂的道路。然后“简陋粗糙”的JS语言无法承受这个责任,用JS写超大型应用绝对是个灾难。先是出现了CoffeeScript来改进语法添加语法糖,然后是Dart,然后是TypeScript,但是都是一家支持,没有形成标准。ES6的出现就是希望给出了一个标准大家可以一起支持,让JS可以用来开发大型应用。 所以按照你的说法JS已经太复杂,没错确实如此,但是ES6的方向也是一次让JS变得更好的尝试,一个向后兼容的解决方案,也是大多数厂商可以接受的方案。 其实我也觉得这个方案过于稳妥,不利于长远发展,但是如果不这么做,要不就放弃HTML5平台的发展,Web就是Web,不要去做所谓的应用。 要么就是用另外一个语言或者平台取而代之,比如Dart。但是实现一个Dart同时还要支持JS,是不是让浏览器变得更加复杂了呢。 我觉得解决方案就是相当于内置一个Flash Runtime或者JVM或者.Net IL或者LLVM这样的东西,换句话说就是支持一个通用的Web二进制(相当于汇编语言),然后各种语言可以编译到这个目标上面执行。并且内置JS的JIT,这样同时兼顾兼容性,同时可以随意引入更好的语言。 这样浏览器的代码执行就可以和语言分离,然后各种功能通过API的形式提供。
  • #5 柳絮才高 1393319312000
    @yyfearth

    你说的很早以前就有人做过了: Java Applet 已经失败; Flash 正在走向衰退
  • #6 ayanamist 1393343485000
    看来楼主不知道JS出现的第一天,class和extends就已经是关键字了,呵呵
  • #7 忘了爱 1393383560000
    @ayanamist

    保留字
  • #8 bingb511 1393390066000
    还是觉得 js 比较好
  • #9 callee 1393720994000
    菜鸟, 不懂函数式就别乱发表了
  • #10 留井 1393825588000
    @callee

    函数式不需要非要使用箭头来实现……
  • #11 hyspace 1394499851000
    其实多数只是语!法!糖!而且很多对象在虚拟机中也是用js实现的,不会拖累引擎,但开发者可以少依赖一些外部库
  • #12 旧事 1394504029000
    用不着抵制吧,浏览器应该不会去实现这些……
  • #13 johnhax 1395802737000
    ourjs为什么现在越来越多这样无知的文章呢?
  • #14 withered_brook 1407285761083

    要往JS里塞class extend abstract impletmemt 的应该都不是真正的jser

  • #15 tommy酱 1445353427177

    ourjs为什么现在越来越多这样无知的文章呢?

  • #16 冯力吗 1452837479136

    @留井 #1

    不能

  • #17 吴目任 1453127865751

    我支持这些说法。引入复杂性不好

  • #18 唐戏叶 1454215842278

    我也是抵制es6的一员 Q289880020 有空探讨下

  • #19 xwing 1456478956085

    @yyfearth #3 没听说过 WebAssembly 吗?就是你想要的啊

  • #20 施厅广 1457416535710

    非常悲哀,ES6的巨烈改动体现了JavaScript标准起草人对JS语法的不自信,一心想要改变;一些对自己所使用的语言都不自信的人凭什么制定JavaScript的标准?

  • #21 DanoR 1461201532753

    反正ES6我看重的只有let一个特性...只有这个特性才是ES进化路上最重要的一步

  • #22 陶后寺 1463251195118

    js太不严谨了,写法太多,一段代码可能理解很长时间,相对于php而言可能一下就能看得懂

  • #23 龚叹右 1467791839689

    块级作用域,解构赋值,什么Class extend,值得这个标准一定是后端程序员,因为它写不来自由的javascript

  • #24 岑币子 1469294191560

    嘲笑历史的人,终将会被历史所嘲笑。

  • #25 郎议义 1510743101591

    使用箭头函数多简单啊!chrome、Firefox——就连微软的edge都支持了几乎所有的ES6,原PO现在还在抵制ES6吗?

  • #26 冯仰忙 1533199096590

    现在是2018-08-02,我想问下本篇文章的最后一句话是不是打脸了?

微信扫码 立即评论