ES6详细知识点

234 阅读6分钟

前言:希望可以通过这篇文章,能够给你得到帮助。(感谢一键三连),前端小白不断升级打怪中...

1. let const

   {} // 块级作用域
   for if while // 都是块级作用域 

没有预解析,不存在变量提升 在代码块内,只要let定义变量,在之前使用报错(先定义,再使用)

function show(){
    console.log(a);
    let a = 3; //报错
}

不能重复定义变量(同一个作用域) for循环for循环里面是父级作用域,里面又一个作用域

for(let i=0;i<3;i++){ // 两个作用域
    let i= 'abc';
    console.log(i);
    // abc abc abc
}

暂时性死区 const 特性和let一样 const 常量不能修改 const定义完变量,必须有值,不能后赋值

var tmp = 123;
if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}
if (true) {
  // TDZ开始
  tmp = 'abc'; // ReferenceError
  console.log(tmp); // ReferenceError

  let tmp; // TDZ结束
  console.log(tmp); // undefined

  tmp = 123;
  console.log(tmp); // 123
}

对象引用可以修改 例如:

const arr = [1,2,2];
arr.push(3);
// 1,2,2,3
Object.freeze([1,2,3]) //不能修改
(function(){
})() //用来模拟作用域

2. 结构赋值

注意:左右两边,结构保持一致

let [a,b,c] = [12,5,6];
let [a='默认值',b,c] = [12,5];
let [a,b,c:'默认值'] = [12,5,null];  c = null
let a= 12;
let b= 5;
[a,b] = [b,a]; a = 5,b = 12
let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]

json 对象结构

let json = {
    name: 'xxx',
    age: 18
}
let {name,age} = json;
console.log(name,age);// xxx 18

let {name:n,age} = json; //n别名
let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"

let { baz } = { foo: 'aaa', bar: 'bbb' };
baz // undefined

如果变量名与属性名不一致,必须写成下面这样。


let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"

let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'
let obj = {
  p: [
    'Hello',
    { y: 'World' }
  ]
};

let { p, p: [x, { y }] } = obj;
x // "Hello"
y // "World"
p // ["Hello", {y: "World"}]

字符串的解构赋值 解析时候可以给默认值 传参也可以结构

const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
let {length : len} = 'hello';
len // 5

3. 字符串模板

优点:随意换行

`${}`
let name = 'xxx';
let age = 18;
let str = `这个人叫${name},年龄是${age}`

字符串方法 查找

indexOf('') // 返回索引位置
str.includes(要找的东西) //返回true/false
str.startswith() // 以xxx开头
str.endswith() // 以xxx结尾
str.repeat(n) // 重复多少次
str.padStart(整个字符常长度,填充的东西) // 往前填充
str.padEnd() //往后填充

4. 函数

函数默认参数

function show(x='默认值',y='默认值'){
    console.log(x,y);
};
show('','a');
show('b');

*结构

function show({x=0,0}={}){
    console.log(x,y);
};
show({x:1,y:7});
show();

函数参数默认已经定义,不能再使用let,const声明

function show(x=18){
    let x=101; //报错
}
show();

扩展运算符 Rest运算符 ... //扩展运算符 即展开又可以重置 展开数组

let arr = [1,2,3];
console.log(arr); //[1,2,3];
console.log(...arr);
// 1,2,3

合并

 function show(...a){
     console.log(a) //[1,2,3,4,5]
 }
 show(1,2,3,4,5)

类似

 function show(){
     let a = Array.prototype.slice.call(arguments);
     console.log(a); // [1,4,5,2,9,4]
 }
 show(1,4,5,2,9,4);

剩余运算符 展开数组 [1,2,3]->...[1,2.3]->1,2,3 重置 1,2,3-> ...1,2,3 -> [1,2,3] 剩余参数:必须放到参数最后

function show(a,b,...c){
    // a = 1,
    // b = 2,
    // c= [3,4,5]
}
show(1,2,3,4,5)
let arr = [1,2,3];
let arr2 = [...arr]; // [1,2,3]
或者 let arrs = Array.from(arr); // [1,2,3]
let str = 'a b c'; let arrs = Array.from(str); // ['a','b','c']

