(作者:青竹 目前供职于SAP)
更新: 2014年2月28日
作为一名专职的JavaScript开发者,我会密切关注有关JS最新动态,不过最近看过ECMAScript 6的一些新的语法后。我认为ES委员会已经偏离正确的轨道,正在将JavaScript引向错误的方向,很可能又在重复ES4的老路。
JavaScript的简单
长久以来,我一直认为当今JavaScript的广泛应用一部分原因是源于她的“简单”。
一定程度上也可以叫作“简陋”,因为她并不能让程序员很“舒服”的写代码。我曾经从事过很长时间的C#和Java的开发,一度认为JavaScript的讲法极其糟糕,跟很多人一样对这种语言非常不屑,甚至觉得她并不能称之为语言,到处都是坑:浏览器兼容,异步回调,继承机制,域,类型转换……
但自从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越来越不稳定的原因。
以下特性,部分截自此幻灯片: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:
本人还是比较喜欢原型链式写法,宁愿自己累点也不愿让JS引擎多一丁点负担,而且这样写起来非常自由,通过Function.prototype或Object.create可以组织出来多种继承形式,甚至我可以需要的时侯指定,动态改变对象的基类(prototype),信手捻来,不受拘束;
其次模拟的继承必竟不如extends来得方便,这样可以在一定程度上防止过度面向对象,避免过度设计。本人坚持反对在框架级别滥用面向对象,滥用设计模式,崇尚简约自然的代码组织形式。(注:之前另一篇反模式的文章 他们为什么说面向对象有问题,探讨面向对象的一些缺陷 )
这一点已经其实已经颠覆了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表达形式
3.再来点Java和Node的模块管理
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文件,尽可能地提高前端性能。
模块管理是非常顶层的层次需求,应该第三方来完成,这样才能满意不同人的需要,一旦采用这种模块管理,你可能就真的没得选了,
目前的前端的模块加载方式非常成熟,且各种方案均可以通过BUILD工具自动合并,压缩分散的JS文件,尽可能地提高前端性能。
模块管理是非常顶层的层次需求,应该第三方来完成,这样才能满意不同人的需要,一旦采用这种模块管理,你可能就真的没得选了,
结论
我坚信大道至简,JavaScript应该有自己的风格,应该更加自信,应该追求实现最简,而非书写最简。语言的核心特性应该是稳定的,灵活的,最大程度减少语法限制,这样才能组合出自由多样的用法,这样才能有效地控制语言的复杂度,从而确保运行时能获得最佳性能。
我一度以为我只是为数不多反ES6这些特性的程序员,其实有些国外程度员很早就已经提出异议了,参见Thoughts on ECMAScript 6 and new syntax 观其评论,反对这些“Bad new syntax”特性的人者居多。
总而言之,ES6也提出了一些好的部分。但很多地方似乎“借鉴”了一点Java,一点.Net,一点TypeScript,一点CoffeeScript,一点Ruby/Python…… 我不是很明白他们要制定出一个什么东西,我们应该欢迎那些简单,实用的新特性,但标准并不应该让语言变得更复杂,尤其是一个四不像的东西。但幸亏JavaScript是一个公开,开放的,由大家共同维护的平台,这些过于颠覆的新特性可能会再次重蹈ES4的覆辙,再次被遗弃。
部分同意,既然已经用了这么久,就不要变了吧……
你说的很早以前就有人做过了: Java Applet 已经失败; Flash 正在走向衰退
保留字
函数式不需要非要使用箭头来实现……
要往JS里塞class extend abstract impletmemt 的应该都不是真正的jser
ourjs为什么现在越来越多这样无知的文章呢?
@留井 #1
不能
我支持这些说法。引入复杂性不好
我也是抵制es6的一员 Q289880020 有空探讨下
@yyfearth #3 没听说过 WebAssembly 吗?就是你想要的啊
非常悲哀,ES6的巨烈改动体现了JavaScript标准起草人对JS语法的不自信,一心想要改变;一些对自己所使用的语言都不自信的人凭什么制定JavaScript的标准?
反正ES6我看重的只有let一个特性...只有这个特性才是ES进化路上最重要的一步
js太不严谨了,写法太多,一段代码可能理解很长时间,相对于php而言可能一下就能看得懂
块级作用域,解构赋值,什么Class extend,值得这个标准一定是后端程序员,因为它写不来自由的javascript
嘲笑历史的人,终将会被历史所嘲笑。
使用箭头函数多简单啊!chrome、Firefox——就连微软的edge都支持了几乎所有的ES6,原PO现在还在抵制ES6吗?
现在是2018-08-02,我想问下本篇文章的最后一句话是不是打脸了?