mirror of
https://github.com/ruanyf/es6tutorial.git
synced 2025-05-24 10:22:23 +00:00
整理格式
This commit is contained in:
parent
60b767cae5
commit
46395127c2
18
docs/let.md
18
docs/let.md
@ -25,7 +25,7 @@ for循环的计数器,就很合适使用let命令。
|
||||
```javascript
|
||||
|
||||
for(let i = 0; i < arr.length; i++){}
|
||||
|
||||
|
||||
console.log(i)
|
||||
//ReferenceError: i is not defined
|
||||
|
||||
@ -80,9 +80,9 @@ function do_something() {
|
||||
|
||||
```javascript
|
||||
|
||||
if (1) {
|
||||
typeof x; // ReferenceError
|
||||
let x;
|
||||
if (1) {
|
||||
typeof x; // ReferenceError
|
||||
let x;
|
||||
}
|
||||
|
||||
```
|
||||
@ -93,16 +93,16 @@ if (1) {
|
||||
|
||||
```javascript
|
||||
|
||||
var tmp = 123;
|
||||
var tmp = 123;
|
||||
|
||||
if (true) {
|
||||
tmp = 'abc'; // ReferenceError
|
||||
let tmp;
|
||||
let tmp;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。
|
||||
上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。
|
||||
|
||||
ES6明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些命令,就会报错。
|
||||
|
||||
@ -114,10 +114,10 @@ if (true) {
|
||||
// TDZ开始
|
||||
tmp = 'abc'; // ReferenceError
|
||||
console.log(tmp); // ReferenceError
|
||||
|
||||
|
||||
let tmp; // TDZ结束
|
||||
console.log(tmp); // undefined
|
||||
|
||||
|
||||
tmp = 123;
|
||||
console.log(tmp); // 123
|
||||
}
|
||||
|
@ -276,14 +276,14 @@ function clone(origin) {
|
||||
将多个对象合并到某个对象。
|
||||
|
||||
```javascript
|
||||
const merge =
|
||||
const merge =
|
||||
(target, ...sources) => Object.assign(target, ...sources);
|
||||
```
|
||||
|
||||
如果希望合并后返回一个新对象,可以改写上面函数,对一个空对象合并。
|
||||
|
||||
```javascript
|
||||
const merge =
|
||||
const merge =
|
||||
(...sources) => Object.assign({}, ...sources);
|
||||
```
|
||||
|
||||
@ -516,7 +516,7 @@ Symbol.for方法在全局环境中搜索指定key的Symbol值,如果存在就
|
||||
|
||||
```javascript
|
||||
|
||||
Symbol.for("bar") === Symbol.for("bar")
|
||||
Symbol.for("bar") === Symbol.for("bar")
|
||||
// true
|
||||
|
||||
Symbol("bar") === Symbol("bar")
|
||||
@ -530,7 +530,7 @@ Symbol.keyFor方法返回一个已登记的Symbol类型值的key。
|
||||
|
||||
```javascript
|
||||
|
||||
var s1 = Symbol.for("foo");
|
||||
var s1 = Symbol.for("foo");
|
||||
Symbol.keyFor(s1) // "foo"
|
||||
|
||||
var s2 = Symbol("foo");
|
||||
@ -741,8 +741,8 @@ var pipe = (function () {
|
||||
return new Proxy({}, {
|
||||
get: function (pipeObject, fnName) {
|
||||
if (fnName == "get") {
|
||||
return pipe.reduce(function (val, fn) {
|
||||
return fn(val);
|
||||
return pipe.reduce(function (val, fn) {
|
||||
return fn(val);
|
||||
}, value);
|
||||
}
|
||||
pipe.push(window[fnName]);
|
||||
@ -752,12 +752,12 @@ var pipe = (function () {
|
||||
}
|
||||
}());
|
||||
|
||||
var double = function (n) { return n*2 };
|
||||
var double = function (n) { return n*2 };
|
||||
var pow = function (n) { return n*n };
|
||||
var reverseInt = function (n) { return n.toString().split('').reverse().join('')|0 };
|
||||
|
||||
pipe(3) . double . pow . reverseInt . get
|
||||
// 63
|
||||
pipe(3) . double . pow . reverseInt . get
|
||||
// 63
|
||||
|
||||
```
|
||||
|
||||
@ -855,7 +855,7 @@ let {proxy, revoke} = Proxy.revocable(target, handler);
|
||||
|
||||
proxy.foo = 123;
|
||||
proxy.foo // 123
|
||||
|
||||
|
||||
revoke();
|
||||
proxy.foo // TypeError: Revoked
|
||||
|
||||
@ -870,9 +870,9 @@ Object.observe方法用来监听对象(以及数组)的变化。一旦监听
|
||||
```javascript
|
||||
|
||||
var user = {};
|
||||
Object.observe(user, function(changes){
|
||||
Object.observe(user, function(changes){
|
||||
changes.forEach(function(change) {
|
||||
user.fullName = user.firstName+" "+user.lastName;
|
||||
user.fullName = user.firstName+" "+user.lastName;
|
||||
});
|
||||
});
|
||||
|
||||
@ -890,9 +890,9 @@ user.fullName // 'Michael Jackson'
|
||||
|
||||
var div = $("#foo");
|
||||
|
||||
Object.observe(user, function(changes){
|
||||
Object.observe(user, function(changes){
|
||||
changes.forEach(function(change) {
|
||||
var fullName = user.firstName+" "+user.lastName;
|
||||
var fullName = user.firstName+" "+user.lastName;
|
||||
div.text(fullName);
|
||||
});
|
||||
});
|
||||
@ -908,12 +908,12 @@ Object.observe(user, function(changes){
|
||||
var o = {};
|
||||
|
||||
function observer(changes){
|
||||
changes.forEach(function(change) {
|
||||
console.log('发生变动的属性:' + change.name);
|
||||
console.log('变动前的值:' + change.oldValue);
|
||||
console.log('变动后的值:' + change.object[change.name]);
|
||||
console.log('变动类型:' + change.type);
|
||||
});
|
||||
changes.forEach(function(change) {
|
||||
console.log('发生变动的属性:' + change.name);
|
||||
console.log('变动前的值:' + change.oldValue);
|
||||
console.log('变动后的值:' + change.object[change.name]);
|
||||
console.log('变动类型:' + change.type);
|
||||
});
|
||||
}
|
||||
|
||||
Object.observe(o, observer);
|
||||
@ -925,9 +925,9 @@ Object.observe(o, observer);
|
||||
```javascript
|
||||
|
||||
var change = {
|
||||
object: {...},
|
||||
type: 'update',
|
||||
name: 'p2',
|
||||
object: {...},
|
||||
type: 'update',
|
||||
name: 'p2',
|
||||
oldValue: 'Property 2'
|
||||
}
|
||||
|
||||
|
105
docs/promise.md
105
docs/promise.md
@ -366,6 +366,20 @@ p.then(function (s){
|
||||
|
||||
上面代码生成一个新的Promise对象的实例p,它的状态为fulfilled,所以回调函数会立即执行,Promise.resolve方法的参数就是回调函数的参数。
|
||||
|
||||
所以,如果希望得到一个Promise对象,比较方便的方法就是直接调用Promise.resolve方法。
|
||||
|
||||
```javascript
|
||||
|
||||
var p = Promise.resolve();
|
||||
|
||||
p.then(function () {
|
||||
// ...
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
上面代码的变量p就是一个Promise对象。
|
||||
|
||||
如果Promise.resolve方法的参数是一个Promise对象的实例,则会被原封不动地返回。
|
||||
|
||||
Promise.reject(reason)方法也会返回一个新的Promise实例,该实例的状态为rejected。Promise.reject方法的参数reason,会被传递给实例的回调函数。
|
||||
@ -430,9 +444,7 @@ run(g);
|
||||
|
||||
### 概述
|
||||
|
||||
async函数与Promise、Generator函数一样,是用来取代回调函数、解决异步操作的另一种方法。它可以写出比Promise和Generator更简洁易读的代码,但是依赖这两者来实现。
|
||||
|
||||
async函数并不属于ES6,而是被列入了ES7,但是traceur编译器和regenerator转码器已经实现了这个功能。
|
||||
async函数与Promise、Generator函数一样,是用来取代回调函数、解决异步操作的另一种方法。它可以写出比Promise和Generator更简洁易读的代码,但是依赖这两者来实现。async函数并不属于ES6,而是被列入了ES7,但是traceur、Babel.js、regenerator等转码器已经支持这个功能,转码后立刻就能使用。
|
||||
|
||||
在用法上,只要函数名之前加上async关键字,就表明该函数内部有异步操作。该异步操作应该返回一个Promise对象,前面用await关键字注明。当函数执行的时候,一旦遇到await就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。
|
||||
|
||||
@ -453,6 +465,8 @@ getStockPrice("JNJ")
|
||||
|
||||
上面代码是一个获取股票报价的函数,函数前面的async关键字,表明该函数将返回一个Promise对象。调用该函数时,当遇到await关键字,立即返回它后面的表达式(getStockPrice函数)产生的Promise对象,不再执行函数体内后面的语句。等到getStockPrice完成,再自动回到函数体内,执行剩下的语句。
|
||||
|
||||
仔细观察getStockPrice函数,你会发现除了添加async、await这两个命令,整个代码与同步操作的流程一模一样。这就是async函数的本意,尽可能地用同步的流程,表达异步操作。
|
||||
|
||||
下面是一个更一般性的例子。
|
||||
|
||||
```javascript
|
||||
@ -472,6 +486,91 @@ async function asyncValue(value) {
|
||||
|
||||
上面代码中,asyncValue函数前面有async关键字,表明函数体内有异步操作。执行的时候,遇到await语句就会先返回,等到timeout函数执行完毕,再返回value。
|
||||
|
||||
总之,async函数的关键就是,await命令后面,必须是一个返回Promise对象的操作。因为Promise对象的运行结果可能是rejected,所以最好把await命令放在try...catch代码块中。
|
||||
|
||||
```javascript
|
||||
|
||||
async function myFunction() {
|
||||
try {
|
||||
await somethingThatReturnsAPromise();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
await命令只能用在async函数之中,如果用在普通函数,就会报错。
|
||||
|
||||
```javascript
|
||||
|
||||
async function dbFuc(db) {
|
||||
let docs = [{}, {}, {}];
|
||||
|
||||
// 报错
|
||||
docs.forEach(function (doc) {
|
||||
await db.post(doc);
|
||||
});
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
上面代码会报错,因为await用在普通函数之中了。但是,如果将forEach方法的参数改成async函数,也有问题。
|
||||
|
||||
```javascript
|
||||
|
||||
async function dbFuc(db) {
|
||||
let docs = [{}, {}, {}];
|
||||
|
||||
// 可能得到错误结果
|
||||
docs.forEach(async function (doc) {
|
||||
await db.post(doc);
|
||||
});
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
上面代码可能不会正常工作,原因是这时三个db.post操作将是并发执行,也就是同时执行,而不是继发执行。正确的写法是采用for循环。
|
||||
|
||||
```javascript
|
||||
|
||||
async function dbFuc(db) {
|
||||
let docs = [{}, {}, {}];
|
||||
|
||||
for (let doc of docs) {
|
||||
await db.post(doc);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
如果确实希望多个请求并发执行,可以使用Promise.all方法。
|
||||
|
||||
```javascript
|
||||
|
||||
async function dbFuc(db) {
|
||||
let docs = [{}, {}, {}];
|
||||
let promises = docs.map((doc) => db.post(doc));
|
||||
|
||||
let results = await Promise.all(promises);
|
||||
console.log(results);
|
||||
}
|
||||
|
||||
// 或者使用下面的写法
|
||||
|
||||
async function dbFuc(db) {
|
||||
let docs = [{}, {}, {}];
|
||||
let promises = docs.map((doc) => db.post(doc));
|
||||
|
||||
let results = [];
|
||||
for (let promise of promises) {
|
||||
results.push(await promise);
|
||||
}
|
||||
console.log(results);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
ES6将await增加为保留字。使用这个词作为标识符,在ES5是合法的,在ES6将抛出SyntaxError。
|
||||
|
||||
### 与Promise、Generator的比较
|
||||
|
@ -87,6 +87,7 @@
|
||||
- Jack Franklin, [Embracing Promises in JavaScript](http://javascriptplayground.com/blog/2015/02/promises/): catch方法的例子
|
||||
- Luke Hoban, [Async Functions for ECMAScript](https://github.com/lukehoban/ecmascript-asyncawait): Async函数的设计思想,与Promise、Gernerator函数的关系
|
||||
- Jafar Husain, [Asynchronous Generators for ES7](https://github.com/jhusain/asyncgenerator): Async函数的深入讨论
|
||||
- Nolan Lawson, [Taming the asynchronous beast with ES7](http://pouchdb.com/2015/03/05/taming-the-async-beast-with-es7.html): async函数通俗的实例讲解
|
||||
|
||||
## Class与模块
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user