箭头函数 注意: 1.this问题,定义函数所在的对象,不再是运行时所在的对象 2.箭头函数没有arguments,用... 3.箭头函数不能当构造函数

 let show = () => 1;
 console.log(show()); // 1
	() => {
	    语句
	}
 let show = (a=12,b=8)=>{
     console.log(a);
     return a*b;
 }
 let json = {
     id: 1,
     show:function(){
         alert(this.id); // 1
     }
 }
 json.show();
 let json = {
     id: 1,
     show:function(){
         setTimeout(function(){
         alert(this.id); // undefined
         },200)
         //setTimeout是用window执行的,
         window没有id
     }
 }
 json.show();
var id = 10;
let id = 10; //如果是let定义也是undefined
 let json = {
     id: 1,
     show:function(){
         setTimeout(function(){
         alert(this.id); // 10
         },200)
     }
 }
 json.show();
let json = {
     id: 1,
     show:function(){
         setTimeout(()=>{
            alert(this.id); // 1
         },200)
     }
 }
 json.show();
var id= 6;
let json = {
    id: 1,
    show:function(){
        setTimeout(()=>{
            let id = 10;
            alert(this.id); // 1
        },200)
    }
}
json.show();
var id= 6;
let json = {
    id: 1,
    show:()=>{
	    alert(this.id) // 6
        setTimeout(()=>{
            let id = 10;
            alert(this.id); // 6
        },200)
    }
}
json.show();
let id= 6;
let json = {
    id: 1,
    show:()=>{
	    alert(this.id) //undefined
        setTimeout(()=>{
            let id = 10;
            alert(this.id); // undefined
        },200)
    }
}
json.show();

5. 数组

for循环 2.while / /es5新增 (forEach,map,filter,some,every,reduce,reduceRight)

arr.forEach()

 // 以下他们可以接受两个参数(循环回调函数,this指向谁)
let arr=[1,2,3];
for(let i = 0;i < arr.length; i++){
    
}
arr.forEach()//代替普通for循环

arr.forEach(function(val,index,arr){
    console.log(this)//456 this指向456
},456);

// 箭头形式
arr.forEach((val,index,arr)=>{
        console.log(this)// this指向window
},123);
// 箭头函数this指向定义时 window

arr.map() 非常有用,做数据交互,‘映射’ 正常情况下,需要配合return,返回是一个新数组,如果没有return,相当于forEach 注意:平时用map,一定要有return;

let newArr = arr.map((item,index,arr)=>{
    return item;
});
newArr = [1,2,3];
arr.filter()
let arr = [{title:'111',hot: false},
{title: '222',hot:true},{title:'333',hot:false}]
let newArr = arr.filter((item,index,arr){
    return item.hot === true;
});
console.log(newArr);
// [{title: '222',hot:true}]

arr.some() 类似查找,数组里面某一个元素符合,返回true //过滤 过滤一些不合格,如果回调函数返回true,就留下来

let arr = ['aa','bb','cc'];
let back = arr.some((item,index,arr)=>{
    return item === 'aa'
});
console.log(back)//true

arr.every() 数组里面所有的元素都要符合条件,才返回true

arr.reduce() 从左往右 //求数组的和,阶乘 接收的参数与其他不同

let arr = [1,2,3,4,5,6,7,8,9,10];
let res = arr.reduce((prev,cur,index,arr)=>{
    return prev+cur;
});
// 55  prev上一个结果,cur当前值

arr.reduceRight() //从右往左

// for----of
let arr = ['aaa','bbb','ccc'];
for(let val of arr){
    console.log(val) // 
    aaa bbb ccc
}
for(let index of arr.keys()){
    console.log(index) // 
    0 1 2
}

for(let item of arr.entries()){
    console.log(item) // 
    [0,'aaa']  item[0] 1 item[1] aaa
    [1,'bbb']
    [2,'ccc']
}
for(let [key,val] of arr.entries()){
    console.log(key,val);//
    0 aaa
    1 bbb
    2 ccc
}

Array.from() 作用:把类数组(获取一组元素,arguments....)对象转成数组 个人观点:具备length这东西就靠谱

[].slice.call(arr) //ES5之前的方法 Array.from(arr)//ES6方法 [...arr]//ES6方法
let str = "stri";
Array.from(str) // ['s','t','r','i'];

