1
0
mirror of https://github.com/ruanyf/es6tutorial.git synced 2025-05-24 18:32:22 +00:00

整理格式

This commit is contained in:
Ruan Yifeng 2015-03-16 09:25:42 +08:00
parent 60b767cae5
commit 46395127c2
4 changed files with 135 additions and 35 deletions

View File

@ -25,7 +25,7 @@ for循环的计数器就很合适使用let命令。
```javascript ```javascript
for(let i = 0; i < arr.length; i++){} for(let i = 0; i < arr.length; i++){}
console.log(i) console.log(i)
//ReferenceError: i is not defined //ReferenceError: i is not defined
@ -80,9 +80,9 @@ function do_something() {
```javascript ```javascript
if (1) { if (1) {
typeof x; // ReferenceError typeof x; // ReferenceError
let x; let x;
} }
``` ```
@ -93,16 +93,16 @@ if (1) {
```javascript ```javascript
var tmp = 123; var tmp = 123;
if (true) { if (true) {
tmp = 'abc'; // ReferenceError tmp = 'abc'; // ReferenceError
let tmp; let tmp;
} }
``` ```
上面代码中存在全局变量tmp但是块级作用域内let又声明了一个局部变量tmp导致后者绑定这个块级作用域所以在let声明变量前对tmp赋值会报错。 上面代码中存在全局变量tmp但是块级作用域内let又声明了一个局部变量tmp导致后者绑定这个块级作用域所以在let声明变量前对tmp赋值会报错。
ES6明确规定如果区块中存在let和const命令这个区块对这些命令声明的变量从一开始就形成了封闭作用域。凡是在声明之前就使用这些命令就会报错。 ES6明确规定如果区块中存在let和const命令这个区块对这些命令声明的变量从一开始就形成了封闭作用域。凡是在声明之前就使用这些命令就会报错。
@ -114,10 +114,10 @@ if (true) {
// TDZ开始 // TDZ开始
tmp = 'abc'; // ReferenceError tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError console.log(tmp); // ReferenceError
let tmp; // TDZ结束 let tmp; // TDZ结束
console.log(tmp); // undefined console.log(tmp); // undefined
tmp = 123; tmp = 123;
console.log(tmp); // 123 console.log(tmp); // 123
} }

View File

@ -276,14 +276,14 @@ function clone(origin) {
将多个对象合并到某个对象。 将多个对象合并到某个对象。
```javascript ```javascript
const merge = const merge =
(target, ...sources) => Object.assign(target, ...sources); (target, ...sources) => Object.assign(target, ...sources);
``` ```
如果希望合并后返回一个新对象,可以改写上面函数,对一个空对象合并。 如果希望合并后返回一个新对象,可以改写上面函数,对一个空对象合并。
```javascript ```javascript
const merge = const merge =
(...sources) => Object.assign({}, ...sources); (...sources) => Object.assign({}, ...sources);
``` ```
@ -516,7 +516,7 @@ Symbol.for方法在全局环境中搜索指定key的Symbol值如果存在就
```javascript ```javascript
Symbol.for("bar") === Symbol.for("bar") Symbol.for("bar") === Symbol.for("bar")
// true // true
Symbol("bar") === Symbol("bar") Symbol("bar") === Symbol("bar")
@ -530,7 +530,7 @@ Symbol.keyFor方法返回一个已登记的Symbol类型值的key。
```javascript ```javascript
var s1 = Symbol.for("foo"); var s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo" Symbol.keyFor(s1) // "foo"
var s2 = Symbol("foo"); var s2 = Symbol("foo");
@ -741,8 +741,8 @@ var pipe = (function () {
return new Proxy({}, { return new Proxy({}, {
get: function (pipeObject, fnName) { get: function (pipeObject, fnName) {
if (fnName == "get") { if (fnName == "get") {
return pipe.reduce(function (val, fn) { return pipe.reduce(function (val, fn) {
return fn(val); return fn(val);
}, value); }, value);
} }
pipe.push(window[fnName]); 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 pow = function (n) { return n*n };
var reverseInt = function (n) { return n.toString().split('').reverse().join('')|0 }; var reverseInt = function (n) { return n.toString().split('').reverse().join('')|0 };
pipe(3) . double . pow . reverseInt . get pipe(3) . double . pow . reverseInt . get
// 63 // 63
``` ```
@ -855,7 +855,7 @@ let {proxy, revoke} = Proxy.revocable(target, handler);
proxy.foo = 123; proxy.foo = 123;
proxy.foo // 123 proxy.foo // 123
revoke(); revoke();
proxy.foo // TypeError: Revoked proxy.foo // TypeError: Revoked
@ -870,9 +870,9 @@ Object.observe方法用来监听对象以及数组的变化。一旦监听
```javascript ```javascript
var user = {}; var user = {};
Object.observe(user, function(changes){ Object.observe(user, function(changes){
changes.forEach(function(change) { 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"); var div = $("#foo");
Object.observe(user, function(changes){ Object.observe(user, function(changes){
changes.forEach(function(change) { changes.forEach(function(change) {
var fullName = user.firstName+" "+user.lastName; var fullName = user.firstName+" "+user.lastName;
div.text(fullName); div.text(fullName);
}); });
}); });
@ -908,12 +908,12 @@ Object.observe(user, function(changes){
var o = {}; var o = {};
function observer(changes){ function observer(changes){
changes.forEach(function(change) { changes.forEach(function(change) {
console.log('发生变动的属性:' + change.name); console.log('发生变动的属性:' + change.name);
console.log('变动前的值:' + change.oldValue); console.log('变动前的值:' + change.oldValue);
console.log('变动后的值:' + change.object[change.name]); console.log('变动后的值:' + change.object[change.name]);
console.log('变动类型:' + change.type); console.log('变动类型:' + change.type);
}); });
} }
Object.observe(o, observer); Object.observe(o, observer);
@ -925,9 +925,9 @@ Object.observe(o, observer);
```javascript ```javascript
var change = { var change = {
object: {...}, object: {...},
type: 'update', type: 'update',
name: 'p2', name: 'p2',
oldValue: 'Property 2' oldValue: 'Property 2'
} }

View File

@ -366,6 +366,20 @@ p.then(function (s){
上面代码生成一个新的Promise对象的实例p它的状态为fulfilled所以回调函数会立即执行Promise.resolve方法的参数就是回调函数的参数。 上面代码生成一个新的Promise对象的实例p它的状态为fulfilled所以回调函数会立即执行Promise.resolve方法的参数就是回调函数的参数。
所以如果希望得到一个Promise对象比较方便的方法就是直接调用Promise.resolve方法。
```javascript
var p = Promise.resolve();
p.then(function () {
// ...
});
```
上面代码的变量p就是一个Promise对象。
如果Promise.resolve方法的参数是一个Promise对象的实例则会被原封不动地返回。 如果Promise.resolve方法的参数是一个Promise对象的实例则会被原封不动地返回。
Promise.reject(reason)方法也会返回一个新的Promise实例该实例的状态为rejected。Promise.reject方法的参数reason会被传递给实例的回调函数。 Promise.reject(reason)方法也会返回一个新的Promise实例该实例的状态为rejected。Promise.reject方法的参数reason会被传递给实例的回调函数。
@ -430,9 +444,7 @@ run(g);
### 概述 ### 概述
async函数与Promise、Generator函数一样是用来取代回调函数、解决异步操作的另一种方法。它可以写出比Promise和Generator更简洁易读的代码但是依赖这两者来实现。 async函数与Promise、Generator函数一样是用来取代回调函数、解决异步操作的另一种方法。它可以写出比Promise和Generator更简洁易读的代码但是依赖这两者来实现。async函数并不属于ES6而是被列入了ES7但是traceur、Babel.js、regenerator等转码器已经支持这个功能转码后立刻就能使用。
async函数并不属于ES6而是被列入了ES7但是traceur编译器和regenerator转码器已经实现了这个功能。
在用法上只要函数名之前加上async关键字就表明该函数内部有异步操作。该异步操作应该返回一个Promise对象前面用await关键字注明。当函数执行的时候一旦遇到await就会先返回等到触发的异步操作完成再接着执行函数体内后面的语句。 在用法上只要函数名之前加上async关键字就表明该函数内部有异步操作。该异步操作应该返回一个Promise对象前面用await关键字注明。当函数执行的时候一旦遇到await就会先返回等到触发的异步操作完成再接着执行函数体内后面的语句。
@ -453,6 +465,8 @@ getStockPrice("JNJ")
上面代码是一个获取股票报价的函数函数前面的async关键字表明该函数将返回一个Promise对象。调用该函数时当遇到await关键字立即返回它后面的表达式getStockPrice函数产生的Promise对象不再执行函数体内后面的语句。等到getStockPrice完成再自动回到函数体内执行剩下的语句。 上面代码是一个获取股票报价的函数函数前面的async关键字表明该函数将返回一个Promise对象。调用该函数时当遇到await关键字立即返回它后面的表达式getStockPrice函数产生的Promise对象不再执行函数体内后面的语句。等到getStockPrice完成再自动回到函数体内执行剩下的语句。
仔细观察getStockPrice函数你会发现除了添加async、await这两个命令整个代码与同步操作的流程一模一样。这就是async函数的本意尽可能地用同步的流程表达异步操作。
下面是一个更一般性的例子。 下面是一个更一般性的例子。
```javascript ```javascript
@ -472,6 +486,91 @@ async function asyncValue(value) {
上面代码中asyncValue函数前面有async关键字表明函数体内有异步操作。执行的时候遇到await语句就会先返回等到timeout函数执行完毕再返回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。 ES6将await增加为保留字。使用这个词作为标识符在ES5是合法的在ES6将抛出SyntaxError。
### 与Promise、Generator的比较 ### 与Promise、Generator的比较

View File

@ -87,6 +87,7 @@
- Jack Franklin, [Embracing Promises in JavaScript](http://javascriptplayground.com/blog/2015/02/promises/): catch方法的例子 - 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函数的关系 - 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函数的深入讨论 - 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与模块 ## Class与模块