ES6总结

目录

1.let和const

2.symbol

3.简写方式

4.解构赋值

5.for-of

6.字符串API

7.模版字符串

8.拓展运算符

9.map

10.reduce

11.新增方法

12.Map和WeakMap

13.Set和WeakSet

14.Map,Set,Array,Object

15.代理Proxy和反射Reflect

16.针对函数的拓展

17.箭头函数

18.类的概念

19.import和export

20.Promise异步编程

21.遍历接口Iterator和for...of循环

22.Generator函数

23.await和async


1.let和const

let只能在当前块作用域生效,没有变量提升,无法重复声明,存在暂时性死区
const一定要赋初始值,一般常量使用大写(属于编程规范),常量值不能修改,存在块级作用域
对于数组和对象的元素修改,不算做对常量的修改,不会报错
(因为引用数据类型保存的是内存地址,所以声明数组和对象时可以使用const声明
以此保证其保存的内存地址不变)

let obj = {
  name:'张三',
  car:'奔驰'
}
const x = obj
console.log(x.car)//输出奔驰
obj.car('比亚迪')
console.log(x.car)//输出比亚迪

2.symbol

ES6引入了一种新的原始数据类型Symbol,表示独一无二的值
它是JavaScript语言的第7种数据类型,是一个类似字符串的数据类型
Symbol值不能与其他数据进行运算,也不能与自己进行运算,譬如+、-、*、/、比较运算
Symbol定义的对象属性不能使用for…in遍历

let s = Symbol()
console.log(s,typeof s) // Symbol() "symbol"
let s2 = Symbol('张三') // '张三'作为Symbol描述,作用相当于注释
let s3 = Symbol('张三')
console.log(s2 === s3) // false
let b1 = Symbol.for('yy')
let b2 = Symbol.for('yy')
console.log(b1===b2) // true
Symbol.for这个API会在全局寻找yy这个变量,有就赋值到b1里
传入的值一致返回值就一致
//对象中使用
let a1 = Symbol("kk")
let obj = {
  [a1]:'124',
  kk:123,
  a1:456
}
console.log(obj)

3.简写方式

ES5中想把一个名为 listeners 的数组赋值给events对象中的listeners属性

var listeners = []
function listen() {}
var events = {
  listeners: listeners,
  listen: listen
}

在ES6中可以这样写
var listeners = []
function listen() {}
var events = { listeners, listen }

4.解构赋值

只要一个数据允许循环遍历的话就可以使用解构赋值

const Web = ['html', 'css', 'javascript']
let [tool1, tool2, tool3] = Web
console.log('tool1-----', tool1) // html
console.log('tool2-----', tool2) // css
console.log('tool3-----', tool3) // javascript

对象解构
const liMing = {
  name: 'liMing',
  age: '22',
  tell: function(){
  console.log(`I am liMing`)
  }
}
let {name, age, tell} = liMing
console.log(name) // 'liMing'
console.log(age) // '22'
console.log(tell) // f(){...}
tell() // I am liMing
对象解构赋值
let { foo , bar } = { foo: "aaa", bar: "bbb" };
foo = "aaa"
bar = "bbb"
给键值起别名
function fn(){
  return{
    name:'张三',
    nameList:[{
        name:'李四'
      }
    ]

  }
}
let b = fn()
let {name:person,nameList:[{name:otherPerson}]} = b
console.log(person,otherPerson) // 张三 李四

5.for-of

对字符串更好用
const str = '\u{20bb7}'
for(let word of str){
  console.log(word)
}

6.字符串API

方法描述
include(string,position)判断字符串中是否包含指定字符串,返回值是布尔值
startsWith(string,position)判断字符串的开头是否包含指定字符串,返回值是布尔值
endsWith(string,position)判断字符串的尾部是否包含指定字符串,返回值是布尔值
repeat(n)repeat() 方法返回一个新字符串,表示将原字符串重复n 次。
字符串补全第一个参数是补全后的字符串长度,第二个参数是用于补全的字符串
padStart(length,str)用于头部补全
padEnd(length,str)用于尾部补全
//find,findIndex返回第一个符合条件的值或索引
const arr = [
  {title:'es6'},
  {title:'webpack',id:2},
  {title:'vue'},
  {title:'webpack',id:3}
];
let result = arr.find(function(item){
    return item.title === 'webpack'
})
let resultIndex = arr.findIndex(function(item){
    return item.title === 'webpack'
})
console.log(result,resultIndex);