let json = {
    0:'aa',
    1: 'bb',
    2: 'cc'
}

Array.from(json) //不行

let json = {
    0:'aa',
    1: 'bb',
    2: 'cc',
    length: 3
}

Array.from(json) // ['aa','bb','cc']

let json = {
    0:'aa',
    1: 'bb',
    2: 'cc',
    length: 2
}

Array.from(json) // ['aa','bb']

Array.of() 把一组值转成数组

 Array.of('aa','bb')
 // ['aa','bb']

arr.find() 查找找出第一个符合条件的数组成员,如果没有找到,返回undefined

let arr = [23,59,900,200];
let res = arr.find((val,index,arr)=>{
    return val > 100; // 900
});

arr.findIndex() 找的是位置,没找到返回-

let arr = [23,59,900,200];
let res = arr.find((val,index,arr)=>{
    return val > 100; // 2
});

arr.fill(填充的东西,开始位置,结束位置)

 let arr = new Array(10);
 arr.fill('默认值')
 ['默认值',...]

arr.includes() 在ES2016里面新增 类似 arr.indexOf()返回索引

let arr = [1,2,3];
arr.includes(1) // true
let a=new Set([1,2,3]);
let b=new Set([4,3,2]);
//交集
let union= [...new Set([...a,...b])];
console.log(union);
//并集
let intersect= [...new Set([...a].filter(x=> b.has(x)))];
console.log(intersect);
//差集
let difference= [...new Set([...a].filter(x=> !b.has(x)))];
console.log(difference);

对象

let name='aaa';
let json={
    name,
    show(){//个人建议,一定注意,不要箭头函数
     return this.name //'aaa'
        
    }
}
let name='aaa';
let json={
    name,
    show()=>{//个人建议,一定注意,不要箭头函数
     return this.name //没值
        
    }
}

