diff --git a/docs/array.md b/docs/array.md index 24b0da3..e693e61 100644 --- a/docs/array.md +++ b/docs/array.md @@ -182,7 +182,7 @@ for (let [index, elem] of ['a', 'b'].entries()) { ## 数组实例的includes() -Array.protypeto.includes方法返回一个布尔值,表示某个数组是否包含给定的值。该方法属于ES7。 +`Array.protypeto.includes`方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的`includes`方法类似。该方法属于ES7,但Babel转码器已经支持。 ```javascript [1, 2, 3].includes(2); // true @@ -190,13 +190,35 @@ Array.protypeto.includes方法返回一个布尔值,表示某个数组是否 [1, 2, NaN].includes(NaN); // true ``` -该方法的第二个参数表示搜索的起始位置,默认为0。 +该方法的第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从0开始。 ```javascript [1, 2, 3].includes(3, 3); // false [1, 2, 3].includes(3, -1); // true ``` +没有该方法之前,我们通常使用数组的`indexOf`方法,检查是否包含某个值。 + +```javascript +if (arr.indexOf(el) !== -1) { + // ... +} +``` + +`indexOf`方法有两个缺点,一是不够语义化,它的含义是找到参数值的第一个出现位置,所以要去比较是否不等于-1,表达起来不够直观。二是,它内部使用严格相当运算符(===)进行判断,这会导致对`NaN`的误判。 + +```javascript +[NaN].indexOf(NaN) +// -1 +``` + +`includes`使用的是不一样的判断算法,就没有这个问题。 + +```javascript +[NaN].includes(NaN) +// true +``` + 下面代码用来检查当前环境是否支持该方法,如果不支持,部署一个简易的替代版本。 ```javascript @@ -208,6 +230,11 @@ const contains = (() => contains(["foo", "bar"], "baz"); // => false ``` +另外,Map和Set数据结构有一个`has`方法,需要注意与`includes`区分。 + +- Map结构的`has`方法,是用来查找键名的,比如`Map.prototype.has(key)`、`WeakMap.prototype.has(key)`、`Reflect.has(target, propertyKey)`。 +- Set结构的`has`方法,是用来查找值的,比如`Set.prototype.has(value)`、`WeakSet.prototype.has(value)`。 + ## 数组推导 数组推导(array comprehension)提供简洁写法,允许直接通过现有数组生成新数组。这项功能本来是要放入ES6的,但是TC39委员会想继续完善这项功能,让其支持所有数据结构(内部调用iterator对象),不像现在只支持数组,所以就把它推迟到了ES7。Babel转码器已经支持这个功能。 diff --git a/docs/module.md b/docs/module.md index 106dc8b..ebcd2a5 100644 --- a/docs/module.md +++ b/docs/module.md @@ -20,11 +20,13 @@ import { stat, exists, readFile } from 'fs'; 所以,ES6可以在编译时就完成模块编译,效率要比CommonJS模块高。 +需要注意的是,ES6的模块自动采用严格模块,不管你有没有在模块头部加上`"use strict"`。 + ## export命令 -模块功能主要由两个命令构成:export和import。export命令用于用户自定义模块,规定对外接口;import命令用于输入其他模块提供的功能,同时创造命名空间(namespace),防止函数名冲突。 +模块功能主要由两个命令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。 -ES6允许将独立的JS文件作为模块,也就是说,允许一个JavaScript脚本文件调用另一个脚本文件。该文件内部的所有变量,外部无法获取,必须使用export关键字输出变量。下面是一个JS文件,里面使用export命令输出变量。 +一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。下面是一个JS文件,里面使用export命令输出变量。 ```javascript // profile.js @@ -58,6 +60,23 @@ export function multiply (x, y) { 上面代码对外输出一个函数multiply。 +通常情况下,export输出的变量就是本来的名字,但是可以使用as关键字重命名。 + +```javascript +function v1() { ... } +function v2() { ... } + +export { + v1 as streamV1, + v2 as streamV2, + v2 as streamLatestVersion +}; +``` + +上面代码使用as关键字,重命名了函数v1和v2的对外接口。重命名后,v2可以用不同的名字输出两次。 + +最后,export命令可以出现在模块的任何位置,只要处于模块顶层就可以。如果处于块级作用域内,就会报错,下面的import命令也是如此。 + ## import命令 使用export命令定义了模块的对外接口以后,其他JS文件就可以通过import命令加载这个模块(文件)。 @@ -72,9 +91,9 @@ function setName(element) { } ``` -上面代码属于另一个文件main.js,import命令就用于加载profile.js文件,并从中输入变量。import命令接受一个对象(用大括号表示),里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块(profile.js)对外接口的名称相同。 +上面代码的import命令,就用于加载profile.js文件,并从中输入变量。import命令接受一个对象(用大括号表示),里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块(profile.js)对外接口的名称相同。 -如果想为输入的变量重新取一个名字,import语句中要使用as关键字,将输入的变量重命名。 +如果想为输入的变量重新取一个名字,import命令要使用as关键字,将输入的变量重命名。 ```javascript import { lastName as surname } from './profile'; @@ -129,7 +148,7 @@ export function circumference(radius) { ```javascript // main.js -import { area, circumference } from 'circle'; +import { area, circumference } from './circle'; console.log("圆面积:" + area(4)); console.log("圆周长:" + circumference(14)); @@ -138,7 +157,7 @@ console.log("圆周长:" + circumference(14)); 上面写法是逐一指定要输入的方法。另一种写法是整体输入。 ```javascript -import * as circle from 'circle'; +import * as circle from './circle'; console.log("圆面积:" + circle.area(4)); console.log("圆周长:" + circle.circumference(14)); @@ -151,7 +170,7 @@ module命令可以取代import语句,达到整体输入模块的作用。 ```javascript // main.js -module circle from 'circle'; +module circle from './circle'; console.log("圆面积:" + circle.area(4)); console.log("圆周长:" + circle.circumference(14)); @@ -161,7 +180,7 @@ module命令后面跟一个变量,表示输入的模块定义在该变量上 ## export default命令 -从前面的例子可以看出,使用import的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。 +从前面的例子可以看出,使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。 为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到`export default`命令,为模块指定默认输出。 @@ -182,7 +201,7 @@ import customName from './export-default'; customName(); // 'foo' ``` -上面代码的import命令,可以用任意名称指向`export-default.js`输出的方法。需要注意的是,这时import命令后面,不使用大括号。 +上面代码的import命令,可以用任意名称指向`export-default.js`输出的方法,这时就不需要知道原模块输出的函数名。需要注意的是,这时import命令后面,不使用大括号。 export default命令用在非匿名函数前,也是可以的。 @@ -226,8 +245,16 @@ export function crc32(){}; export default function (x, y) { return x * y; }; + +// 或者 + +function add(x, y) { + return x * y; +}; +export {add as default}; + // app.js -import { default } from 'modules'; +import { default as xxx } from 'modules'; ``` 有了`export default`命令,输入模块时就非常直观了,以输入jQuery模块为例。 diff --git a/docs/number.md b/docs/number.md index ea7ff8b..4225cc1 100644 --- a/docs/number.md +++ b/docs/number.md @@ -430,3 +430,24 @@ ES6新增了6个三角函数方法。 - Math.asinh(x) 返回x的反双曲正弦(inverse hyperbolic sine) - Math.acosh(x) 返回x的反双曲余弦(inverse hyperbolic cosine) - Math.atanh(x) 返回x的反双曲正切(inverse hyperbolic tangent) + +## 指数运算符 + +ES7新增了一个指数运算符(`**`),目前Babel转码器已经支持。 + +```javascript +2 ** 2 // 4 +2 ** 3 // 8 +``` + +指数运算符可以与等号结合,形成一个新的赋值运算符(`**=`)。 + +```javascript +let a = 2; +a **= 2; +// 等同于 a = a * a; + +let b = 3; +b **= 3; +// 等同于 b = b * b * b; +``` diff --git a/docs/reference.md b/docs/reference.md index 6c2b2dd..9b6c60a 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -26,26 +26,15 @@ - Benjamin De Cock, [Frontend Guidelines](https://github.com/bendc/frontend-guidelines): ES6最佳实践 - Jani Hartikainen, [ES6: What are the benefits of the new features in practice?](http://codeutopia.net/blog/2015/01/06/es6-what-are-the-benefits-of-the-new-features-in-practice/) -## 语法点 +## let和const - Kyle Simpson, [For and against let](http://davidwalsh.name/for-and-against-let): 讨论let命令的作用域 - kangax, [Why typeof is no longer “safe”](http://es-discourse.com/t/why-typeof-is-no-longer-safe/15): 讨论在块级作用域内,let命令的变量声明和赋值的行为 - Axel Rauschmayer, [Variables and scoping in ECMAScript 6](http://www.2ality.com/2015/02/es6-scoping.html): 讨论块级作用域与let和const的行为 + +## 解构赋值 + - Nick Fitzgerald, [Destructuring Assignment in ECMAScript 6](http://fitzgeraldnick.com/weblog/50/): 详细介绍解构赋值的用法 -- Nicholas C. Zakas, [Understanding ECMAScript 6 arrow functions](http://www.nczonline.net/blog/2013/09/10/understanding-ecmascript-6-arrow-functions/) -- Jack Franklin, [Real Life ES6 - Arrow Functions](http://javascriptplayground.com/blog/2014/04/real-life-es6-arrow-fn/) -- Axel Rauschmayer, [Handling required parameters in ECMAScript 6](http://www.2ality.com/2014/04/required-parameters-es6.html) -- Axel Rauschmayer, [ECMAScript 6’s new array methods](http://www.2ality.com/2014/05/es6-array-methods.html): 对ES6新增的数组方法的全面介绍 -- Dmitry Soshnikov, [ES6 Notes: Default values of parameters](http://dmitrysoshnikov.com/ecmascript/es6-notes-default-values-of-parameters/): 介绍参数的默认值 -- Ragan Wald, [Destructuring and Recursion in ES6](http://raganwald.com/2015/02/02/destructuring.html): rest参数和扩展运算符的详细介绍 - -## Collections - -- Mozilla Developer Network, [WeakSet](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet):介绍WeakSet数据结构 -- Dwayne Charrington, [What Are Weakmaps In ES6?](http://ilikekillnerds.com/2015/02/what-are-weakmaps-in-es6/): WeakMap数据结构介绍 -- Axel Rauschmayer, [ECMAScript 6: maps and sets](http://www.2ality.com/2015/01/es6-maps-sets.html): Set和Map结构的详细介绍 -- Jason Orendorff, [ES6 In Depth: Collections](https://hacks.mozilla.org/2015/06/es6-in-depth-collections/):Set和Map结构的设计思想 -- Axel Rauschmayer, [Converting ES6 Maps to and from JSON](http://www.2ality.com/2015/08/es6-map-json.html): 如何将Map与其他数据结构互相转换 ## 字符串 @@ -59,6 +48,19 @@ - Mathias Bynens, [Unicode-aware regular expressions in ES6](https://mathiasbynens.be/notes/es6-unicode-regex): 详细介绍正则表达式的u修饰符 - Axel Rauschmayer, [New regular expression features in ECMAScript 6](http://www.2ality.com/2015/07/regexp-es6.html):ES6正则特性的详细介绍 +## 数组 + +- Axel Rauschmayer, [ECMAScript 6’s new array methods](http://www.2ality.com/2014/05/es6-array-methods.html): 对ES6新增的数组方法的全面介绍 +- TC39, [Array.prototype.includes](https://github.com/tc39/Array.prototype.includes/): 数组的includes方法的规格 + +## 函数 + +- Nicholas C. Zakas, [Understanding ECMAScript 6 arrow functions](http://www.nczonline.net/blog/2013/09/10/understanding-ecmascript-6-arrow-functions/) +- Jack Franklin, [Real Life ES6 - Arrow Functions](http://javascriptplayground.com/blog/2014/04/real-life-es6-arrow-fn/) +- Axel Rauschmayer, [Handling required parameters in ECMAScript 6](http://www.2ality.com/2014/04/required-parameters-es6.html) +- Dmitry Soshnikov, [ES6 Notes: Default values of parameters](http://dmitrysoshnikov.com/ecmascript/es6-notes-default-values-of-parameters/): 介绍参数的默认值 +- Ragan Wald, [Destructuring and Recursion in ES6](http://raganwald.com/2015/02/02/destructuring.html): rest参数和扩展运算符的详细介绍 + ## 对象 - Addy Osmani, [Data-binding Revolutions with Object.observe()](http://www.html5rocks.com/en/tutorials/es7/observe/): 介绍Object.observe()的概念 @@ -81,6 +83,14 @@ - Jason Orendorff, [ES6 In Depth: Symbols](https://hacks.mozilla.org/2015/06/es6-in-depth-symbols/) - Keith Cirkel, [Metaprogramming in ES6: Symbols and why they're awesome](http://blog.keithcirkel.co.uk/metaprogramming-in-es6-symbols/): Symbol的深入介绍 +## Set和Map + +- Mozilla Developer Network, [WeakSet](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet):介绍WeakSet数据结构 +- Dwayne Charrington, [What Are Weakmaps In ES6?](http://ilikekillnerds.com/2015/02/what-are-weakmaps-in-es6/): WeakMap数据结构介绍 +- Axel Rauschmayer, [ECMAScript 6: maps and sets](http://www.2ality.com/2015/01/es6-maps-sets.html): Set和Map结构的详细介绍 +- Jason Orendorff, [ES6 In Depth: Collections](https://hacks.mozilla.org/2015/06/es6-in-depth-collections/):Set和Map结构的设计思想 +- Axel Rauschmayer, [Converting ES6 Maps to and from JSON](http://www.2ality.com/2015/08/es6-map-json.html): 如何将Map与其他数据结构互相转换 + ## Iterator - Mozilla Developer Network, [Iterators and generators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators) @@ -138,6 +148,7 @@ - Jack Franklin, [JavaScript Modules the ES6 Way](http://24ways.org/2014/javascript-modules-the-es6-way/): ES6模块入门 - Axel Rauschmayer, [ECMAScript 6 modules: the final syntax](http://www.2ality.com/2014/09/es6-modules-final.html): ES6模块的介绍,以及与CommonJS规格的详细比较 - Dave Herman, [Static module resolution](http://calculist.org/blog/2012/06/29/static-module-resolution/): ES6模块的静态化设计思想 +- Jason Orendorff, [ES6 In Depth: Modules](https://hacks.mozilla.org/2015/08/es6-in-depth-modules/): ES6模块设计思想的介绍 ## 工具 diff --git a/docs/string.md b/docs/string.md index fb65336..b1e575a 100644 --- a/docs/string.md +++ b/docs/string.md @@ -286,14 +286,14 @@ function authorize(user, action) { var x = 1; var y = 2; -console.log(`${x} + ${y} = ${x+y}`) +`${x} + ${y} = ${x + y}` // "1 + 2 = 3" -console.log(`${x} + ${y*2} = ${x+y*2}`) +`${x} + ${y * 2} = ${x + y * 2}` // "1 + 4 = 5" var obj = {x: 1, y: 2}; -console.log(`${obj.x + obj.y}`) +`${obj.x + obj.y}` // 3 ``` @@ -304,7 +304,7 @@ function fn() { return "Hello World"; } -console.log(`foo ${fn()} bar`); +`foo ${fn()} bar` // foo Hello World bar ``` @@ -318,6 +318,13 @@ var msg = `Hello, ${place}`; // 报错 ``` +由于模板字符串的大括号内部,就是执行JavaScript代码,因此如果表达式放在引号之中,将会原样输出。 + +```javascript +`Hello ${'World'}` +// "Hello World" +``` + ## 标签模板 模板字符串的功能,不仅仅是上面这些。它可以紧跟在一个函数名后面,该函数将被调用来处理这个模板字符串。这被称为“标签模板”功能(tagged template)。