// includes 和 indexOf
// includes判断当前元素是否在数组中存在,返回值是true或false
// indexOf返回的是对应索引,不存在返回-1
const arr = [1,2,3,4,5,6];
let result = arr.includes(7);
console.log(result);

// flat展开数组的操作
const arr = [1,2,3,['2nd',4,5,6,['3rd',7,8]]];
let flatArr = [].concat(...arr);
console.log(flatArr);
// 不传参数的话默认只展开1层数组
let flatArr2 = arr.flat(2);
console.log("flat",flatArr2);

7.模版字符串

const name="⼩明"
const age=18
const hobbies="游泳、跑步和打篮球"
// ES5写法
const str1='我的名字是'+name+',我今年'+age+'岁,我喜欢'+hobbies
console.log(str1)
// ES6写法
const str2=`我的名字是${name},我今年${age}岁,我喜欢${hobbies}`
console.log(str2)

8.拓展运算符

展开数组
console.log(...[1,2,3]); // 1 2 3
console.log(1,...[2,3,4],5) // 1 2 3 4 5
console.log([1,...[2,3,4],5]) // [1, 2, 3, 4, 5]
let a,other
[a,...other] = [1,2,3];
console.log(a,other) // 1 [2,3]


深拷贝数组
let arr1 = [1,2,3,4,5]
let arr2 = [...arr1]

分割数组
const arr1 = [1,'a','b','c']
let [,...arr2] = arr1
console.log(arr2) // ['a','b','c']
//fill方法
let arr3 = [...arr1].fill(3) //[3,3,3,3]
//参数:要替换的值,开始的下标,结束的下标(包左不包右)
let arr4 = [...arr1].fill(3,1,3) //[1,3,3,'c']

// 复制对象
const obj = {name:'xiaoming',age:'19'};
const initObj = {color:'red'}
let obj2 = {...obj}
console.log(obj2);
//给对象设置默认值
let obj3 = {...obj,name:'jack'}
console.log(obj3);
// 合并对象
let obj4 = {...obj,...initObj};
console.log(obj4);

9.map

const json = [
  { title: 'es6', status: 1 }, 
  { title: 'react', status: 0 }, 
  { title: 'webpack', status: 1 }, 
  { title: 'vue', status: 0 }
]
let video = json.map(function (item) {
  let obj = {}
  // 复制对象方法,防止源数据被污染
  Object.assign(obj, item)
  obj.status = obj.status ? '已上线' : '未上线'
  return obj
})

10.reduce

// reduce对数组中的每一个元素进行一次回调
// 升序执行然后将回调值汇总成一个返回值
reduce 对数组中的每个元素进行一次回调,升序执行然后将回调值汇总一个返回值
回调函数中的参数:
acc:返回值(每次回调之后的返回值)
currentValue:当前进行回调的值
currentIndex :currentValue对应的位置
reduce参数:
initalValue:就是返回值,是一个可选参数,如果传入值的话acc初始值就是这个值
             如果不传的话acc初始值就是数组中的第一项
不传入的话acc的初始值是数组第一项

const letterList = "abcadefrd";
const result = letterList.split('').reduce(function (acc, cur) {
  //acc初始值就是{},判断acc对象中是否有该属性,有就把值加1,没有就赋值1
  acc[cur] ? acc[cur]++ : acc[cur] = 1
  return acc
//这个空对象就是initalValue
}, {})
console.log(result);

11.新增方法

// Object.is
let result = Object.is(NaN,NaN); // true
console.log(result,NaN === NaN); // false