Object.is() 用来比较两个值是否相等

 console.log(Object.is(NaN,NaN)//true
 console.log(+0 == -0)//true
 console.log(Object.is(+0,-0))//false

Object.assign(目标对象,source1,source2) 1.用来合并对象 用途: 1.复制一个对象 2.合并参数

let json = {a:1};
let json2 = {b:2};
let json3 = {c:3};

Object.assign({},json,json2,json3);
//  {a:1,b:2,c:3}
let json4 = {b:2,a:2};
Object.assign({},json4,json3);
//{a:2,b:2,c:3}
//2.
let arr = ['aa','bb','cc'];
Object.assign([],arr);
//['aa','bb','cc']

Object.keys() Object.values() Object.entries()

let json = {
    a:1,
    b:2,
    c:3
}

for(let key of Object.keys(json)){
    console.log(key) // a b c
}

for(let value of Object.values(json)){
    console.log(value) // 1 2 3
}

//或者这么写 解构
let {keys,values,entries} = Object;
for(let item of entries(json)){
    console.log(item)
    // ['a':1] ['b':2] ['c':3]
}
for(let [key,value] of entries(json)){
    
}

对象身上:计划ES2018引入 ... 扩展复制等

 let {x,y,...z} = {x:1,y:2,a:3,b:4}
 // x:1 
    y:2 
    {a:3,b:4}
    
let json = {a:3,b:4};
let json2 = {...json};
// a:3  b:4

6. Promise

作用:解决异步问题 传统方式,大部分用回调函数,事件

ajax(url,{ //获取token
  ajax(url,{ //获取用户信息
       .... //获取用户相关信息
  })
})

语法

let promise = new Promise(function(resolve,reject){
    // resolve 成功调用
    // reject  失败调用
});

promise.then(res=>{
    
},err=>{
    
});
promise.catch(err=>{//reject,发生错误别名
    console.log(err)
});

或者
promise.then(res=>{
    
}).catch(err=>{
    
});
 let a = 10;
 let promise = new Promise((resolve,reject){
     if(a===10){
         resolve('成功')
     }else{
         reject('失败')
     }
 });
 promise.then(res=>{
     console.log(res);
 },err=>{
     console.log(res);
 });

Promise.resolve('aa'):将现有的东西,转成一个Promise对象,resolve状态,成功状 态 Promise.reject('bb'):将现有的东西,转成一个Promise对象,reject状态,失败状态

let p = Promise.resolve('aa');
p.then(resolve=>{
    resolve('aaa')
})

Promise.all([p1,p2,p3]); 把Promise打包,扔到数组里面,打包完还是一个 Promise对象必须确 保,所有的promise对象,都是resolve状态,都是成功的状态

 let p1= Promise.resolve('aaa');
 let p2 = Promise.resolve('bbb');
 let p3= Promise.resolve('ccc');
 
 Promise.all([p1,p2,p3]).then(res=>{
     let [res1,res2,res3] = res;
     console.log(res1,res2,res3)
 })

Promise.race([p1,p2,p3]); 只要有一个resolve,就返回

 let p1= Promise.reject('aaa');
 let p2 = Promise.reject('bbb');
 let p3= Promise.resolve('ccc');
 
 Promise.all([p1,p2,p3]).then(res=>{
     let [res1,res2,res3] = res;
     console.log(res1,res2,res3)
 }).catch(res=>{
     
 });

用户登录->用户信息

let status = 1;
let userLogin = (resolve,reject)=>{
    setTimeout(()=>{
        if(status ===1){
           resolve({data:'登录成功,age:xx})
        }else{
            reject('失败')
        }
    },2000)
}

let getUserInfo = (resolve,reject)=>{
    setTimeout(()=>{
        if(status ===1){
           resolve({data:'获取用户信息,age:xx})
        }else{
            reject('失败')
        }
    },1000)
}

new Promise(userLogin).then(res=>{
    console.log('用户登录成功');
    console.log(res);
    return new Promise(getUserInfo);
}).then(res=>{
    console.log('获取用户信息成功')
    console.log(res);
})

//用户登录成功
// {data: xxx}
// 获取用户信息成功
// {data: '获取用户信息'}

7. 模块化

js不支持模块化 在ES6之前,社区制定一套模块规范 Common.js 主要服务端 node.js require('http') AMD requireJs ,curlJs ,seaJs ES6出来,同意服务端和客户端模块规范 import {xxx} ddd;

使用模块( 注意放到服务器环境 ) 1.如何定义模块 export const a = 1; 2.如何使用 import './module/1.js'

<script type ="module">
    import './module/1.js'
</script>
1.js
console.log('模块加载了')
export const a = 1;
或者
const a = 1;
const b = 2;
export {
    a,
    b as c // 别名
}

import特点 :可以是相对路径,也开始绝对路径

import {a as x, c} from './module/1.js';

import 模块只会导入一次,无论引入多少次

  1. import './module/1.js' 相对于引入文件
  2. 有提升效果,import会自动提升到顶部,首先执行
  3. 导出去模块内容,如果里面有定时器更改,外面也会改动,不像Common规范缓存
  4. import() 类似node里面require,可以动态引入;
  5. 默认import语法不能写到if之类里面 返回值是个Promise对象
  6. 优点: 按需加载 可以写if中 路径也可以动态
<script type ="module">
    import {a as x, c} from './module/1.js';
    console.log(x,c) // 
    //模块加载了
    1  2
    
    
    import * as mode from './module/1.js';
    mode.a // 1
</script>


exprot default a = 12; // 不用{}需要定义default
import a from './module/2.js';
 a // 12
 
 
 
 3.js
 
 const a= 12;
 const b = 5;
 或者import {a,b} from './module/1.js';
 const sum = ()=>{
     return a+b;
 }
 const show = ()=>{
     return 'aaa'
 }
 class Person {
     constructor(name,age){
         this.name = name;
         this.age = age;
     }
     showName(){
         return this.name;
     }
 }
 export {
     a,b,sum,show
 }
 export default {
     Person
 }
 
  console.log(a,b) // 12 5 // 有提升效果
 import mode,{show,sum,a,b} from './module/3.js';
 
 let p = new node.Person('xx');
 show(); //aaa
 sum(); // 17
 console.log(a,b) // 12 5
 p.showName() // xx

import() 例子

 let a = 12;
 if(a===12){
     import {a} from './module/1.js';
 }else{
     import {b} from './module/2.js';
 }
 // 错误的
 
 import('./module/1.js').then(res=>{
     console.log(res.a) // 12
 })

返回值是个Promise对象 优点: 1.按需加载 2.可以写if中 3.路径也可以动态 Promise.all()

Promise.all(['./1.js','./2.js']).then([mode1,mode2])=>{
    
})

ES2017 加 async wait

async function main(){
     const mode1 = wait import('./1.js');
      const mode2 = wait import('./1.js');
      const [m1,m2] = wait Promise.all([mode1,mode2]).then([import('./1.js'),import('./2.js')]);
      console.log(m1,m2);
 }
 main();

'use strict' 严格模式

8. class

ES5之前是通过函数模拟

function Person(name,age){
    this.name = name;
    this.age = age;
}
Person.prototype.showName = function(){
    return this.name;
}
或者
object.assign(Person.prototype,{
    showName(){
        return this.name;
    },
    showAge(){
        return this.age;
    }
});
let p = new Person('strive',18);
p.showName(); // strive

ES6写法: 1.class没有提升功能,没有预解析,在ES5用函数模拟可以,默认函数提升 2.this比之前轻松多了

class Person{
    //构造函数,调用new ,自动执行
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    showName(){
        return this.name;
    }
}
new Person('strive',age);

或者这么定义 不推荐使用
const Person = class{
        //构造函数,调用new ,自动执行
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    showName(){
        return this.name;
    }
}
let show = 'other';
let show1 = 'uuu';
const Person = class{
        //构造函数,调用new ,自动执行
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    showName(){
        return this.name;
    },
    show(){
        console.log('xxx');
    },
    [show1](){
        console.log('yyy');
    }
    [show+show1](){
        
    }
}
let p = new Person('strive',18);
p.show() // 'xxx'
p.show1() // undefined
p[show1]() // 'yyy'

矫正this 1.fn.call(this指向,arg1,arg2...) 2.fn.apply(this指向,[arg1,arg2...]); 3.fn.bind();

  class Person{
      constructor(){
          this.name = 'strive';
          this.showName = this.showName.bind(this);
      }
      showName(){
          return this.name;
      }
  }
  let p =new Person();
  let {showName} = p;
  console.log(showName())//报错
   可以用 this.showName = this.showName.bind(this); //矫正

class里面取值函数(getter),赋值(setter)

 class Person(){
     constructor(){
         
     }
     get aaa(){
         return `aaa的属性`
     }
     set aaa(val){
         console.log(val) //111
     }
     
 }
 let p = new Person();
 p.aaa = '111';
 console.log(p.aaa)//111的属性

静态方法:就是类身上的方法

static fn(){}

静态方法可以由子类继承

class Person(){
    constructor(){
        
    }
    showName(){
        
    }
    static show(){
        return '这是静态方法'
    }
}
let p = new Person();
p.showName();
Person.show();

父类子类 继承之前的方法

//父类
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 stu = new Student('strive','逃学');
stu.showName();

ES6继承 extends

// 父类
 class Person(){
     constructor(name){
         this.name = name;
     }
     showName(){
         console.log('父类')
     }
 }
// 子类
 class Student extends Person{
     constructor(name,skill){
         super(name);//父类构造函数
         this.skill = skill;
     }
     showName(){
         super.showName()//父类方法执行
         console.log('子类')
     }
     show(){
         console.log(this.name,this.skill)
     }
 }
 let stu = new Student('xxx','yyy');
 stu.skill // yyy
 stu.show() // xxx yyy
 stu.showName(); // 父类 子类

拖拽

<div id="div1"></div>
<div id="div2"></div>
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.dixY = 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.onmouseuo = null;
  }
}
//子类
class LimitDrag extends Drop{
    fnMove(ev){
        super.fnMove(ev);
        //限制范围
        if(this.oDiv.offsetLeft <= 0){
           this.oDiv.style.left = 0; 
        }
    }
}
//new Drag('#div1'); //能拖出去
new LimitDrag('#div2');//限制拖出去

9. Symbol

数据类型

// number string boolean Object undefined function
// 用typeof 检测出来数据类型
Symbol
new Number(12)

Symbol使用一般 注意: 1、Symbol不能new 2、Symbol()返回是一个唯一值(房建传说,做一个key,定义一些唯一或者私有) 3、Symbol是一个单独数据类型,就叫Symbol基本类型 4、如果Symbol作为key,用for in 循环不出来

let syml = Symbol('aaa);

let syml = Symbol('strive);
let json = {
    a: 'aa',
    [symbol]:'bbb'
}
json[a] //aa
json[symbol] //bbb

for(let key in json){
    console.log(key) //a     4、如果Symbol作为key,用for in 循环不出来
}

10. generator函数

解决异步问题,深度嵌套的问题 语法

function * show(){
    yield
}

function * show(){
    yield 'aaa'
    yield 'bbb'
    return 'ccc'
}
//调用
let sh = show()
console.log(sh) // 返回对象
console.log(sh.next())//{value: "aaa", done:false}
console.log(sh.next())//{value: "bbb", done:false}
console.log(sh.next())//{value: "bbb", done:true}
console.log(sh.next())//{value: undefined, done:true}

//以上调用,手动调用,麻烦

for...of自动遍历generator,return的东西。它不会遍历
for(let val of sh){
    cosole.log(val)
}
// generator不仅可以配合for...of还可以结构赋值

function * show(){
    yield 'aaa'
    yield 'bbb'
    yield 'ccc'
    return 'ddd'
}
let [a,b,c,d] = show();
// aaa bbb ccc undefined

let [a,...b] = show();
//aaa ['bbb', 'ccc']
// 扩展运算符
...show() // aaa bbb ccc

Array.from(show()) ['aaa','bbb','ccc']

generator结合axios数据请求

 function * gen(){
     let val = yeild 'strive';
     yield axios.get(''http://.../${val});
 }
 let g = gen();
 let userName = g.next().value;
 //g.next(userName).value -->promise
 g.next(userName).value.then(res=>{
     console.log(res.data);
 });

异步:不连续,上一个操作没有执行完,下一个操作照样开始。 同步:连续执行,上一个操作没有执行完,下一个没法开始。 关于异步,解决方案: 1.回调函数 2.事件监听 3.发布/订阅 4.Promise对象

ES2017,规定async

11. async

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.text').then(res=>{
console.log(res.toString());//aaa
return readFile('data/b.txt');
}).then(res=>{
    console.log(res.toString())// aaa bbb
})

genertaor

function *gen(){
    yield readFile('data/a.txt');
    yield readFile('data/b.txt');
    yield readFile('data/c.txt');
}
let g = gen();
g.next().value.then(res=>{
    console.log(res.toString());
    return g.next().value;
}).then(res=>{
    console.log(res.toString());
    return g.next().value;
}).then(res=>{
    console.log(res.toString()) // aaa bbb ccc
})

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());
}

async特点: 1.await 只能放到async函数里 2.相比generator语义化更强 3.await后面可以是promise对象,也可以数字、字符串、布尔 4.async函数返回是一个promise对象 5.只要await语句后面promise状态变成reject,那么整个async函数中断执行 如何解决async函数中抛出错误,影响后续代码 a)try{ }catch(e){ } b)promise本身catch 个人建议:只要await 都try catch

