2016年学习JavaScript是怎样的一种体验(转)
转自:http://www.zcfy.cc/article/how-it-feels-to-learn-javascript-in-2016-hacker-noon-1871.html
在这篇文章的写作过程中没有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。一个很酷的家伙,想要彻底颠覆 JavaScript 编程方式。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。