// Object.assign 复制对象 浅拷贝
const person = {name:'小花',age:19,info:{height:180}};
let person2 = {};
Object.assign(person2,person);
person.info.height = 160;
console.log(person2);

//Object.keys (遍历对象中的所有属性名)返回数组
//Object.values (遍历对象中的所有属性值)返回数组
//Object.entries (遍历对象中的所有键值对)返回二维数组
const json = {name:'zhangsan',video:'es6',date:'2021'}
let obj = {};
console.log(Object.entries(json));
for(const key of Object.keys(json)){
    obj[key] = json[key]
}
console.log(obj);

12.Map和WeakMap

Map用于保存键值对,任何值(对象或者原始值)都可以作为一个键或一个值。

//创建一个map
let map = new Map();
// 参数一:key,参数二:value
map.set([1,2,3],'number');
console.log(map);

创建时直接赋值
//这里每一个数组都是map中一个值,数组中的第一个值为key,第二个值为value
let map2 = new Map([["name","zhangsan"],["sex","male"]])
console.log(map2.size); // 2
//map2里的zhangsan会变成jack
map2.set("name","jack").set("hobbies",['抽烟','喝酒','烫头'])
属性或方法作用
size返回键值对的数量
clear()清除所有键值对
has(key)判断键值对中是否有指定的键名,返回值是布尔值
get(key)获取指定键名的键值对,如不存在则返回 undefined
set(key,value)添加键值对,如键名已存在,则更新键值对
delete(key)删除指定键名的键值对
// WeakMap
// 1,只接受对象作为键名,不接受任何其他类型
// 2,键名所指的对象会触发垃圾回收机制
// 3,没有clear 没有size 无法遍历
let weakMap = new WeakMap([
    [{name:'haha'},'xxx']
])
console.log(weakMap);
//常规情况下如何回收垃圾
let obj = {name:'zhangsan'};
let arr = [obj,'person'];
arr[0] = null;

13.Set和WeakSet

ES6提供了新的数据结构set(集合),本质上是一个对象
它类似于数组,但成员的值都是唯一的,集合实现了iterator接口
所以可以使用「扩展运算符」和for...of进行遍历

let set = new Set(['1', 1, 2, 3, 4, 5]);
//元素重复添加不进去
set.add(1);
console.log(set);
console.log("size", set.size);

let set = new Set();
set.add({fruit:'apple'});
//因为set里面存的是对象的地址,has中的是一个新对象,地址不同
console.log("has",set.has({fruit:'apple'})) // false
const item = { fruit: 'apple' };
set.add(item);
console.log("has", set.has(item)) //true

// keys() values() entries()
const set = new Set([1, 2, 3, 4, 5]);
for (const key of set.keys()) {
    console.log(key);//key的值跟value的值是一样的,并不是常规索引
}
for (const value of set.values()) {
    console.log(value);
}
for (const value of set.entries()) {
    console.log(value);
}

//数组去重
const arr = [1, 2, 4, 5, 1, 2, 5, 7, 9, 7];
let set = new Set(arr);
console.log(set);
//将set转换为数组
let arr2 = Array.from(set);
console.log(arr2);
size返回集合的元素个数
add(value)增加一个新元素,返回当前集合
delete(value)删除元素,返回Boolean值
has(value)检测集合中是否包含某个元素,返回Boolean值
clear()清除所有成员
WeakSet
1.元素只能是对象
2.无法遍历 没有size 没有clear

let obj = {};
let weekSet = new WeakSet();
weekSet.add(obj);
console.log(weekSet);

14.Map,Set,Array,Object

