一.迭代器Iterator
迭代器是一个能快捷访问数据的接口,通过Symbol.iterator创建迭代器,然后由迭代器方法next方法获取迭代之后的结果.
迭代器就是一个用于遍历数据结构的指针,一种新的遍历机制
const item = ['one', 'two', 'three']
console.log(item[Symbol.iterator]);
//item[Symbol.iterator]返回迭代器 创建新的迭代器
const ites = item[Symbol.iterator]()
//通过迭代器调用next方法,返回对象value: "one"和done:false
console.log(ites.next());//done:返回false时表示遍历可以继续,如果为true表示遍历完成
console.log(ites.next());
console.log(ites.next());
console.log(ites.next());//done:true value:undefined 表示数组已经遍历完了
二.生成器generator
可以通过yield将函数挂起,使函数不在往下执行;为了改变执行流程提供可能,也为做异步编程提供了方案
与普通函数的区别:
- function后面和函数名之前有个*
- 只能在函数内部使用yield表达式让函数挂起
1.yield
Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行
每次遇到yield
,函数暂停执行,下一次再从该位置继续向后执行,而return
语句不具备位置记忆的功能。一个函数里面,只能执行一次(或者说一个)return
语句,但是可以执行多次(或者说多个)yield
表达式。正常函数只能返回一个值,因为只能执行一次return
;Generator 函数可以返回一系列的值,因为可以有任意多个yield
。
yield
表达式后面的表达式,只有当调用next
方法、内部指针指向该语句时才会执行
遍历器对象的next
方法的运行逻辑如下。
(1)遇到yield
表达式,就暂停执行后面的操作,并将紧跟在yield
后面的那个表达式的值,作为返回的对象的value
属性值。
(2)下一次调用next
方法时,再继续往下执行,直到遇到下一个yield
表达式。
(3)如果没有再遇到新的yield
表达式,就一直运行到函数结束,直到return
语句为止,并将return
语句后面的表达式的值,作为返回的对象的value
属性值。
(4)如果该函数没有return
语句,则返回的对象的value
属性值为undefined
。
function* func() {
yield 2
}
let fn = func()//返回遍历器对象 可以调用next()返回yield值
console.log(fn.next());//done:false value:2
console.log(fn.next());//done:true value:undefined
2.next()
function* add() {
console.log('start');
let x = yield '2'
console.log('one:' + x);
let y = yield '3'
console.log('two:' + y);
return x + y
}
// x,y不是yield返回值,而是使用next()方法,恢复执行yield传入的实参
let fn = add()
console.log(fn.next());//done: false value: "2" 恢复yield的执行
console.log(fn.next(20));//done:false value:"3"
console.log(fn.next(30));//done: true value:50
3.geneartor用处
(1)为不具备Interator接口的对象提供添加接口遍历操作
有点懵........
// 2.生成迭代器函数
function* objectEntries() {
// 获取对象
const propKeys = Object.keys(obj)
// 3.通过for of遍历数组 propKey 表示每一个【name age】
for (const propKey of propKeys) {
yield [propKey, obj[propKey]]
}
}
const obj = {
name: 'lalla',
age: '18'
}
// 1.为数组生成迭代器函数 ,提供接口
obj[Symbol.iterator] = objectEntries//Symbol(Symbol.iterator): ƒ * objectEntries()
console.log(obj);
// 4.迭代器生成后可通过for。。。of遍历
for (let [key, value] of objectEntries(obj)) {
console.log(`${key},${value}`);
}
(2)让异步代码同步化
设置一个页面加载成功1s后关闭分三步:开始加载页面,加载成功,关闭加载页面
若分别写三个函数进行调用,则隐藏函数会比加载完成函数先执行,因为加载完成是一个异步操作
所以这时候可以使用generator迭代器,通过yield暂停函数,在由next方法调用函数
// 5.迭代器方法
function* load() {
loadUI()
yield showData()
hideUI()
}
// 1.数据开始加载
function loadUI() {
console.log('开始加载......');
}
//2.加载完成
function showData() {
setTimeout(() => {
console.log('加载完成');
itload.next()//7.执行hideUI
}, 1000)
}
// 3.结束加载
function hideUI() {
console.log('加载结束......');
}
// 4.创建迭代器
let itload = load()
// 6.执行showData()
itload.next()
三.Promise对象
Promise相当于一个容器,保存着未来才会结束的事件(异步操作)的结果;各种异步操作都可以由同样方法处理
特点:
(1)对象的状态不受外界影响,处理异步操作三个状态:pending(进行中),resolved(已成功),rejected(已失败)
(2)状态改变就不再变,
let pro = new Promise(function (resolved, rejected) {
//执行异步操作
let res = {
code: 221,
data: {
name: 'lala'
},
error: '错了'
}
setTimeout(() => {
if (res.code === 222) {
resolved(res.data)
} else {
rejected(res.error)
}
}, 1000)
})
console.log(pro);
//接收当前异步操作完成后返回的结果 then()可以接受第二个回调函数
pro.then((val) => {
console.log(val);
}, (err) => {
console.log(err);
})
也可以简化写:
// timeout为超时函数
function timeout(ms) {
return new Promise((resolved, rejected) => {
setTimeout(() => {
resolved('成功了')
}, ms)
})
}
// 调用上面函数, 然后返回正确时间,2000为传入的ms参数,val为返回的resolved
timeout(2000).then((val) => {
console.log(val);
})
promise好友很多方法,后期学习
四.async用法
使异步操作更方便
async有多种使用方法:
// 函数声明
async function foo() {}
// 函数表达式
const foo = async function () {};
// 对象的方法
let obj = { async foo() {} };
obj.foo().then(...)
// Class 的方法
class Storage {
constructor() {
this.cachePromise = caches.open('avatars');
}
async getAvatar(name) {
const cache = await this.cachePromise;
return cache.match(`/avatars/${name}.jpg`);
}
}
const storage = new Storage();
storage.getAvatar('jake').then(…);
// 箭头函数
const foo = async () => {};
async
函数返回一个 Promise 对象。async
函数内部return
语句返回的值,会成为then
方法回调函数的参数。
async
函数就是将 Generator 函数的星号(*
)替换成async
,将yield
替换成await
如果await
操作成功,就会使用break
语句退出循环;如果失败,会被catch
语句捕捉,然后进入下一轮循环。
五.class类/继承
ES6类的写法:
constructor()必须在实例化时立即被调用
class Person {
// 实例化时立即被调用
constructor(name, age) {
this.name = name
this.age = age
}
// 给实例赋值方法
sayName() {
return this.name
}
sayAge() {
return this.age
}
}
let p1 = new Person('ww', '18')
console.log(p1);
类的继承:
使用extends实现继承
class Animal {
constructor(name, age) {
this.name = name
this.age = age
}
sayName() {
return this.name
}
sayAge() {
return this.age
}
}
// 继承父类属性方法
class Dogs extends Animal {
constructor(name, age, color) {
super(name, age)
this.color = color
}
sayColor() {
return `${this.name}今年${this.age}岁了,它是${this.color}的`
}
// 重写父类方法
sayName() {
return this.name + super.sayAge() + this.color
}
}
let d1 = new Dogs('大老黑', '2', 'black')
console.log(d1.sayColor());
console.log(d1.sayName());