本文转载自:众成翻译
译者:myvin
链接:http://www.zcfy.cc/article/1871
原文:https://hackernoon.com/how-it-feels-to-learn-javascript-in-2016-d3a717dd577f#.cmul9wb9g

在这篇文章的写作过程中没有JavaScript框架被创建出来。

下面这篇文章是受Circle CI的《这就是未来》激发而写的。你可以在这里读到原始版本。这篇文章只是代表一种观点,就像任何JavaScript框架一样,不必严肃对待。

嗨,我最近获得了一个web项目,但是说实话,我已经有几年没有写web代码了,而且我也听说web领域发生了一些变化。你算是最跟得上时代潮流的web开发者了,对吧?

-确切的说应该是前端工程师,但是是的,你算是找对人了。2016年我做web开发,可视化、音乐播放器、踢足球的无人机,你随便问,来者不拒。我刚刚参加完JS大会和React大会,所以我知道构建web应用的最新技术。

牛掰啊。我需要创建一个展示用户最近活动的页面,所以我需要从RESTful API获取数据,然后在可过滤的表格上展示出来。我在想是不是可以用jQuery来获取并展示数据?

-Word天呐,不可以,现在已经没有人用jQuery了。你应该学习下React,现在可是2016年了啊。

额,好吧。React是什么呢?

-它是一个Facebook出品的超级酷炫的库,它允许你非常简单地操控视图的变化,并且能使你的应用具有可控性和高性能。

听起来不错哦。那我可以用React展现从服务器上获取的数据么?

-必须的,但是首先你需要在你的页面上添加React库和React DOM库。

哎,等会儿,怎么是两个库呢?

-是这样的,一个库是我刚说的那个,另一个库是用来操作JSX写的DOM的。

JSX?JSX是个啥玩意?

-JSX是JavaScript的语法扩展,看起来特别像XML。它是另一种写DOM的方式,你可以认为它是一种更好的写HTML的方式。

HTML有什么问题么?

-现在是2016年了好嘛。已经木有人直接写HTML了。

好吧,不管怎么样,如果我添加了这两个库我是不是就可以使用React了?

-不完全是。你需要添加Babel,然后你就可以用React了。

另一个库?Babel是嘛玩意?

-哦,Babel是个转义工具,可以将任意版本的JavaScript转义成特定版本的JavaScript。使用React并不是必须用Babel,但是如果你不用Babel的话,你就只能用ES5了。现实点吧哥们,现在可是2016年了啊,你应该像其他牛掰的同学那样用ES2016+来码代码。

ES5?ES2016+?我又蒙了。ES5和ES2016+又是什么鬼?

-ES5就是ECMAScript 5。大部分人都会用ES5,因为现在大部分浏览器都支持ES5。

ECMAScript?

-是的,你知道的,JavaScript是1995诞生的,ECMAScript是在1999年制定出来的JavaScript标准,那会儿JavaScript还叫Livescript,而且只能跑在网景浏览器里面。那会儿非常混乱,但是现在好了,而且有7个版本的JavaScript。

我了个去,7个版本。那ES5和ES2016+是啥?

-分别是第五版和第七版。

等会儿,第六版搁哪了,不是要雨露均沾?

-你是说ES6?我是说,每一个版本是前一个版本的超集,所以如果你正在使用ES2016+,那么你就可以使用之前版本的所有特性。

哦,这样啊。那为啥不用ES2016+而是用ES6呢?

-哦,你可以用ES6,但是为了使用一些像async和await这样炫酷十足的特性,你就得用ES2016+了。否则,你就只能用ES6的generator来控制异步流程了。

我真心不懂你刚刚说了什么,这名字都把我搞晕了。是这样的,我就是想从服务器上获取数据,我之前是从CDN引入jQuery,然后使用AJAX来获取数据,为啥我现在不能这样做了呢?

-大哥,这都2016年了好伐,没有人再用jQuery了。每个人都知道,使用jQuery的最终下场就是码出一堆意大利面条一样的代码。

哦,那我现在就需要加载三个库来获取数据并用HTML表格来展现。

-恩,你需要把这三个库引进来,然后用模块管理器把它们打包成一个文件。

好吧,那什么是模块管理器呢?

-具体的定义是依赖于环境的,但是在web开发中一般意味着支持AMD或者CommonJS模块的东西。

