es6语法最全深入浅出(四)

简介: es6语法最全深入浅出
yidld*语句

如果yield命令后面跟的是一个遍历器,需要在yield命令后面加上星号,表明它返回的是个遍历器。这被称为yield*语句。

在下面代码中,delegatinglterator是代理者,delegatedlterator是被代理者。由于yield* delegatedlterator语句得到的值,是一个遍历器,所以要用星号表示运行结果就是使用一个遍历器,遍历了多个Genertor函数,有递归的效果

let delegatedIterator = (function*() {
  yidld 'Hello!';
  yield 'Bye!';
}());
let delegatingIterator = (function*() {
  yield 'Greetings!';
  yield* delegatedIterator;
  yield 'Ok,bye';
}());
for(let value of delegatingIterator) {
  console.log(value);
}
//"Greetings!"
//"Hello!"
//"Bye!"
//"Ok,bye."

预处理

es6原生提供了Promise对象。所谓Promise对象,就是代表了未来某个将要发生的事件 (通常是一个异步操作)。它的好处在于,有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象还提供了一整套完整的接口,使得可以更加容易地控制异步操作

基本用法

es6的Promise对象是一个构造函数,用来生成Promise实例。下面是Promise对象的基本用法。

下面代码表示,Promise构造函数接收一个函数作为参数,该函数的两个参数分别是resolve()方法和reject()方法。如果异步操作成功,则用resolve()方法将Promise对象的状态变为“成功”(即从pending变为resolved) ; 如果异步操作失败,则用reject()万法将状态变为“失败”(即从pending变为rejected)

var promise = new Promise(function(resolve,reject) {
  if(/* 异步操作成功 */) {
    resolve(value);
  } else {
    reject(error);
  }
});
promese.then(function(value) {  //成功
},function(value) {     //失败
});
then方法

Promise.prototype.then方法返回的是一个新的Promise对象,因此可以采用链式写法。

getJSON("/posts.json").then(function(json)
  return json.post;
}).then(function(post) {
  //执行后续处理
});

上面的代码使用then()方法,依次指定了两个回调函数。第一个回调函数完成以后,会将返回结果作为参数,传入第二个回调函数

如果前一个回调函数返回的是Promise对象,这时后一个回调函数就会等待该Promise对象有了运行结果,才会进一步调用。

getJSON("/post/1.json").then(function(post)
  return getJSON(post.commentURL);
}).then(function(comments) {
  //对 comments 进行处理
});

这种设计使得嵌套的异步操作,可以被很容易地改写,从回调函数的“横向发展”改为“向下发展”。

catch()方法

Promise.prototype.catch()方法是Promise.prototype.then(null,rejection)的别名,用于指定发生错误时的回调函数。

getJSON("/posts.json").then(function(posts) {
  //JavaScript 代码
}).catch(function(error) {
  //处理前一个回调函数运行时发生的错误
  console.log("发生错误!",error)
})

Promise对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。

getJSON("/post/1.json").then(function(post) {
  return getJSON(post.commentURL);
}).then(function(comments) {
  //JavaScript代码
}).catch(function(error) {
  //处理前两个回调函数的错误
});
all和race()方法

Promise.all()万法用于将多个Promise实例,包装成一个新的Promise实例.

var p = Promise.all([p1,p2,p3]);

上面代码中,Promise.all()方法接收一个数组作为参数,p1、p2、p3都是Promise对象的实例。 (Promise.all()万法的参数不一定是数组,但是必须具有iterator接口,且返回的每个成员都是Promise实例。)

p的状态由p1、p2、p3决定,分成两种情况。

只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2p3的返回值组成一个数组,传递给p的回调函数

只要p1、p2、p3中有一个被reiected,p的状态就变成rejected,此时第一个被reiect的实例的返回值,会传递给p的回调函数

下面是一个具体的例子