let arr = [];
let obj = {};
let map = new Map();
let set = new Set();
const item = {fruit:'apple'};
// 增加
arr.push(item);
obj["fruit"] = item.fruit;
map.set("fruit","apple");
set.add(item);
console.log("add",arr,obj,map,set);
// 查询
const resultArr = arr.includes(item);
const resultObj = 'fruit' in obj;
const resultMap = map.has('fruit');
const resultSet = set.has(item);
console.log("search",resultArr,resultObj,resultMap,resultSet);
// 修改
arr.forEach(function(item){
    item.fruit = item.fruit ? 'orange' : '';
})
obj['fruit'] = 'orange';
map.set('fruit','orange');
set.forEach(function(item){
    item.fruit = item.fruit ? 'orange' :'';
})
console.log("update",arr,obj,map,set);
// 删除
const index = arr.findIndex(function(item){
    return item.fruit
})
arr.splice(index,1);
delete obj.fruit;
map.delete("fruit");
set.delete(item);
console.log("delete",arr,obj,map,set);
// 类型转换 map和对象间转换
let obj = {
    name:'小明',
    age:19
}
// 由于map中要接收的是键值对数组,所以需要将对象转换为键值对数组
// 通过Object.entries这个API就可以进行转换 
let map = new Map(Object.entries(obj))
console.log("map",map);
// map 转对象
let obj2 = Object.fromEntries(map);
console.log("obj",obj2);
// 数组和set
let arr = [1,2,3,4];
// 数组转set
let set = new Set(arr);
console.log("set",set);
// set转数组
let arr2 = Array.from(set);
console.log("arr",arr2);

15.代理Proxy和反射Reflect

Proxy直接作用在对象上,而是作为一种媒介
如果需要操作对象的话,需要经过这个媒介的同意
使用方法:let p = newProxy(target,handler)
target:⽤Proxy包装的⽬标对象
handler:⼀个对象,对代理对象进⾏拦截操作的函数,如set、get

{
  let account = {
    id: 9999,
    name: 'admin',
    phone: '13838383838',
    _private: 'demo',
    create_time: '2021'
  }

  let accountProxy = new Proxy(account, {
    //拦截读取操作
    // 需求:对手机号中间4位换成****,创建时间换成2020
    //target就是传进来的对象
    get: function (target, key) {
      switch (key) {
        case 'phone':
          return target[key].substring(0, 3) + "****" + target[key].substring(7)
        case 'create_time':
          return target[key].replace("2021", 2020);
        default:
          return target[key]
      }
    },
    // 拦截设置操作
    // 需求:如果要设置的是id就不允许设置
    // 判断如果要设置的是id就赋值成之前的默认值,其他正常赋值
    // name是要设置的键名,value是要设置的值
    set: function (target, key, value) {
      if (key === "id") {
        return target[key]
      } else {
        return target[key] = value
      }
    },
    // 拦截 key in obj 操作
    // 就是判断这个key是否在对象中存在的操作
    has: function (target, key) {
      if (key in target) {
        console.log(`${key}:`, target[key]);
        return true
      } else {
        console.log("没有这个属性");
        return false
      }
    },
    // 拦截delete操作
    // 需求:如果当前要删除的key是以下划线开头证明是私有属性,不允许删除
    deleteProperty: function (target, key) {
      if (key.indexOf("_") === 0) {
        console.warn("私有属性不能删除");
        return false
      } else {
        delete target[key]
        return true
      }
    },
    // 拦截Object.keys()遍历操作
    // 需求:如果是id或者以下划线开头的就过滤掉,不能输出
    ownKeys(target) {
      return Object.keys(target).filter(function (item) {
        //把id和 _ 开头的属性过滤掉
        return item !== "id" && item.indexOf("_") !== 0;
      })
    }
  })

  console.log("拦截读取", accountProxy.phone, accountProxy.create_time);
  accountProxy.id = "123";
  accountProxy.name = "xxxx";
  console.log("拦截设置", accountProxy.id, accountProxy.name);
  console.log("-----------------");
  console.log('拦截in', "name" in accountProxy);
  console.log("==============");
  // console.log("拦截删除",delete accountProxy["_private"]);
  console.log("拦截删除", delete accountProxy["name"]);
  console.log("拦截Object.keys()", Object.keys(accountProxy));
}