好吧。。。AMD和CommonJS又是个啥玩意?

-有多种方式来描述多个JavaScript库和类之间如何交互。你知道exports和require不?你可以写多个定义AMD或者COmmonJS API的JavaScript文件,然后使用像Browserify一样的东西来打包。

好吧,听起来好像很有道理的样子。那Browserify是什么呢?

-它是一个工具,允许你将符合CommonJS的依赖打包成可以运行在浏览器中的文件,它之所以会诞生,是因为大多数开发者都把依赖放到npm仓库中。

npm仓库?

-它是一个庞大的公共仓库,开发者把代码和依赖作为模块放到这里。

就像CDN一样?

-不太准确。它更像是一个集中式的数据库,在这里任何人都可以发布、下载仓库,你可以用来本地开发,如果你想的话也可以把它们上传到CDN上。

哦,就像Bower一样!哈哈,终于遇到我会的了~~

-恩,是的,但是现在可都是2016年了,已经木有人使用Bower了。

哦,我懂了。。。所以我需要从npm上面下载那些库咯?

-恩,是的。举个栗子,如果你要使用React,你就下载React模块,然后把它导入到你的代码中。几乎每一个流行的JavaScript库都可以这样做。

哦,就像Angular一样!

-Angular已经是2015年的了。但是,你说的挺对的。Angular依旧坚挺着,但是并肩的还有VueJS、RxJS和其他炫酷十足的库。你想学不?

我们还是接着用React吧,我现在已经学了太多的东西了。所以,如果我要用React的话,我就得用npm安装React,然后使用 Browserify ?

-恩,是的。

获取一堆依赖,然后把它们打包,这貌似有点复杂啊。

-是的,这就是我们为什么使用Grunt、GUlp或者Broccoli来自动化运行Browserify的原因。哦,见鬼,你现在甚至可以用Mimosa了。

Grunt?Gulp?Broccoli?Mimosa?我们到底在讨论什么鬼东西?

-任务管理器呀。但是它们已经不像之前那么炫酷了。我们在2015年使用那些东西,然后我们使用Makefiles,但是现在我们用Webpack来打包所有东西。

Makefiles?我以为那只用在C或C++项目里。

-是的,但是在web开发中,我们喜欢先把事情搞复杂,然后再回归本源。我们每年都是这么做的,你就等着吧,一年或者两年内我们都能在web里写汇编了。

哎,你刚说到了什么Webpack东东?

-它是另一个浏览器模块管理器,也是一个任务管理器。它就像一个更牛的Browserify。

哦,好吧,那它牛在哪里呢?

-恩,也许不是很牛,他只是告诉你如何更好的绑定你的依赖。Webpack允许你使用不同的模块管理器,不仅仅是CommonJS,ES6支持的模块都可以。

我都已经完全被CommonJS/ES6搞糊涂了。

-大家都被搞糊涂了,但是伴随着SystemJS,那些东西你都不用关心了。

Word天呐,又一个什么JS。SystemJS又是什么?

-恩,不像Browserify和Webpack 1.x版本,SystemJS是一个动态模块加载器,它允许你把多个模块打包成多个文件,而不是打包成一个文件。

等会儿,我原以为我们要把我们的库打包成一个大文件,然后加载就行了!

-是的,但是因为HTTP/2马上就要来了,多个HTTP请求其实更好。

等会儿,所以为了使用React我们不能仅仅添加三个库?

-是的。我是说,你可以把它们当做脚本从CDN引进来,但是你依然需要引入Babel。

哎,这样就行了吗?

-是的,你需要引入整个babel-core,而且不应该用于生产环境。发布到生产环境之前,你需要运行一些任务来确保你的项目一切正常,就像把召唤撒旦的仪式整成一个煎蛋配方一样。你需要压缩、混淆、样式内联、延迟加载脚本。

我懂了,我懂了。如果我不能直接从CDN中引入这些库,那我该这么做?

-我会使用使用Webpack、SystemJS和Babel来转义Typescript。

Typescript?我原以为我们是用JavaScript在码代码!

-Typescript也是JavaScript,或者更好的一种说法是,Typescript是JavaScript的超集,是基于ES6的更屌的JavaScript。你还记得吧,就是我们刚才讲到的第六版。

