ES6詳細知識點

2020-08-11 17:43:49

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

安全整數:
安全整數:-(253-1)到253包含-(253-1)和253
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}