//生成一个Promise对象的数组
var promises = [2,3,5,7,11,14].map(function(id){
  return getJSON("/post/" + id + "json");
});
Promise.all(promises).then(function(posts) {
  //...
}).catch(function(reason){
`//...
});

Promise.race()方法同样是将多个Promise实例,包装成一个新的Promise实例

var p=Promise.race([p1,p2,p3]);

上面代码中,只要p1、p2、p3中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给p的返回值。

如果Promise.all0方法和Promise.race()方法的参数,不是Promise实例,就会先调用下面讲到的Promise.resolve()方法,将参数转为Promise实例,再进一步处理

resolve(和reject()方法

有时需要将现有对象转为Promise对象,Promise.resolve()方法就起到这个作用

var jsPromise=Promise.resolve($.ajax("/whatever.json"));

上面代码将jQuery生成deferred对象,转为一个新的es6的Promise对象

如果Promise.resolve()方法的参数,不是具有then()方法的对象 (又称thenable对象),则返回一个新的Promise对象,且它的状态为fulfilled。

var p = Promise.resolve('Hello');
p.then(function(s) {
  console.log(s)
})
//Hello

上面代码生成一个新的Promise对象的实例p,它的状态为fulfilled,所以回调函数会立即执行,Promise.resolve()方法的参数就是回调函数的参数

如果Promise.resolve()方法的参数是一个Promise对象的实例,则会被原封不动地返回.

Promise.reject(reason)方法也会返回一个新的Promise实例,该实例的状态为rejected。Promise. reject()方法的参数reason,会被传递给实例的回调函数

var p = Promise.reject('出错了');
p.then(null,function(s){
  console.log(s)
})

上面代码生成一个Promise对象的实例p,状态为reiected,回调函数会立即执行

async函数

async函数是用来取代回调函数的另一种方法。只要函数名之前加上async关键字,就表明该函数内部有异步操作。该异步操作应该返回一个Promise对象,前面用await关键字注明。当函数执行时,一旦遇到await就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。

下面代码是一个获取股票报价的函数,函数前面的async关键字,表明该函数将返回一个Promise对象。调用该函数时,当遇到await关键字,立即返回它后面的表达式(getStockPrice()函数) 产生的Promise对象,不再执行函数体内后面的语句。等到getStockPrice完成,再自动回到函数体内,执行剩下的语句.

async function getStockPrice(symbol,currency) {
  let price = await getStockPrice(symbol);
  return convert(price,currency);
}

async函数并不属于ECMAScript 6,而是被列入了ES7,但是traceur编译器已经实现了这个功能。

类和模块

类和模块都是代码封装的基本方法,它们的主要差异在于:类可以实例化为对象,而标准模块则不能。由于标准模块的数据只有一个副本,因此当程序的一部分更改标准模块中的公共变量时,如果程序的其他任何部分随后读取该变量,都会获取同样的值。与之相反,每个实例化对象的对象数据则单独存在。另一个不同在于: 不像标准模块,类可以实现接口。

es5通过构造函数,定义类。ECMAScript 6开始引入Class (类) 概念。通过class关键字,可以定义类

本示例定义了一个类,类中包含一个constructor构造函数,而this关键字表示实例对象。除了构造方法,还可以自定义方法。定义方法时,前面不需要加上function保留字。

class Point {
  constructor(x,y) {
    this.x = x;
    this.y = y;
  }
  toString() {
    return '('+this.x+','+this.y+')';
  }
}
var point = new Point(2,3);
point.toString()    //(2,3)

模块

es6支持模块功能,解决JavaScript代码的依赖和部署问题,取代现有的CommonJS和AMD规范,成为浏览器和服务器通用的横块解决方案

基本用法

模块功能有两个关键字: export和import。export用于用户自定义模块,规定对外接口;import用于输入其他模块提供的功能,同时创造命名空间 (namespace) ,防止函数名冲突。

es6允许将独立的JavaScript文件作为模块,也就是说,允许一个JavaScript脚本文件调用另一个脚本文件。该文件内部的所有变量,外部无法获取,必须使用export关键字输出变量。

下面是一个JavaScript文件,里面使用export关键字输出变量

//profile.js
export var frstName='David';
export var lastName='Belle';
export var year=1973;

上面是profile.js文件,ECMAScript 6将其视为一个模块,里面用export关键字输出了3个变量。

模块的整体加载

export关键字除了输出变量,还可以输出方法或类 (class)

本示例是一个circle.is文件,它输出两人方法

//circle.js
export function area(radius) {
  return Math.PI * radius * radius;
}
export function circumference(radius) {
  return 2 * Match.PI * radius;
}

然后,可以在main.js文件中引用这个模块

//main.js
import {area,circumference} from 'circle';
console.log("圆面积:" + area(4));
console.log("原周长:"+ circumference(14));
export default语句

如果不想为某个属性或方法指定输入的名称,可以使用export default语句

//export-defult.js
export default function foo() {
   console.log('foo');
}

在上面代码中,foo()方法被称为该模块的默认方法

在其他模块导入该模块时,import语句可以为默认方法指定任意名字

//import-default.js
import customName form './export-default'
customName(); // 'foo'

注意:一个模块只能有一个默认方法。

如果想在一条import语句中,同时输入默认方法和指定名称的变量,可以写成下面这样。

import customName, { otherMethod } from './export-default';

如果要输出默认属性,只需将值跟在export default之后即可

export default 42;

提示: export default也可以用来输出类

//MyClass.is
export default class {...}
import MyClass from 'MyClass'
//main.is
模块继承

模块之间也可以继承.

下面示例设计一个circleplus模块,继承了circle模块。

//circlcplus.js
export * from 'circle':
export var e =2.71828182846:
export default function(x) {
  return Math.exp(x);
}

在上面代码中,“export *”表示输出circle模块的所有属性和方法,export default命令定义模块的默认方法。

这时可以为circle中的属性或方法,改名后再输出。

export [ area as circleArea ] from 'circle'

加载上面模块的写法如下:

//main.is
module math from "circleplus";;
import exp from "circleplus";
console.log(exp(math.pi));

上面代码中的“import exp”表示将circleplus模块的默认方法加载为exp方法

讲解结束感谢观看

参考自《JavaScript网页编程从入门到精通》

相关文章
|
JavaScript 前端开发 Java
|
存储 JavaScript 前端开发
|
Web App开发 JavaScript 前端开发
|
JavaScript
ES6的基础用法
对js es6的用法进行简单介绍
|
前端开发
es6 语法简单使用2
es6 语法简单使用
64 0
|
网络架构
es6 语法简单使用1
es6 语法简单使用
74 0
|
JavaScript 前端开发
|
JavaScript 前端开发 网络架构
每天3分钟,重学ES6-ES12(四)函数的补充 展开语法
每天3分钟,重学ES6-ES12(四)函数的补充 展开语法
84 0
|
Web App开发 前端开发 JavaScript
ES9语法知识点回顾
ES9语法知识点回顾
264 31