Reflect就是操作对象属性和方法的另外一种方式
它将对象里一些明显属于语言内部的方法移植到Reflect对象上
它对某些方法的返回结果进行了修改,使其更合理
并且使用函数的方式实现了Object的命令式操作
let obj = {
  name: '张三',
  age: '22',
  sex: 'male',
  hobbies: '玩的晚,睡觉,迟到'
}
console.log(Reflect.get(obj, 'hobbies'));
Reflect.set(obj, 'name', '温俊康');
console.log(obj.name);
console.log(Reflect.has(obj, 'name'));
实现双向绑定
{
  // 获取dom元素
  // 获取输入框
  const inp = document.querySelector("#inp");
  // 获取span标签
  const txt = document.getElementById("txt");
  // 初始化代理对象,也就是下面的target
  const obj = {};
  // 代理选项 
  const handler = {
    get: function (target, key) {
      console.log("get");
      //获取值
      return Reflect.get(target, key)
    },
    set: function (target, key, value) {
      if (key === "text") {
        //向输入框中设置值
        inp.value = inp.value === value ? inp.value : value;
        //把值同步给span
        txt.innerHTML = value;
      }
      //向对象中设置值
      return Reflect.set(target, key, value)
    }
  }
  let objProxy = new Proxy(obj, handler);
  inp.addEventListener("keyup", function (e) {
    //给objProxy添加一个text属性并赋值
    //因为是代理,所以拦截到设置触发set方法
    objProxy.text = e.target.value
    console.log(objProxy.text);
  })
  //初始值
  objProxy.text = "123"
}

16.针对函数的拓展

// 默认参数
//ES5模式
function es5Fn(x, y) {
  y = y || "word"
  console.log('es5', x + y);
}
es5Fn("haha", "hehe");
//ES6模式
function es6Fn(x, y = "world") {
  console.log("es6", x + y);
}
es6Fn("哈哈")

//rest把所有的参数都保存在一个数组里
function add(...rest) {
  console.log(rest);
  let sum = 0;
  //累加
  for (let value of rest) {
    sum += value
  }
  console.log(sum);
}
add(1, 2, 3, 4, 5);

// 尾调用
// 在函数调用后返回另一个函数,这种称之为尾调用
// 如果后面有其他任何运算都不是尾调用
function fn1(x) {
  console.log('尾调用', x);
}
function fn2(){
    return fn1(111)
}
fn2()
//尾递归
function fn2(){
    return fn2()
}
fn2()

17.箭头函数

//声明函数
const arrow = (x, y) => {
  console.log("箭头函数", x + y);
}
arrow(5, 6)
//当只有一个参数且函数语句只有一句是return和{}可以省略
const arrow = x => x * 2
//箭头函数没有this,它里的this始终指向它被创建时所处作用域中的this
const obj = {
  name: 'apple',
  age: 19,
  show: function () {
    window.setTimeout(() => {
      console.log(this);
      console.log(this.name, this.age);
    }, 1000)
  },
  aa: () => {
    console.log(this);
  }
}
//Object.method()这样调用哦个的话就用普通函数进行声明,其他情况下都用箭头函数

18.类的概念

//es5的时候是通过构造函数来实现类的功能的
//因为函数是引用类型,若直接在构造函数中写方法
//在建立多个对象时会开辟多个空间来存储相同的函数,浪费
function Person(name,age){
  this.name = name;
  this.age = age;
}
Person.prototype.say = function(){
  console.log(`大家好,我叫${this.name},今年${this.age}岁了`);
}
const p = new Person("小明",19);
console.log(p);
p.say()

// es6新增关键字
class Person {
  constructor(name, age) {
    //this指向实例
    this.name = name;
    this.age = age;
  }
  sayHello() {
    console.log(`大家好,我叫${this.name},今年${this.age}岁了`);
  }
}
const p = new Person("小明", 19);
console.log("class", p);
p.sayHello()

// 类的继承
class Person {
  //设置初始值
  constructor(name = "小黑") {
    this.name = name
  }
}
//继承
class Child extends Person {
  constructor(name = "小白", age = 19) {
    //name是父类继承来的,super调用父类的constructor,把name赋值上
    //super一定要放到构造函数最上面
    super(name)
    this.age = age;
  }
}
console.log('继承', new Child());