async function fn(){ //表示异步,这个函数里面有异步任务
    await  //表示后面结果需要等待
}
//async
async function fn(){
    return 'aaa';
}
fn() //Promise
fn().then(res=>{
    console.log(res) // aaa
})
async function fn(){ //表示异步,这个函数里面有异步任务
    await  //表示后面结果需要等待
}
//async
async function fn(){
   throw new Error('出错了')
}
fn() //Promise
fn().then(res=>{
    console.log(res)
}),err=>{
    console.log(err);//出错了
}
// 或者
fn().then(res=>{
    console.log(res)
}).catch(err=>{
    console.log(err); //出错了
})

async function fn(){
  awiat Promise.reject('出错了')
  //可以try  catch
  try{
      awiat Promise.reject('出错了')
  }catch(e){
      
  }
  //也可以promise  catch
  awiat Promise.reject('出错了').catch(err=>{
      console.log(err)
  })
  let a = await Promise.resolve('aaa');
}
 fn().then(res=>{
     console.log(res) // aaa
 }).catch(err=>{
     console.log(err)
 })

12. Set 和WeakSet

数据结构:数组,json,二叉树.... set数据结构,类似数组,但里面不能有重复值 用法:new Set(['a','b']); key和value一样 如果 new Set({})//报错 但通过add方式是可以的{}

