零散知识
- ES6 -> ECMA 标准
- ES7 ES8…
- ES5.x
- 最早的版本:ECMA-262 -> ES1.0
- ES2015
- ES6 -> 2015年6月 ES6.0
- 每年6月份,发布一个版本
2016年6月 ES6.1 ES7 ES2016
2017年6月 ES6.2(async await) ES8 ES2017
ESnext '下一代 js'语言
- 任何人都可以向 标准委员会 (TC39), 要求更改语言标准
- 提案变成标准,经历5个阶段
Stage 0 展示阶段 Stage 1 征求意见阶段 Stage 2 草案阶段(准备) Stage 3 候选阶段 Stage 4 定案阶段(标准)
- babel
- https://github.com/tc39/ecma262
- react, vue, angularJs, angular
- chrome, 对新的语法支持,速度还挺猛
- ES6环境:
webpack3.x
Traceur
关于定义(声明)变量:
-
之前:
var a=12; let a=12;
-
作用域:
- 全局作用域
- 函数作用域
-
- let 相当于之前的 var
- const 常量, 定义好了不能改变
- 用var定义一个全局变量,属于window, let,const不同,不属于window
-
let注意:
- 没有预解析,不存在变量提升
- 在代码块内,只要let定义变量,在之前使用,都是报错
- 先定义完,在使用
- 同一个作用域里, 不能重复定义变量
- 例1:报错
let a = 12; let a = 5;
- 例2:正确
let a = 12; a = 5;
- 例1:报错
- for循环,for循环里面是父级作用域,里面又一个
- 没有预解析,不存在变量提升
-
TDZ:暂时性死区
- 例1:
let a = 12; function fn(){ alert(a); //TDZ开始 暂时性死区 alert(b) let a = 5; //TDZ 结束 let b = 12; } fn();
- 例1:
-
块级作用域:
{ //块级作用域 }
- 比如说
- {{{{let a = 12}}}}
- if(){xx}
- for(){}
- while(){}
- 比如说
-
const: 特性和let一样
- const定义变量不能修改
- const定义完变量,必须有值,不能后赋值,不能修改
- 例
- 例1:
const arr =['apple','banana']; arr.push('orange'); console.log(arr); //返回三个元素,因为,数组的地址并没有改变,只是新添了元素
- 例2:使用Object.freeze(对象)
const arr = Object.freeze(['apple','banana']); arr.push('orange'); //不能扩展,报错 console.log(arr);
- 例3:
const config={ host: username: password: version: }
- 例4:立即执行函数
{ //TODO } IIFE(立即执行函数) (function(){ //TODO })()
- 例1:
-
建议:以后就用 let,const 不要再使用var,比如const http = require(‘http’);
解构赋值:
非常有用,特别在做数据交互 ajax
- 解构数组
例1:let [a,b,c] =[12,5, 6]; let [a,[b,c]] =[12,[5, 6]]; //注意: 左右两边,结构格式要保持一致
- 解构json
例1:let {name,age, job} = { name:'Strive', age:18, job:'码畜' };
- 起别名:
let {name:n,age:g, job:a} = json;
- 解构时候可以给默认值:
- 例1:注意null
let [a,b, c="默认值"] = ['aaa','bbb']; let [a, b, c = '暂无...'] = ['aa' , 'b' , null]; //返回null let [a, b, c = '暂无...'] = ['aa' , 'b' , undefined]; //返回暂无...
- 例2:正常花括号是结构,但是有时候写不好可能被当作块级作用域,解决方法就是在外面再包一层小括号()
let a; ({a} = {a:'apple', b:'banana'}); //这个大括号用不好会被当作块级作用域,所以最好用let {a} = {a:'apple',...},而不是将let a 和{a}分开 console.log(a);
- 例3:交换两个数的位置
let a = 12; let b = 5; [a,b] = [b,a]; console.log(a,b); import {a,b,c} from './mod'
- 例4:
function show({a='默认1',b='默认'} = {}){ console.log(a, b); //因为函数没有传参数,如果直接将对象传进去会报错,所以我们将函数参数也给个默认值为{},这样就不会报错了 } show()
- 例1:注意null
- 解构赋值在函数中的应用
- 应用1:
function show({a,b='默认'}){ console.log(a, b); } show({ a:1 }) //1 undefined
- 应用2:
function show({a='默认1',b='默认'}){ console.log(a, b); } show({})
- 应用1:
字符串模板:
- 字符串模板:
- 优点: 可以随意换行
- 用法:
${变量名字}
- 字符串连接
例:
let name ='Strive'; let age = 18; let str = `这个人叫${name}, 年龄是 ${age}岁`;
- 字符串查找:
- str.indexOf(要找的东西) 返回索引(位置) ,没找到返回-1
- str.includes(要找的东西) 返回值 true/false
- 判断浏览器: includes
http://www.xxx.xx
- 字符串是否以谁开头:str.startsWith(检测东西)
例:检测地址
let str2 ='https://www.baidu.com/'; console.log(str2.startsWith('http'));
- 字符串是否以谁结尾:str.endsWith(检测东西)
例:.png
let str = 'aaaa.png'; let str2 = 'aaaa.html'; console.log(str2.endsWith('png'));
- 重复字符串:str.repeat(次数);
例:
let str = '牧码人'; console.log(str.repeat(2));
- 填充字符串:
- str.padStart(整个字符串长度, 填充东西) 往前填充
- str.padEnd(整个字符串长度, 填充东西) 往后填充
- str.padStart(str.length+padStr.length, padStr),第一个参数是填充后字符串长度
函数变化:
- 函数默认参数
- 例1:
function show({x=0,y=0}={}){ console.log(x,y); //0 0 } show()
- 例2:
function show({x=0,y=0}){ console.log(x,y); //报错 } show()
- 例3:
function show(a='欢迎',b='mmr'){ console.log(a,b); } show('welcome' , ''); //代表传了但是是空字符串,不走默认值
- 例4:函数参数默认已经定义了,不能再使用let,const声明
function show(a=18){ let a = 101; //错误,报错 console.log(a); } show()
- 例1:
扩展运算符(Rest运算符): …
- 展开数组
... : [1,2,3,4] -> ... [1,2,3,4] -> 1,2,3,4,5 ... : 1,2,3,4,5 -> ...1,2,3,4,5 -> [1,2,3,4,5]
- 例1:剩余参数: 必须放到最后
function test(a, b, ...c){ console.log(a, b, c); } test(1, 2, 3, 4, 5);
- 例2:
let arr =['apple','banana','orange']; console.log(arr); /*Array(3)['apple' , 'banana' , 'orange']*/ console.log(...arr); /*apple banana orange*/
- 例1:剩余参数: 必须放到最后
- 箭头函数: =>
- 格式:
- () => return东西
例:let show = () => 1; - () =>{
语句
return
- () => return东西
- 注意:
- this问题, 定义函数所在的对象,不在是运行时所在的对象
- 箭头函数里面没有arguments, 用 ‘…’
- 箭头函数不能当构造函数
- 例题:
- 例1:解释注意中的 2
let show = (...arg) =>{ console.log(arg); } show(1, 2, 3, 4);
- 例2:
var id = 10; //用var定义一个全局变量,属于window, let,const不同,不属于window let json={ id:1, show:function(){ setTimeout(function(){ alert(this.id);//如果全局范围内没定义id或者用let定义id的话,返回undefined,所以这里返回9 },2000); /* setTimeout(()=>{ alert(this.id); /*用箭头函数定义,这里的this不再是全局内的this,而是属于这个对象,所以这里的this.id为1*/ },2000);*/ } }; json.show();
- 例3:
//ES2017 函数参数最后逗号可以有了 function show(a,b,c,d,){ console.log(a,b,c,d); } show(1 , 2 , 3 , 4 ,);//不报错
- 例1:解释注意中的 2
- 格式:
数组:ES5里面新增一些东西
注意:
从forEach开始到reduce之前结束,这些数组方法,其实他们可以接收两个参数:
arr.forEach/map…(循环回调函数, this指向谁(this默认指向window));
- arr.forEach() // 代替普通for
- 例1
arr.forEach(function(val, index, arr){ console.log(this, val, index, arr); //this默认指向window });
- 例2:
arr.forEach(function(val, index, arr){ console.log(this, val, index, arr); //this指向Number }.bind(123)); <==> }, 123)
- 普通循环:
1. for for(let i=0; i<arr.length; i++) 2. while
- 例1
- arr.map() // 非常有用,做数据交互 “映射”
- 正常情况下,需要配合return,返回是一个新的数组,若是没有return,相当于forEach
- 注意:平时只要用map,一定是要有return
- 重新整理数据结构:[{title:‘aaa’}] -> [{t:‘aaaa’}]
- map例:
let arr = [ {title:'aaaaa', read:100, hot:true}, {title:'bbbb', read:100, hot:true}, {title:'cccc', read:100, hot:true}, {title:'dddd', read:100, hot:true} ]; let newArr = arr.map((item, index, arr)=>{ let json={} json.t = `^_^${item.title}-----`; json.r = item.read+200; json.hot = item.hot == true && '??°?!!!'; return json; }); console.log(newArr);
- arr.filter(): 过滤,过滤一些不合格“元素”, 如果回调函数返回true,就留下来
let arr = [ {title:'aaaaa', read:100, hot:true}, {title:'bbbb', read:100, hot:false}, {title:'cccc', read:100, hot:true}, {title:'dddd', read:100, hot:false} ]; let newArr = arr.filter((item, index, arr)=>{ return item.hot==false; }); console.log(newArr);
- arr.some(): 类似查找, 数组里面某一个元素符合条件,返回true
- 例1:
let arr = [10, 12, 11] let res = arr.some(function(val, index, arr){ return val == 10; }) console.log(res);
- 例2:封装方法
let arr = [1, 2, 3, 4]; function findInArray(arr, item){ return arr.some(function(val, index, arr){ return val == item; }) } console.log(findInArray(arr, 1))
- 例1:
- arr.every(): 数组里面所有的元素都要符合条件,才返回true
- arr.reduce() //从左往右,一般用来求数组的和、阶乘
- 例:
let arr = [2,2,3]; let res = arr.reduce((prev, cur, index, arr) =>{ return Math.pow(prev,cur); }); console.log(res);
- 例:
let arr = [1,2,3,4,5,6,7,8,9,10]; let res = arr.reduce((prev, cur, index, arr) =>{/*四个参数:前一个存储的结果,当前,当前索引,当前数组*/ return prev+cur;//最终返回55 }); console.log(res);
- 例:
- arr.reduceRight() //从右往左
- for…of…:
- arr.keys() 数组下标
- arr.entries() 数组某一项
- 例:
let arr = ['apple','banana','orange','tomato']; for(let val of arr){ console.log(val); } for(let index of arr.keys()){ console.log(index); } for(let item of arr.entries()){ console.log(item); } for(let [key, val] of arr.entries()){ console.log(key,val); }
- Array.from:
- 作用: 把类数组(获取一组元素、arguments…) 对象转成数组
- 个人观点: 具备 length这个东西,就靠谱,就可以调用数组方法
- Array.of(): 把一组值,转成数组
例1:let arr = Array.of('apple','banana','orange'); console.log(arr);
- arr.find(): 查找,找出第一个符合条件的数组成员,如果没有找到,返回undefined
- arr.findIndex(): 找的是位置, 没找到返回-1
- arr.fill(填充的东西, 开始位置, 结束位置);
例:let arr = new Array(4); arr.fill('a', 1, 3); console.log(arr); //返回[empty, "a", "a", empty]
- arr.indexOf()
- arr.includes() ==>字符串中也有类似用法str.includes()
ES2017新增一个运算符:
- 幂运算
Math.pow(2,3) -->8
2 ** 3 -->8
- 复习一哈扩展运算符
let arr =[1,2,3]; let arr2 = [...arr]; let arr2 = Array.from(arr);
对象:
-
几个例子
+
let json ={ a:1, b:2, showA:function(){ return this.a; } showB:function(){ return this.b; } }
+
```
let json ={
a,
b,
showA(){ //个人建议: 一定注意,不要用箭头函数
},
showB(){
}
}```
-
new Vuex.Store({ state, mutation, types, actions });
-
new Vue({ router, App, vuex })
-
-
对象简介语法(相当有用):
- Object.is(): 用来比较两个值是否相等
- 例1:
Object.is('a','a'); 比较两个东西相等: == ===
- 例2:
Object.is(NaN, NaN);//true Object.is(+0, -0);//false
- 例1:
- Object.assign(): 用来合并对象
- 例1:
let 新的对象 = Object.assign(目标对象, source1, srouce2....)
- 例2:
function ajax(options){ //用户传 let defaults={ type:'get', header: data:{} .... }; let json = Object.assign({}, defaults, options); ..... }
- 例1:
- 用途:
- 复制一个对象
- 合并参数
- Object.is(): 用来比较两个值是否相等
ES2017引入:
- Object.keys()
- Object.entries();
- Object.values();
- let {keys, values, entries} = Object;
- 对象身上: 计划在ES2018引入…
let json = {a:3, b:4}; let json2 = {...json};
Promise: 承诺,许诺
- 作用: 解决异步回调问题
- 传统方式,大部分用回调函数,事件
ajax(url,{ //获取token ajax(url,()=>{ //获取用户信息 ajax(url, ()=>{ //获取用户相关新闻 }) }) })
- 语法:
let promise = new Promise(function(resolve, reject){ //resolve, 成功调用 //reject 失败调用 }); promise.then(res=>{ //then返回的结果还是一个promise对象,可以一直.下去 }, err=>{ })
- 例1:返回结果success
let a = 1; let promise = new Promise(function(resolve, reject){ if(a == 1){ resolve('yes'); } else{ reject('no'); } }) promise.then(res=>{ //这个res就是resolve传进来的参数 console.log(res); },err=> { //这个err就是reject传进来的参数 console.log(err); })
- 例1:返回结果success
- 本人用法:
new Promise().then(res=>{ }).catch(err=>{ //等价于上例中promise对于错误的处理 })
- Promise.resolve(‘aa’) :
将现有的东西,转成一个promise对象, resolve状态,成功状态,等价于:let promise = new Promise(resolve =>{ resolve('aaa') }); promise.then(res =>{ console.log(res); })
- Promise.reject(‘aaa’):
将现有的东西,转成一个promise对象,reject状态,失败状态,等价于:let promise = new Promise((resolve, reject) =>{ reject('aaa') }); promise.then(res =>{ console.log(res); }).catch(err => { console.log(err); })
- Promise.all([p1, p2, p3]):把promise打包,扔到一个数组里面,打包完还是一个promise对象
注意:必须确保,所有的promise对象,都是resolve状态,都是成功状态
例1:let a = Promise.resolve('a'); let b = Promise.resolve('b'); let c = Promise.resolve('c'); Promise.all([a, b, c]).then(res =>{ console.log(res); }) //返回数组['a' , 'b' , 'c']
- Promise.race([p1, p2, p3]): 只要有一个成功,就返回
例1:let a = Promise.resolve('a'); let b = Promise.reject('b'); let c = Promise.resolve('c'); Promise.race([a, b, c]).then(res =>{ console.log(res); }).catch(err=>{ // console.log(err); }) //返回a
- 模拟:用户登录 -> 用户信息
模块化:
-
js不支持模块化
ruby require python import
-
在ES6之前,社区制定一套模块规范:
Commonjs 主要服务端 nodeJs require('http') AMD requireJs, curlJs CMD seaJs
-
ES6出来,同意服务端和客户端模块规范:
import {xx} ddd Math.pow() Math.abs() import {pow, abs} from 'Math' 我自己瞎想
-
模块化:注意: 需要放到服务器环境
- 如何定义模块?
export 东西 export const a =12; export{ a as aaa, b as banana } export default .....
- 如何使用?
import import './modules/1.js'; import {a as a, banana, c} from './modules/2.js' import * as modTwo from './modules/2.js'; 使用模块: <script type="module"></script>
- 如何定义模块?
-
import: 特点
- import 可以是相对路径,也可以是绝对路径
import 'https://code.jquery.com/jquery-3.3.1.js';
- import模块只会导入一次,无论你引入多少次
- import ‘./modules/1.js’; 如果这么用,相当于引入文件
- 有提升效果,import会自动提升到顶部,首先执行
- 导出去模块内容,如果里面有定时器更改,外面也会改动,不想Common规范缓存
-
* import() 类似node里面require, 可以动态引入, 默认import语法不能写到if之类里面 返回值,是个promise对象 import('./modules/1.js').then(res=>{ console.log(res.a+res.b); });
- import 可以是相对路径,也可以是绝对路径
-
优点:
- 按需加载
- 可以写if中
- 路径也可以动态
程序中类
-
ES6
- 面向对象 ,类
- 属性
- 方法
- 函数模拟
- 例:
人: Person 属性: name 展示名字: showName Person.prototype.showName
-
ES5之前:
function Person(){ this.name='aaa'; } Person.prototype.showName=function(){}
-
ES6中变形:
- 例1:
class Person{ constructor(){ //构造方法(函数), 调用new,自动执行 this.name = 'aaa'; } //一定注意这里没有逗号 showName(){//注意这里没有function showName这样的形式 } }
- 例2:
const Person = class{} <===> class Person{}
- 例3:
let aa = "abc"; class Person{ contructor(name , age){ this.name = name; this.age = age; } [aa](){ console.log('aaaaaa'); } } let person = new Person('name', 17); person[aa]();
- 例4:
let aaa='aaa'; let bbb='ddd'; let json={ [aaa+bbb]:'welcome 51mmr.net' }
- 例1:
-
注意:
- ES6里面class没有提升功能,在ES5,用函数模拟可以,默认函数提升
- ES6里面this 比之前轻松多了
- 例1:
class Person{ constructor(){ this.name = 'Strive'; this.showName = this.showName.bind(this); //矫正this } showName(){ console.log('this:', this); return `名字为: ${this.name}`; } } let p1 = new Person(); let {showName } = p1; console.log(showName());
-
矫正this:
- fn.call(this指向谁, args1, args2…)
- fn.apply(this指向谁, [args1, args2…])
- fn.bind()
-
class里面取值函数(getter), 存值函数(setter)
例1:class Person{ constructor(){ } get aaa(){ return `aaa的属性`; } set aaa(val){ console.log(`设置aaa属性,值为:${val}`); } } let p1 = new Person(); p1.aaa='123'; console.log(p1.aaa);
-
静态方法: 就是类身上方法,父类.aaa();
例1:class Person{ constructor(){ } static aaa(){ return '静态方法'; } show(){ return '类'; } } let p = new Person(); console.log(p.show); console.log(Person.aaa());
-
父类Person,子类Student,继承
- 之前:
//父类 function Person(name){ this.name = name; } Person.prototype.showName = function(){ return `名字是: ${this.name}`; }; //子类 function Student(name,skill){ Person.call(this,name); //继承属性 this.skill = skill; } Student.prototype = new Person(); //继承方法 //调用 let stu1 = new Student('Strive','逃学'); console.log(stu1.showName());
- 现在: extends
class Student extends Person{ }
- 例1:
//父类 class Person{ constructor(name){ this.name = name; } showName(){ console.log('父类showName'); return `名字为: ${this.name}`; } } //子类 class Student extends Person{ constructor(name,skill){ super(name); this.skill = skill; } showName(){ super.showName(); //父级的方法执行 //TODO 做子级事情 console.log('子类里的showName'); } showSkill(){ return `哥们儿的技能为: ${this.skill}`; } } //调用 let stu1 = new Student('Strive','逃学'); console.log(stu1.showName());
- 例2:拖拽:两个小方块,第一个能拖拽,第二个继承第一个能拖拽的属性,并且移动位置不能超过屏幕
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>51牧码人――http://www.51mmr.net 专注[前端+Java],人才培养</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> .box{ width:100px; height:100px; background: red; position: absolute; top:0; } .left{ left:0; } .right{ right:0; } </style> <script> </script> </head> <body> <div id="div1" class="box left">DIV1</div> <div id="div2" class="box right">DIV2</div> <script> //普通拖拽 -- 父类 class Drag{ constructor(id){ this.oDiv = document.querySelector(id); this.disX = 0; this.disY = 0; this.init(); } init(){ this.oDiv.onmousedown = function(ev){ this.disX = ev.clientX - this.oDiv.offsetLeft; this.disY = ev.clientY - this.oDiv.offsetTop; document.onmousemove = this.fnMove.bind(this); document.onmouseup = this.fnUp.bind(this); return false; }.bind(this); } fnMove(ev){ this.oDiv.style.left = ev.clientX - this.disX+'px'; this.oDiv.style.top = ev.clientY - this.disY+'px'; } fnUp(){ document.onmousemove=null; document.onmouseup=null; } } //子类―― 限制范围 class LimitDrag extends Drag{ fnMove(ev){ super.fnMove(ev); //限制范围 if(this.oDiv.offsetLeft<=0){ this.oDiv.style.left =0; } } } //调用 new Drag('#div1'); new LimitDrag('#div2'); </script> </body> </html>
- 例1:
- 之前:
symbol:使用情况一般
- 用typeof检测出来数据类型:
symbol number string boolean Object undefined function
- 定义:let syml = Symbol(‘aaa’);
- 注意:
- Symbol 不能new
- Symbol() 返回是一个唯一值:坊间传说, 做一个key,定义一些唯一或者私有一些东
- symbol是一个单独数据类型,就叫 symbol, 基本类型(不能再拆分了)
- 如果symbol作为key,用for in循环,出不来
- 例:
let symbol = Symbol('aaa'); let json = { a : 'a', b : 'b', [symbol] : 'symbol', } for(let item in json){ console.log(item); }
generator函数(生成器)
- 箭头函数: () =>{}
- generator函数,解决异步深度嵌套的问题, async
- 语法:
function * show(){ yield } function* show(){ } function *show(){ }
- 定义:
function * gen(){ yield 'welcome'; yield 'to'; return '牧码人'; } let g1 = gen(); // 得到的结果是一个对象,g1是一个对象
- 调用:手动调用,麻烦:
let g1 = gen(); g1.next(); // {value:'welcome', done:false} g1.next(); // {value:'to', done:false} g1.next(); // {value:'牧码人', done:true}
- for … of 自动遍历 generator
function * gen(){ yield 'welcome'; yield 'to'; return 'lfy'; } let g = gen(); for(let item of g){ console.log(item); } //注意:return的东西,它不会遍历
- generator不仅可以配合 for … of … , 还可以:
- 解构赋值: let [a, …b] = gen();
- 扩展运算符: ‘…’ ===> console.log(…gen());
- Array.from(): console.log(Array.from(gen()));
- generator结合 axios数据请求:
- 例:
//https://api.github.com/users/itstrive function * gen(){ let val = yield 'aaa'; yield axios.get(`https://api.github.com/users/${val}`); } let g1 = gen(); let username = g1.next().value; //第一遍返回是aaa, //g1.next().value 得到的是一个promise对象 //console.log(g1.next(username).value); g1.next(username).value.then(res=>{ //将第一次返回结果的值传进去,作为gen中val的值,然后成功执行回调函数 console.log(res.data); });
关于异步
异步: 不连续,上一个操作没有执行完,下一个操作照样开始
同步: 连续执行,上一个操作没有执行完,下一个没法开始
2. 解决方案:
+ 回调函数
+ 事件监听
+ 发布/订阅
+ Promise对象
+ co…
+ ES2017,规定 async
读取文件 fs.readFile
```
const fs = require('fs');
//简单封装 fs封装成一个promise
const readFile = function (fileName){
return new Promise((resolve, reject) =>{
fs.readFile(fileName, (err, data) =>{
if(err) reject(err);
resolve(data);
});
});
}
```
异步的几种方法
- promise
readFile('data/a.txt').then(res=>{ console.log(res.toString()); return readFile('data/b.txt'); }).then(res=>{ console.log(res.toString()); return readFile('data/c.txt'); }).then(res=>{ console.log(res.toString()); })
- genrator
function * gen(){ yield readFile('data/a.txt'); yield readFile('data/b.txt'); yield readFile('data/c.txt'); } let g1 = gen(); g1.next().value.then(res=>{ console.log(res.toString()); return g1.next().value; }).then(res=>{ console.log(res.toString()); return g1.next().value; }).then(res=>{ console.log(res.toString()); })
- async
async function fn(){ let f1 = await readFile('data/a.txt'); console.log(f1.toString()); let f2 = await readFile('data/b.txt'); console.log(f2.toString()); let f3 = await readFile('data/c.txt'); console.log(f3.toString()); } fn();
aysnc
-
语法
async function fn(){ //表示异步,这个函数里面有异步任务 let result = await xxx //表示后面结果需要等待 }
-
async特点:
- await只能放到async函数中
- 相比genrator语义化更强
- await后面可以是promise对象,也可以数字、字符串、布尔
- async函数返回是一个promise对象
- 只要await语句后面Promise状态变成 reject, 那么整个async函数会中断执行
- 例
- 例1:async函数返回是一个promise对象
async function fn(){ throw new Error('Error出错了'); } fn().then(res=>{ console.log(res); }).catch(err=>{ console.log(err); })
- 例2:只要await语句后面Promise状态变成 reject, 那么整个async函数会中断执行
async function fn(){ await Promise.reject('出现问题了'); let a = await Promise.resolve('success'); console.log(a); } fn().then(res=>{ console.log(res); }).catch(err=>{ console.log(err); })
- 问题:为什么await Promise.reject(‘出现问题了’); 在then中直接能打出结果’出现问题了’,
而await Promise.resolve(‘success’); 结果为undefined
- 问题:为什么await Promise.reject(‘出现问题了’); 在then中直接能打出结果’出现问题了’,
- 例1:async函数返回是一个promise对象
-
如何解决async函数中抛出错误,影响后续代码:
- try{ }catch(e){}
例:async function fn(){ try{ await Promise.reject('wrong'); }catch(e){} let a = await Promise.resolve('right'); console.log(a); } fn().then(res=>{ console.log(res); },err=>{ console.log(err); })
- promise本身catch
例:await Promise.reject('出现问题了').catch(err=>{ console.log(err); }); let a = await Promise.resolve('success'); console.log(a);
- try{ }catch(e){}
-
个人建议大家:
try{ let f1 = await readFile('data/a.txt'); let f3 = await readFile('data/c.txt'); let f2 = await readFile('data/b.txt'); }catch(e){}
例:当这三个没什么必然关系的时候
//async async function fn(){ let [a,b,c] = await Promise.all([ //Promise.all([]) readFile('data/a.txt'), readFile('data/b.txt'), readFile('data/c.txt'), ]); console.log(a.toString()); console.log(b.toString()); console.log(c.toString()); } fn();
数据结构
- 数组
- json, 二叉树…
Set
-
set数据结构:类似数组,但是里面不能有重复值
let arr = ['a','b','a']; let arr = new Array();
-
set用法:
let setArr = new Set(['a','b']); setArr.add('a'); 往setArr里面添加一项 setArr.delete('b'); 删除一项 setArr.has('a') 判断setArr里面有没有此值 setArr.size 个数 setArr.clear(); 清空
-
for…of… 循环:
- for(let item of setArr){ //默认是values()
console.log(item);
} - for(let item of setArr.keys()){console.log(item);}
- for(let item of setArr.values()){}
- for(let [k,v] of setArr.entries()){}
-
setArr.forEach((value,index) =>{ console.log(value, index); }); let setArr = new Set().add('a').add('b').add('c');
- for(let item of setArr){ //默认是values()
-
set数据结构变成数组:[…set]
例:数组去重:let arr = [1,2,3,4,5,6,7,6,5,4,3,2,1,2,3,4,4]; let newArr = [...new Set(arr)]; console.log(newArr);