//注意get和set是两个属性不是方法
class Person {
  constructor(name = "小黑") {
    this.name = name
  }
  get fullName() {
    return this.name + '\xa0' + '欧阳'
  }
  set fullName(value) {
    this.name = value
  }
}
const p = new Person();
console.log("get", p.fullName);
p.fullName = "小红"
console.log("set", p.name);

//静态成员:在构造函数本身上添加的成员称为静态成员,只能由构造函数本身来访问
//实例成员:在构造函数内部创建的对象成员称为实例成员,只能由实例化的对象来访问
class Person {
  constructor(name = "小黑") {
    this.name = name
  }
  //static声明的就是静态属性
  static say(obj) {
    console.log('my name is' + obj.name);
  }
}
const p = new Person("小花");
Person.say(p);
Person.aaa = "xxx"
console.log(Person.aaa);

19.import和export

//require用法
function test (args) {
  console.log(args);	
}
module.exports = {
  test
};
let { test } = require('./a.js');
test('this is a test.');

//import
export function test (args) {
  console.log(args);	
}
// 默认导出模块,一个文件中只能定义一个
export default function() { };
export const name = "wjk";
// _代表引入的export default的内容
import _, { test, name } from './a.js';
test(`my name is ${name}`);

20.Promise异步编程

//传统的异步操作会造成回调地狱,两层以上就很难让人理解
// 一层回调
function ajax(cb){
  setTimeout(() => {
    cb && cb();
  }, 1000);
}
ajax(()=>{
  console.log('任务1');
})
// 两层回调
function ajax(cb){
  setTimeout(() => {
    cb && cb(()=>{
      console.log('任务2');
    });
  }, 1000);
}
ajax((cb2)=>{
  console.log('任务1');
  setTimeout(() => {
    cb2 && cb2()
  }, 1000);
})

//利用promise完成异步请求
// Promise 改造回调函数
// resolve和reject是回调函数中的方法
function ajax() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      //一秒之后执行resolve()
      //resolve也就是下一步函数要干什么
      resolve();
    }, 1000);
  })
}
ajax()
  //then传进去的回调函数实际上就是resolve
  .then(() => { 
    //执行完任务1再执行任务2
    console.log('任务1');
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve();
      }, 1000);
    })
  })
  // 因为ajax函数返回值也是一个promise对象
  // 所以可以继续使用.then
  .then(() => {
    console.log('任务2');
  })
// 使用catch方法捕获错误
// catch里回调函数其实是reject
function isNumber(num) {
  return new Promise((resolve, reject) => {
    if (typeof (num) === "number") {
      resolve(num)
    } else {
      const err = new Error("请输入数字");
      reject(err)
    }
  })
}
isNumber("2").then((n) => {
  return console.log(n);
}).catch((err) => {
  return console.log(err);
})
//简写
isNumber(2)
.then(n=>console.log(n))
.catch(err=>console.log(err))
const imgUrl1 = "https://cn.vuejs.org/images/logo.svg"
const imgUrl2 = "https://www.webpackjs.com/6ccd91e44bf7f92d9942781dbc6094b5.png"
const imgUrl3 = 
"https://www.bukaedu.com/files/system/2019/11-28/164327f5243b556898.png"
function getImage(url) {
  return new Promise((resolve, reject) => {
    const img = document.createElement("img");
    img.src = url
    img.onload = () => {
      resolve(img)
    }
    img.onerror = (err) => {
      reject(err)
    }
  })
}
// 渲染所有图片的方法
// forEach就是对数组中的每个元素都执行一次函数
function showImage(imgs) {
  imgs.forEach(item => {
    document.body.appendChild(item)
  });
}
function showFirstImage(img) {
  document.body.appendChild(img)
}
// Promise.all接收promise数组,判断参数中有所的Promise是否执行完毕了
// 当全部执行完之后会执行.then
Promise.all([getImage(imgUrl1),getImage(imgUrl2),getImage(imgUrl3)])
.then(showImage)
// Promise.race用于希望多个Promise函数当中只要有一个执行成功就会触发.then()
Promise.race([getImage(imgUrl1),getImage(imgUrl2),getImage(imgUrl3)])
.then(showFirstImage)