let arr = new Set(['a','b','c']);
//{'a','b','c'}

let setArr = new Set();
setArr.add('a') //添加
setArr.add('b') //添加
setArr.delete('a')//删除
setArr.has('a') // false //判断里面有没有此值
setArr.size() //个数
setArr.clear()//清除所有
// 循环
for...of
for(let item of setArr){//默认是values
    // a b
}
for(let item of setArr.keys()){
    // a b
}
for(let item of setArr.values()){
    // a b
}
for(let item of setArr.entries()){
    // ['a':'a'] ['a':'b']
}
for(let [k,v] of setArr.entries(){
    k->a v->a
}
setArr.forEach(value,index)=>{
    value->a index->a
});

// 去重
let arr = [1,2,3,2,1];
let s = new Set(arr);
Array.form(s);
// 或者
[...new Set(arr)];

set数据结构变成数组
[...set]
想让set使用数组的map filter先变成数组
let arr1 = [...new Set(arr)];//set->arr
let set = new Set(arr1)//arr->set

WeakSet()存储json 初始里面添加东西是不行的,最好用add添加 WeakSet({})这样写不行报错 weakSet没有size,没有clear,有add,has ,delete

let json = {
    a:1,
    b:2
}
let wSet = new WeakSet();
wSet.add(json);//{a:1,b:2}

