在讲 ES 2015 新语法以前,先来讲一下为何叫 ES。JavaScript 是这门语言的名称,它有一个为它制定标准化的组织 European Computer Manufacturers Association,直译就是欧洲计算机制造商协会。这个 ECMA 制定的 JavaScript 的实现标准,被称为 ECMAScript,不一样组织写出来的 JavaScript 语言都要遵照这个 ECMAScript 标准,因此就简写为 ES+版本号。css
这套 ES 标准在2015年以前最高的版本是5.1,也是惟一一个须要你们注意的版本:尽管各个流浏览器实现的 ES 新语法都有差别,但5.1版本是目前各大主流浏览器都支持的。这里再介绍一下传说中的 Babel.js 项目,它的目的很简单,把新语法翻译成老标准的语法。最主要的应用,就是把你写的 ES 201x 的语法翻译成 ES5.1,这样各个浏览器都是支持的。前端
在2015年的时候,ES6 正式发布,也很天然按照年份被称为 ES 2015。以后 ES 每一年都发布一个版本,今年也就是2018年的草案也已经在年初发布了,从6开始今年该到版本9了可是很差记,因此你们都喜欢用 201x 来称呼。虽然语法是归在不一样版本内的,可是各家 JS 的实现进度不一样。你问一个语法具体是哪一个版本实现的,估计10我的里有9个说不清楚,反正不是5.1的语法,因此你们也不区分了,直接都叫 ES 201x。jquery
已经出来了好几年了,因此各类介绍的文章也很全面,我就不复制粘贴又臭又长了。在这里向你们推荐几个学习语法的英文网站,我就是从 babel 和 es6-features.org 这两个网站学习的:webpack
https://babeljs.io/learn-es2015/es6
http://es6-features.org/web
https://css-tricks.com/lets-learn-es2015/ajax
中文的话,能够看这个网站:redux
http://es6.ruanyifeng.com后端
另外呢,MDN( https://developer.mozilla.org ) 上对于这些语法的介绍是很全面的,中文英文也都有。数组
那么接下来呢,我打算讲一讲这些新语法都解决了哪些问题,你应该怎么使用它,这是通常介绍语法的文章不会介绍的。提早说明一下,我我的平时都在用 airbnb 的代码风格,因此这些代码都会延用它家的风格来写。
首先要说的是,因为 var 的问题不少,新语法中永远不要用 var。它有的主要问题做用域是整个函数(function)而不是语法块(block),致使的最大问题是会让 closure 出现“bug”。并且这个“bug”还很经典,出如今许多著名语言中,其中也包括了
脚本界的老二 Python。构造这个 bug 的方法很简单:
1 { 2 const funcs = []; 3 for (var i = 0; i < 5; i++) { 4 funcs.push(() => i); 5 } 6 funcs.map(fn => fn()); 7 }
把上面的代码粘贴到浏览器的 console 里面,结果是5个5,而不是 [0, 1, 2, 3, 4],惊不惊喜,意不意外?虽然把上面的 var 换成 let 就成功的解决了这个问题,但按照如今 JS 倾侧 FP 而不鼓励使用 for 的趋势,下面的方法才是正确的使用姿式:
1 import { times } from 'lodash'; 2 3 const funcs = times(5, i => () => i);
lodash 是一个著名并且很是流行的 JS 库,之后会有专门的文章介绍它。下面再给出其它语言生成这个 clusure 数组的正确投资,用 Python 举例:
1 funcs = [] 2 for i in range(5): 3 funcs.append((lambda x: lambda: x)(i)) 4 [fn() for fn in funcs]
再嵌一层函数来返回须要生成函数的函数,而后再把参数传过去。
那么 const 呢,我在另一个扯一扯编译语言的系列中已经提过,能用 const 就不要用 let。若是你使用了 eslint 的话,只赋值过一次的 let 变量会被提示应该换成 const。
总结下来,就是用 const 代替 var,const 实在解决不了的状况,再用 let。不要以为 const 多敲俩字母就不爱用,早几年还能看到 let 满天飞没有 const 的项目,如今一个项目里 let 出现的少才说明做者的水平高。一旦用了 var 你就是菜B一个,因此千万不要用。
简单来说是 function () {} 的简写形式,括号和参数列表写在 => 前面,大括号和函数体写在 => 后面,可是有3个很是重要的区别:
最后一点并不重要,可是 airbnb 的代码风格要求在只有一个参数时不使用括号,因此我在这里专门提到了,但前面两点都有值得说的地方。
第一条中再也不带 this 等上下文变量,是为了解决以前经常被诟病的搞不清当前 this 是啥的问题。JS 的对象模型是非主流的 prototype(原型)模型,在调用对象函数时,实际上使用的是相似 func.apply(this, arguments) 或者 func.call(this, ...arguments) 来实现的。因此当对象成员函数里面又套了一层 function 的时候,因为在内层函数声明的时候 this 并无关联任何上下文变量,而致使在内层函数中 this 使用时并非该对象,常常会致使试图调用 undefined 的成员函数的问题。并且由于这个模型实在是太非主流了,因此你们常常会忘掉甚至搞不清。因此这个语法在很大程度上就是为了解决 this 的问题。
第二条也会带来一个问题,不少时候咱们想返回一个 Object,好比 { foo: 123, bar: 'baz' },可是 {} 这个东西又是函数体。很遗憾编译器没那么聪明,当你写 () => { foo: 123, bar: 'baz' } 的时候,会报语法错误。解决的办法也很简单,() 虽然套在表达式的外面它仍是一个表达式,因此 () => ({ foo: 123, bar: 'baz' }) 这种写法就没问题了。在 FP 流行的今天,这个技巧的使用真的是十分常见的,因此请养成想要返回 Object 时,直接先敲 ({}) 的习惯。
Babel 的文档里面说,“This is similar to string interpolation features in Perl, Python and more.”,然而我并不以为它跟 string interpolation 有什么本质上的不一样。这里介绍一个技巧,若是你想 google 其它语言的这个语法的话,好比 Kotlin,那么你应该用“string interpolation kotlin”做关键字,搜 template 可能不必定是你想要的结果,但 interpolation 必定能搜到。
这个语法自己已是如今语言的标配了,用标准键盘左上角的 `` 来包裹字符,能够跨行,里面所有的 ${EXPRESSION} 都会变成 EXPRESSION.toString() 插入到字符串中。
可是 JS 的这个语法还有一个神奇的用法,废话很少说直接上代码:
1 function test() { return JSON.stringify(arguments); } 2 test`foo${123}bar${456+789}baz`
你将会看到这样的结果:{"0":["foo","bar","baz"],"1":123,"2":1245} 。第一个参数是正常的字符串部分,按照插入表达式的地方给切开了,剩下的参数则是其它表达式的值。虽然你不太可能会有机会须要用这语法来实现本身的库的功能,但仍是有挺大的机会碰到第三方库提供这样的“语法支持”,好比 React 社区一些 CSS 库。当你看到的时候,就不会以为奇怪,到底人家的库是怎么写的了。
做为一门现代语言,没有模块化的设计是不可能达到工程级的使用的。过去咱们在使用 JS 的时候,都是在 HTML 里导入 JavaScript 库好比 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>。但这么作会带来一个问题就是可能会污染全局变量,一个现实的结果就是,假若有两个库都用了同一个全局变量名,那么你就只能很当心的在引用两个库的中间插入一段代码,重命名其中一个全局变量的名称。另一个问题是,当一个库须要使用另一个库的时候,必须严格遵照必定的顺序。
模块化以后,带来了两个好处,一个是能够自由的在本模块中自由的命名,另外一个是使用 webpack 等工具打包时,能够只打包使用到的代码,从而减少须要发布的 JS 文件大小,节省网络传输时间加快页面加载速度。
遗憾的是,因为 JS 的模块化并无统一的标准,致使出现了各类不一样的加载方式。不过因为 webpack 和 babel 的存在,在写前端代码时,你只要使用 export/import 这一套语法就够了。但若是写 Node 代码,而你又不想使用 Babel 的话,那就得注意一下,因为打包方式不一样,一些在导入 default 时会要求 require(XXX).default,好比 redux-thunk。不过这种状况通常也都是前端库的代码,若是纯后端的话应该也不太须要担忧。
这个语法也挺简单的,跟16进制相似,0b 或者 0B 是2进制的前缀,用字母 O 替换 X 就是8进制的前缀。可是有一点须要注意的地方,你本身写代码的时候用用能够,可是不要期望 parseInt 能够像对十六进制同样起做用。而像 isNaN、Number 之类的,跟浏览器自己的支持也有关,就算你上了 polyfill 也不必定会支持。固然你们会用这个语法的几率也不大。
关于 Symbol(符号)、Set、Map、WeekSet、WeekMap,我的感受不使用其实影响也不大,并且 polyfill 也不能作到彻底支持,作前端就不要考虑了。for ... of 的语法意义也不大,毕竟如今主流已经不推荐写 for 了。iterator 自己没有 Generator 好用,polyfill 支持也有限,因此也没啥意义。剩下的 API 变化也没什么值得说的,前端也只要注意加个 babel-polyfill 之类的就够了。
Proxy、Reflect、Decorator 算是 meta-programming 的内容,须要读个人文章想来水平还不到有机会写神奇功能的水平。若是想实现一些 fancy 的功能,这几个东西仍是颇有用的。举个例子,好比你想监视(observe)对象成员值的变化,老的作法你就得跑过去,获取这个对象当前全部的属性,而后再都给封装一遍,就算这样若是人家再加了个新成员变量你仍是没办法知道。上了 Proxy 你就不用那么麻烦了,全部的操做都会在你的 proxy handler 里面过一遍,实现起来就简单多了。
其它的语法,Promise、async/await、Generator 会在异步里面讲,函数的变化、class、Rest/Spread、Destructing 相关性比较高也会放在同一个章节里面讲。