一、Symbol
Symbol是es6中添加的一种原始数据类型(已有的数据原始类型:String、Number、Boolean、null、undefined、class),Symbol的出现是为了解决es5里面的对象属性名重名的问题
Symbol的 一些特点:
1、Symbol属性值是唯一的,解决了命名冲突问题
2、Symbol值不能与其他的数据进行计算,包括同字符串拼串
3、在for in里面遍历不到Symbol值
调用Symbol函数:
let symbol = Symbol(); // 定义一个symbol,注意这里没有new关键字,因为Symbol()是一个普通函数,而不是一个构造函数
const obj = {
name: '李老板',
age: 20
};
obj[symbol] = 'hello'; // 给obj对象添加一个属性值
console.log(obj);
结果:
Symbol()的传参标识:
let symbol1 = Symbol(); // 定义symbol1、symbol2
let symbol2 = Symbol();
console.log(symbol1 === symbol2); // false
console.log(symbol1, symbol2); // 看上去相同,实则不同
let symbol3 = Symbol('one'); // 可以给Symbol()一个参数来区分不同Symbol
let symbol4 = Symbol('two');
console.log(symbol3, symbol4); // 看上去不同,实则也不同
结果:
内置Symbol值:
除了定义自己使用的Symbol值外,es6还提供了11个内置的Symbol值,指向语言内部的方法
具体参考MDN官网
这里只说一个:
Symbol.iterator
对象的Symbol.iterator属性,指向该对象的默认遍历器方法
而 普通对象 没有,所以只要给普通对象 设置Symbol.iterator属性,就可以遍历普通对象
for in的验证
let symbol = Symbol();
const obj = {
name: '李老板',
age: 20
};
obj[symbol] = 'hello';
console.log(obj);
for(let i in obj) {
console.log(i); // 没有遍历到Symbol属性
}
结果:
二、iterator
iterator的概念:
iterator是一种接口机制,为各种不同的数据结构提供统一的访问机制
iterator的作用是:
提供一个统一的方法(api)来获取不同数据结构的数据,使用for of遍历方法的数据 必须要有iterater接口,也就是说 原生具备iterator接口的数据才可以用for of遍历
iterator工作原理:
返回一个 指针对象(遍历器对象),指向数据结构的起始位置,第一次调用next方法指针会自动指向数据结构的第一个成员,接下来不断调用next方法,指针会一直后移,直到最后一个成员,而且在 每次调用next方法后 会返回一个包含value与done的对象,如{value: 当前成员的值, done: 布尔值},这里面的done是表示当前的数据结构是否遍历结束,当遍历结束的时候value=undefinde,done=true
iterator的简单封装:
const arr = [1, 2, 56, 'll'];
function iterator(arr) {
let currentIndex = 0; // 指针
return { // 返回一个对象
next() { // 对象里面的next方法
return currentIndex < arr.length ? // next方法里面返回一个带有value与done的对象
{ value: arr[currentIndex++], done: false} :
{ value: undefined, done: true}
}
}
}
let obj = iterator(arr); // 获得iterator
console.log(obj.next()); // 调用next方法,结果为{value: 1, done: false}
console.log(obj.next()); // 结果为{value: 2, done: false}
console.log(obj.next()); // 结果为{value: 56, done: false}
console.log(obj.next()); // 结果为{value: "ll", done: false}
console.log(obj.next()); // 结果为{value: undefined, done: true}
console.log(obj.next()); // 结果为{value: undefined, done: true}
三、generator
概念:
是es6提供的解决异步编程的方案之一,generator是一个状态机,内部封装了不同状态的数据,它可用来生成遍历器对象,也可以使用yield来暂停,next来启动,且调用next每次返回的是一个带有yield后表达式的对象,如 {value: “毛毛”, done: false}
特点:
1、function与函数名之间有一个星号
2、内部使用yield表达式来定义不同状态
3、generator函数返回的是指针对象(iterator),而不会执行函数内部逻辑
4、刚开始调用next方法时,函数内部的逻辑开始执行,遇到yield表达式停止,返回{value:yield后的表达式结果,done:false}
5、再次调用next方法会从上一次停止时的yield处开始,直到最后返回{value:return里面的值|undefined,done:true}
6、yield语句返回的结果通常为undefined, 但当调用next方法时传参内容会作为yield语句的返回值
function* generator() { // 定义生成器
console.log(11);
let v1 = yield '李老板'; // yield来停止,并用v1来接收next传递的参数
console.log(v1); // 输出 熊大
console.log(22);
let v2= yield '涂涂'; // yield来停止,并用v2来接收next传递的参数
console.log(v2); // 输出 undefined
console.log(33);
yield '毛毛';
console.log(44);
}
let g = generator(); // 调用函数来得到迭代器对象
console.log(g.next()); // 调用迭代器的next方法,输出{value: "李老板", done: false}
console.log(g.next('熊大')); // 调用迭代器的next方法,并传递参数,输出{value: "涂涂", done: false}
console.log(g.next()); // 输出{value: "毛毛", done: false}
console.log(g.next()); // 输出{value: undefined, done: true}
结果:
四、async与await
async与await就是generator的语法糖, async 取代 *号 await 取代 yield;可以在真正意义上解决异步回调问题,同步流程表达异步操作,且await返回的值总是Promise对象里面的resolve与reject传入的值
要注意的是在async函数本身是异步的,而函数里面所有的操作是同步进行的,且函数里面的某一具体操作可能为回调函数(异步的)
例如:
async function foo() {
await 异步操作;
await 异步操作;
}
const foo = function() { // 定义一个回调(异步)函数
return new Promise((resolve, reject) => {
setTimeout(() => { // 这里的setTime必须包装成异步函数
console.log(111);
resolve(222); // 成功
}, 2000)
})
};
const bar = function() { // 定义一个回调(异步)函数
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(333);
resolve(444); // 成功
}, 1000)
})
};
const fn = function() { // 定义一个回调(异步)函数
return new Promise((resolve, reject) => {
reject('failed') // 失败
})
};
async function demo() { // async函数
try { // 捕获错误
console.log('a');
let fooDemo = await foo(); // await返回的值为resolve或者reject传入的值
console.log(fooDemo);
let barDemo = await bar(); // await返回的值为resolve或者reject传入的值
console.log(barDemo);
let fnDemo = await fn(); // await返回的值为resolve或者reject传入的值
console.log(fnDemo);
console.log('b'); // 因为有错误所以没有打印 b
}
catch (e) {
console.log(e);
}
}
demo();
结果:
五、async和await与promise的区别
使用了Promise:
const foo = function() { // 定义回调(异步)函数
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(111);
resolve(222);
}, 2000)
})
};
function demo1() {
console.log('a');
let fooDemo = foo();
console.log(fooDemo.then(res => console.log(res))); // 使用的是Promise的方法
console.log('b');
}
demo1();
结果:
async和await的应用场景 是当利用异步从网络取得了数据,然后还需要拿到取得的数据里面的数据,再用这个数据去网络获得了数据,此时使用了async和await的函数是按照顺序执行的
而如果使用Promise, 就会造成不知道那个回调函数先完成,会造成逻辑混乱
本文只用于个人学习与记录