13. Map和WeakMap

类似json,但是json的键(key)只能是字符串 map的key可以是任意类型 new Map();

let map = new Map();
let json = {
    a:1,
    b:2
}
map.set('a','aaa');
map.set(json,'aaa');
map.set('b',json); //设置值
map.get(json) //获取 'aaa'
map.delete(key)//删除
map.has(key)//判断有没有
map.clear()//清除所有

//循环:
for(let [key,val] of map){//默认是entries
    
}
for(let key of map.keys()){
    
}
for(let val of map.values()){
    
}
map.forEach((value,key)=>{
    // aaa a
}

WeakMap(): key只能是对象

let wMap = new WeakMap();
let json = {
    a:1,
    b:2
}
wMap.set(json,'aaa');
wMap.set('aa','nn');//报错

14. 数字变化和Math新增的东西

数字(数值)变化

// 二进制:(binnary) 0b开头
let a = 0b010101;
a//21
// 八进制:(octal) 0o开头
let a = 0o666;
a // 
//十六进制:


// 数字变化
let a = 2;
isNaN(a)//false

Number.isNaN(a)//false
Number.isFinite(a)//true //判断是不是数字
Number.isInteger()//判断数字是不是整数
Number.parseInt()
Number.parseFloat()

安全整数: 安全整数:-(2^53-1)到2^53包含-(2^53-1)和2^53 Number.isSafeInteger()

let a = 2**53
Number.isSafeInteger(a) //安全整数
Number.MAX_SAFE_INTEGER //最大安全整数
Number.MIN_SAFRE_INTEGER //最小安全整数

Math:
Math.abs() Math.sqrt() .... 新增 Math.trunc()//截断

Math.trunc(4.56)//4 截断截取,只保留整数部分

Math.sign(-50) //判断一个数到底是正数、复数、0
-50->-1
50->1
0->0
-0->-0
其他值->NaN

Math.cbrt(27) // 3 计算一个数立方根

15. ES2018

命名匹配

let str = "2018-03-20";
let reg = /(\d{4})-(\d{2})-(\d{2})/;
let dateArr = str.match(reg);
let year = dateArr[1]; //2018
let month = dateArr[2];//03
let day = dateArr[3];//20

1.命名捕获

// 语法:(?<名字>)
let str = '2018-03-20';
let reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
let {year,month,day} = str.match(reg).groups;
// 2018  03 20

反向引用:

// \1 \2 $1 $2
// 反向引用命名捕获:
// 语法:\k<名字>
let reg = /^(?<strive>welcome)-\k<strive>$/;
reg.test('a-a'); //false
reg.test('welcome-welcome')//true
let reg = /^(?<strive>welcome)-\k<strive>$-\1$/;
reg.test('welcome-welcome-welcome')//true

2.替换

// $<名字>
let str = '2018-03-20';
let reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
str.replace(reg,'$<year>/$<month>/$<day>')
//str-> 2018/03/20
str.replace(reg,'$<day>/$<month>/$<year>')
//20/03/2018
str.replace(reg,(...args)=>{
    let {year,month,day} = args[args.length-1];
    return `${year}/${month}/${day}`
})

dotAll模式----s 之前 '.'在正则里表示匹配任意东西,但是不包括\n

let reg = /^\w+.\w+$/s;
let str = 'welcome-51mmr';
let str2 ='welcome\n51mmr'; //true
console.log(reg.test(str));//true

标签函数

function fn(){
    
}
fn();//普通函数调用
function fn(args){
    console.log(args);//['welcome',row:Array[1]]
    return args[0].toUpperCase();
}
fn`welcome` //WELCOME

16. Proxy

代理:扩展(增强)对象一些功能: 作用:比如vue中拦截 预警、上报、扩展功能、统计、增强对象等 proxy是设计模式一种,代理模式 语法:

new Proxy(target,handle)
new Proxy(被代理的对象,对代理的对象做什么操作)
handle
{
    set(){},//设置的时候干的事
    get(){},//获取干的事
    deleteProperty(){},//删除 'xxx' in target
    has(){},//问你有没有这个对象
    apply(){},// 调用函数处理
    ....
}

例子

let obj = {
    name: 'strive'
}
let newObj = new Proxy(obj,{
    get(target,property){
        return target[property]
    }
})
newObj.name // strive

访问一个,访问一个对象身上属性,默认不存在给underfined, 希望如果不存在错误(警告)信息

let newObj = new Proxy(obj,{
    get(target,property){
        if(property in target){
            return target[property];
        }else{
            console.warn(`${property}不在属性上`)
        }
    }
})

DOM.div()

const DOM = new Proxy({},{
    get(target,property){
        //property DOM.xxx里面的xxx
        return function(attr={},...chidlen){
            const el = document.createElement(property);
            for(let key of Object.keys(attr)){
                el.setAttribute(key,attr[key]);
            }
            for(let child of children){
                if(tyoeof child === 'string'){
                    child = document.createTextNode(child);
                }
                el.appendChild(child);
            }
            return el; //<div id="div1" class="aaa">我是divhhh</div>
        }
    }
});
let oDiv = DOM.div({id:'div1',class:'aaa'},'我是div','hhh');

set()设置拦截

let obj = new Proxy({},{
  set(target,property,value){
      if(property == 'age'){
          if(!Number.isInteger(value)){
              throw new TypeError('年龄必须为整数');
          }
          if(value>200){
              throw new RangeError('年龄超标了');
          }
      }
      target[property] = value;
  }
})
obj.a =123;
obj.age = 202;//

deleteProperty()删除
has()
let json = {
    a:1,
    b:2
}
let newJson = new Proxy(json,{
    deleteProperty(target,property){
        delete target[property];
    },
    has(target,property){
        return property in target;
    }
});
'a' in newJson // true
delete newJson.a; // {b:2}

Reflect反射 Object.xxx语言内部方法 Object.defineProperty放到Reflect对象身上,通过Reflect对象身上直接拿到语言内部对象

apply()拦截方法
function fn(){
    return '我是函数';
}
let newFn = new Proxy(fn,{
    apply(){
        return '函数吗?'
    }
});
newFn(); //函数吗 fn被拦截里面内容不执行

Reflect反射
Reflect.apply(调用的函数,this指向,参数数组)
fn.call()
fn.apply()类似
function sum(a,b){
    return a+b;
}
let newSum = new Proxy(sum,{
    apply(target,context,args){ //sum函数,this指向,参数数组
        return Reflect.apply(...arguments);
    }
})
newSum(2,3); //5

Math.cell(4.5)//5
Reflect.apply(Math.cell,null,[9.8])//10

function show(...args){
    console.log(this);
    console.log(args);
}
show(1,2,3)// Window [1,2,3]
show.call('abc',[1,2,3])// -->abc   [1,2,3]
show.apply('abc',[1,2,3])//--> abc [1,2,3]
Reflect.apply(show,'aaa',[1,2,3])// -->aaa [1,2,3]

//Object.xxx语言内部方法
//Object.defineProperty放到Reflect对象身上,
//通过Reflect对象身上直接拿到语言内部对象
'assign' in Object
Reflect.has(Object,'assign')//true

let json = {
    a:1,
    b:2
}
delete json.a // {b:2}
Reflect.deleteProperty(json,'a')//{b:2}