es6总结下
ES6总结上
文章目录
- es6总结下
- 七、for of 值遍历与Symbol原始数据类型
- 八、Map 与 Set
- 九、Promise
- 十、async await函数
- 十一、module语法
七、for of 值遍历与Symbol原始数据类型
for of 值遍历
我们都知道for in 循环用于遍历数组,类数组或对象,ES6中新引入的for of循环功能相似,不同的是每次循环它提供的不是序号而是值。
var someArray = [ "a", "b", "c" ];
for (v of someArray) {
console.log(v);//输出 a,b,c
}
Symbol原始数据类型
引入了一种新的原始数据类型 Symbol ,表示独一无二的值,最大的用法是用来定义对象的唯一属性名。
let sy = Symbol("name1");
console.log(sy); // Symbol(name1)
typeof(sy); // "symbol"
八、Map 与 Set
Set 类似与数组的一种数据结构
Set 对象存储的值总是唯一的,所以需要判断两个值是否恒等。有几个特殊值需要特殊对待:
- +0 与 -0 在存储判断唯一性的时候是恒等的,所以不重复;
undefined 与 undefined 是恒等的,所以不重复;
NaN 与 NaN 是不恒等的,但是在 Set 中只能存一个,不重复。
两个对象总是不相等的
set方法:
add() 添加
delete() 删除
clear() 清除所有
has() 查找有无
size() 返回实例的成员总数
keys() 遍历属性名
values() 遍历属性值
entries() 遍历属性名和属性值的键值对
实例:
//Set本身是一个构造函数,用来生成 Set 数据结构。
const s =newSet();
[2,3,5,4,5,2,2].forEach(x => s.add(x));
for(let i of s){
console.log(i);
}// 2 3 5 4
// 去除数组的重复成员
[...newSet(array)]
//去除字符串里面的重复字符
[...newSet('ababbc')].join('')
// "abc"
//Array.from方法可以将 Set 结构转为数组。
const items =newSet([1,2,3,4,5]);
const array =Array.from(items);
向 Set 加入值的时候,不会发生类型转换,所以5和"5"是两个不同的值。Set 内部判断两个值是否不同,使用的算法叫做“Same-value-zero equality”,它类似于精确相等运算符(===),主要的区别是向 Set 加入值时认为NaN等于自身,而精确相等运算符认为NaN不等于自身。
Map 数据结构。
它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应
Map方法:
set(“属性名”,“属性值”) 存值
get(“属性名”)取值
has(“属性名”)
delete(“属性名”)
clear()
size()
keys()遍历属性名
values()遍历属性值
entries()遍历属性名和属性值的
//实例
const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content')
m.get(o) // "content"
//观察下面案例:
const map = new Map();
map.set(['a'], 555);
map.get(['a']) // undefined
//上面代码的set和get方法,表面是针对同一个键,但实际上这是两个不同的数组实例,内存地址是不一样的,因此get方法无法读取该键,返回undefined。
//下面代码中,变量k1和k2的值是一样的,但是它们在 Map 结构中被视为两个键。
const map = new Map();
const k1 = ['a'];
const k2 = ['a'];
map
.set(k1, 111)
.set(k2, 222);
map.get(k1) // 111
map.get(k2) // 222
//由上可知,Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键。这就解决了同名属性碰撞(clash)的问题,我们扩展别人的库的时候,如果使用对象作为键名,就不用担心自己的属性与原作者的属性同名。
九、Promise
Promise 的含义:
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大
Promise对象是一个构造函数,用来生成Promise实例。下面代码创造了一个Promise实例。
function timeout(ms){
return new Promise((resolve, reject)=>{
setTimeout(resolve, ms,'done');
});
//Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。
}
timeout(100).then((value)=>{
console.log(value);
});
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
resolve函数的作用是:
将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
then方法
返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。
getJSON("/posts.json").then(function(json) {
return json.post;
}).then(function(post) {
// ...
});
catch()方法
是用于指定发生错误时的回调函数。如果异步操作抛出错误,状态就会变为rejected,就会调用catch()方法指定的回调函数,处理这个错误。另外,then()方法指定的回调函数,如果运行中抛出错误,也会被catch()方法捕获。
getJSON('/posts.json').then(function(posts) {
// ...
}).catch(function(error) {
// 处理 getJSON 和 前一个回调函数运行时发生的错误
console.log('发生错误!', error);
});
finally()方法
用于指定不管 Promise 对象最后状态如何,都会执行的操作。
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
十、async await函数
async 是“异步”的简写,而 await 可以认为是 async wait 的简写。所以应该很好理 解 async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。
function timeout(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function asyncPrint(value, ms) {
await timeout(ms);
console.log(value);
}
asyncPrint('hello world', 50);
//上面代码指定 50 毫秒以后,输出hello world
async函数会返回一个promise对象,如果在函数中return一个值,那么该值会通过 Promise.resolve()传递出去
可以成为then方法回调函数的参数。
async函数如果内部抛出错误,会导致返回的 Promise 对象变为reject状态。抛出的错误对象会被catch方法回调函数接收到。
async function f() {
return 'hello world';
}
f().then(v => console.log(v))
// "hello world"
await 命令
正常情况下,await命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值。
async function f() {
// 等同于
// return 123;
return await 123;
}
f().then(v => console.log(v))
// 123
如果它等到的是一个 Promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。
//借助await命令就可以让程序停顿指定的时间
function sleep(interval) {
return new Promise(resolve => {
setTimeout(resolve, interval);
})
}
// 用法
async function one2FiveInAsync() {
for(let i = 1; i <= 5; i++) {
console.log(i);
await sleep(1000);
}
}
one2FiveInAsync();
错误处理
await命令后面的 Promise 对象如果变为reject状态,则reject的参数会被catch方法的回调函数接收到。
async function f() {
await Promise.reject('出错了');
}
f()
.then(v => console.log(v))
.catch(e => console.log(e))
// 出错了
任何一个await语句后面的 Promise 对象变为reject状态,那么整个async函数都会中断执行。有时,我们希望即使前一个异步操作失败,也不要中断后面的异步操作。这时可以将第一个await放在try…catch结构里面,这样不管这个异步操作是否成功,第二个await都会执行。
如果await后面的异步操作出错,那么等同于async函数返回的 Promise 对象被reject。防止出错的方法,也是将其放在try…catch代码块之中。
十一、module语法
ES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict";尤其需要注意this的限制。ES6 模块之中,顶层的this指向undefined,即不应该在顶层代码使用this。
import和export命令:
export var a=1 可以导出任何的变量声明语句或者函数声明语句 ,一定是完整的变量声明语句
import {a} from “./a.js”
改名字:
导出 export {原名 as 新名}
引入 import {导出的名字 as 新名}
// 写法一
export var m = 1;
// 写法二
var m = 1;
export {m};
// 写法三
var n = 1;
export {n as m};
//export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。上面代码输出变量foo,值为bar,500 毫秒之后变成baz。
export var foo = 'bar';
setTimeout(() => foo = 'baz', 500);
// 报错
if (x === 2) {
import MyModual from './myModual';
}
//import和export命令只能在模块的顶层,不能在代码块之中(比如,在if代码块之中,或在函数之中)
//所以引入import()函数,支持动态加载模块。
import()函数可以用在任何地方,不仅仅是模块,非模块的脚本也可以使用。它是运行时执行,也就是说,什么时候运行到这一句,就会加载指定的模块。另外,import()函数与所加载的模块没有静态连接关系,这点也是与import语句不相同。
注意点:import()加载模块成功以后,这个模块会作为一个对象,当作then方法的参数
import()也可以用在 async 函数之中:
async function main() {
const myModule = await import('./myModule.js');
const {export1, export2} = await import('./myModule.js');
const [module1, module2, module3] =
await Promise.all([
import('./module1.js'),
import('./module2.js'),
import('./module3.js'),
]);
}
main();
export default 命令(默认导出)
在一个文件或模块中,export、import 可以有多个,export default 仅有一个。
在浏览器中使用ES6模块
浏览器加载 ES6 模块,也使用
<script type="module" src="./foo.js"></script>
//浏览器对于带有type="module"的<script>,都是异步加载,不会造成堵塞浏览器,即等到整个页面渲染完,再执行模块脚本,等同于打开了<script>标签的defer属性。
<!-- 等同于 -->
<script type="module" src="./foo.js" defer></script>