21.遍历接口Iterator和for...of循环

Iterator存在数据集合Symbol身上的一个属性,本质是一个函数
调用它之后会生成一个遍历器对象
遍历器对象上有一个next方法,next能取出数据,还能标识循环是否结束
任何数据结构如果部署了Iterator接口,就能够实现遍历的操作。
const arr = [1,2,3];
const fn = arr[Symbol.iterator]();
console.log(fn.next()) {value:1,done:false}
console.log(fn.next()) {value:2,done:false}
console.log(fn.next()) {value:3,done:false}
console.log(fn.next()) {value:undefined,done:true}

//自行添加iterator
const obj = {
  color: 'red',
  price: 99,
  size: 'small',
  [Symbol.iterator]() {
    let index = 0;
    const values = Object.values(this);
    return {
      next() {
        if (index < values.length) {
          return {
            value: values[index++],
            done: false
          }
        } else {
          return {
            value: undefined,
            done: true
          }
        }
      }
    }
  }
}
//普通遍历
for (let item of obj) {
  console.log(item);
}
//利用iterator遍历
let fn2 = obj[Symbol.iterator]();
console.log(fn2.next());
console.log(fn2.next());
console.log(fn2.next());
console.log(fn2.next());

22.Generator函数

Generator函数是一个状态机,封装了多个内部状态
Generator是可以暂停执行的,所以函数名之前要加星号,以示区别
整个Generator就是一个封装的异步任务,或者说是异步任务的容器
异步操作需要暂停的地方,都用yield语句
function fn(){ // 定义一个Generator函数
yield ‘hello’;
yield ‘world’;
return ‘end’;
}
var f1 =fn(); // 调用Generator函数
console.log(f1); // fn {[[GeneratorStatus]]: “suspended”}
console.log(f1.next()) // {value: “hello”, done: false}
console.log(f1.next()) // {value: “world”, done: false}
console.log(f1.next()) // {value: “end”, done: true}
console.log(f1.next()) // {value: undefined, done: true}

//利用迭代器遍历对象
let obj = {
  a: 1,
  b: 2,
  c: 3
}
obj[Symbol.iterator] = function* () {
  for (const key of Object.keys(obj)) {
    yield obj[key]
  }
}
for (const value of obj) {
  console.log(value);
}

// 长轮询
// 模拟异步操作
function fn1() {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('查询中');
      resolve({ code: 1 })
    }, 1000);
  })
}
const getStatus = function* () {
  yield fn1()
}
function autoGetStatus() {
  //获取一个Generator实例,也就是一个迭代器
  const gen = getStatus()
  const status = gen.next();
  //通过getStatus.next()方法调用了上面函数中yield fn1()
  //函数拿到一个Promise对象
  status.value.then(res => {
    if (res.code === 0) {
      console.log('用户付款成功');
    } else {
      console.log('暂未付款');
      //若没有付款则隔段时间继续查询状态
      //递归
      setTimeout(() => {
        autoGetStatus();
      }, 500);
    }
  })
}
autoGetStatus()

23.await和async

async是异步的简写,用于声明一个函数是异步函数
await等待的是一个表达式,这个表达式的计算结果是Promise对象或者其它值
(换句话说,就是没有特殊限定)
function fn1() {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('任务1');
      resolve()
    }, 1000);
  })
}
function fn2() {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('任务2');
      resolve()
    }, 1000);
  })
}
function fn3() {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('任务3');
      resolve()
    }, 1000);
  })
}
async function init(f1, f2, f3) {
  //await一直等到promise中的resolve执行完了才会放行
  await f1();
  await f2();
  await f3();
}
init(fn1, fn2, fn3)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无非是我

不必打赏,欢迎指正

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值