我以为ES2016+已经是ES6的一个超集了!为什么我们现在使用的这个东东叫Typescript?

-哦,因为它允许我们像使用类型化语言一样使用JavaScript,并且能够减少运行时错误。2016年了,你应该在你的JavaScript代码中增加些类型。

Typescript很明显做到了这些。

-Flow也做到了这些,尽管它只是做输入检测,而作为JavaScript的超集,它需要编译。

额,Flow是。。。?

-它是一个静态类型检查器,也是Facebook出品的。它是用OCaml写的,因为函数式编程炫酷得不要不要的。

OCaml?函数式编程?

_-年轻人,现在牛逼的程序员都会用的,你要知道,现在可是2016年了。函数式编程?高阶函数?柯里化?纯函数?

我不知道你在说啥。

-刚开始谁都会这样的。你只要知道函数式编程比面向对象编程(OOP)更屌就行了,2016年我们就都应该用函数式编程。

等下,我在大学学过面向对象编程,我觉得挺好啊。

-Java在被Oracle买下之前也挺不错的啊。我的意思是说,面向对象编程在过去是挺好,并且在现在也仍然有它的用武之地,但是现在大家正意识到修改状态是很难的,所以现在大家都趋向于使用不可变对象和函数式编程。haskell那伙人已经整了好多年了,-就不说Eml那帮人了-但是幸运的是,在web开发中我们可以使用像Ramda这样的库来实现纯JavaScript进行函数式编程了。

为了讨论方便,你刚才是不是又提到了几个名词?Ramnda是个什么东西?

-不是Ramnda。就像Lambda。你不知道吗,David Chambers的那个库?

David谁?

-David Chambers。一个很牛的哥们儿。玩儿mean Coup游戏的(Plays a mean Coup game)。Ramda的贡献者之一。如果你想学习函数式编程的话,你应该了解下Erik Meijer。

Erik Meijer是何方神圣?

-也是函数式编程一哥们儿,很牛。他在一堆演讲里面批评了Agile。你也应该看看下面这些人的东西:Tj,Jash Kenas,Sindre Sorhus,Paul Irish,Addy Osmani。-

好吧。现在我必须打断你了。所有这一切都很好,但是我只是要获取数据并展现出来,这些东西一下子就搞复杂了,而且是不必要的。我很确定,我没有必要为了创建一个动态数据表格而去了解这些人,或者学习这些东西。让我回到React。我怎么才能用React从服务器获取数据呢?

-是这样的,你不能用React来获取数据,你只能用React来展示数据。

我了个去。那你用什么来获取数据?

-你可以使用Fetch从服务器上fetch(获取)数据。

啥?你用Fetch来fetch(获取)数据?起名儿的这位是不是没上学啊。

-恩,我也知道。Fetch是服务器完成XHR请求的本地实现。

哦,那就是AJAX。

-AJAX只是使用XHR。但是Fetch允许你使用promise来实现ajax请求,这样的话你就可以摆脱回调地狱了。

回调地狱是什么毛线?

-是这样的。每次你完成一个异步请求,你就需要等待服务器的响应,这样的话你就会在一个函数里面增加一个函数,这就叫做回调金字塔,也就是回调地狱。

哦,好吧。Promise可以解决这个问题?

-必须的。通过promise来写回调,你可以写出更优雅更容易理解的代码,你可以去模拟数据并测试代码,你也可以同时发起多个请求并等待它们全部加载完成。

这些都可以用Fetch来实现?

-是的,但是前提是用户使用了完全兼容的常青浏览器(evergreen browser),否则你需要引入一个Fetch polyfill或者使用Request、Bluebird或Axios。

我需要知道多少个库?到底有多少个库啊?

-这就是JavaScript。有成千上万个库可以实现同样的事情。实际上,我们知道js库,我们也拥有最好的js库。我们的库很庞大,有时候我们也会引入Guy Fieri的字符画。

你刚刚说到了Guy Fieri?我们不说他了。Bluebird、Request和Axios库是用来干什么?

-这些库用来操作XHR,然后返回promise。

jQuery的AJAX方法也可以返回promise了吧?

-2016年我们不再使用jQuery了。就用Fetch,如果浏览器没有的话就添加个polyfill,或者用Bluebird、Request、Axios代替都可以。然后在async函数里使用await来管理promise,这样你就可以很好的控制整个流了。

这是你第三次提到await了,但是我还不知道它是个啥。

-Await允许你拦截一个异步回调,这样当获取到数据的时候你就可以更好的去控制,并且代码也会具有更好的可读性。这很酷,而你只需要在Babel里设置stage-3配置,或者使用syntax-async-functions插件和transform-async-to-generator插件。

疯了吧。

-没有,我来告诉你什么才是疯:想用await你需要先预编译Typescript代码,然后用Babel来转义。

啥?Typescript不包含await?

-下个版本就会包含了,但是1.7版本只是针对ES6,所以如果你想在浏览器里使用await,首先你需要把Typescript代码预编译成ES6,然后再用Babel转义成ES5。

现在我已经无语了。

-其实很简单的。用Typescript来写代码。所有使用Fetch的模块编译成ES6,然后设置Babel的stage-3的配置,再用SystemJS来加载。如果你没有Fetch,就添加个polyfill,或者使用Bluebird、Request、Axios,使用await来处理所有的promise。

我们对于简单的定义不一样。好了,有了那个东东我最终获取了数据,现在我可以用React来展示数据了吧?

-你的应用需要处理状态变化吗?

额,不需要吧。我只是要展示数据。

-哦,谢天谢地。否则我就必须向你解释Flux了,还有它的实现,比如Flummox、Alt、Fluxible。不过说实话,你应该使用Redux。

我们就略过这些名字吧。我就只是想展示数据而已。

-哦,如果你只是要展示数据,那么一开始就不需要React。用模板引擎就可以了。

你玩儿我呢?你以为这样玩儿很爽?你就是这样对待你的所爱?

-我只是在解释你可以用哪些东西。

停,可别说了。

-我的意思是,如果我是你的话,尽管是使用模板引擎,但我仍然会使用Typescript + SystemJS + Babel组合。

我需要在页面上展示数据,不是在玩儿真人快打。你就告诉我应该用哪个模板引擎,我直接用就行了。

-有很多模板引擎的,你熟悉哪个呢?

额,我想不起来名字了,过去很长时间了。

-jTemplates?jQote?PURE?

额,不记得。还有其他的吗?

-Transparency?JSRender?MarkupJS?KnockoutJS?这个有双向绑定。

还有其他的吗?

-PlatesJS?jQuery-tmpl?Handlebars?一些人仍然在使用它。

可能是吧。有和最后一个相似的吗?

-Mustache?underscore?我认为Lodash都有模板引擎了,但是那些都是2014年的了。

额,有新一点儿的吗?

-Jade?DustJS?

不是。

-DotJS?EJS?

不是。

-Nunjucks?ECT?

不是。

-恩,已经没人喜欢Coffeescript语法了。Jade?

不是,你已经说过Jade了。

-我是说Pug。我我的意思是说Jade。我的意思是,Jade现在的名字是Pug。

哎,不是。我想不起来了。你用哪个?

-我可能只用ES6原生模板字符串。

让我猜下。这个需要ES6。

-是的。

为了适应不同的浏览器,得使用Babel转义。

-是的。

如果我不想添加整个核心库,我需要使用npm来作为模块加载。

-是的。

需要Browserify或者Wepback,或者类似SystemJS的东西。

-是的。

如果不用Webpack,最好使用一个任务管理器。

-是的。

但是,因为我应该使用函数式编程和类型化语言,所以我需要预编译Typescript或者添加一个Flow。

-是的。

然后,如果我想使用await的话,还必须使用Babel。

-是的。

这样我就可以使用Fetch、promise、控制流和各种吊炸天的东西。

-别忘了,如果不支持Fetch的话,给Fetch添加一个polyfill,Sarafi就不支持。

行了,我觉得我们就说到这吧。实际上,我觉得我也就这样了,我是做不了web开发了,我是写不了JavaScript了。

-没事,再过几年,我们会用Elm或者WebAssembly来写代码。

我想回去做后端。我受不了这么多的变化、版本、编译器和转义工具。JavaScript社区如果认为有人能跟上这种节奏,那这社区一定是疯了。

-我明白了。你应该去Python社区。

为什么?

-听说过Python3吗?

更新:感谢指出排版和其他错误,我会持续更新这篇文章。讨论区请移步 HackerNews Reddit