Javascript ES6-11

RollsRoycewk發表於2020-11-09

ECMS相關介紹

什麼是ECMA

ECMA(European Computer Manufacturers Association)中文名稱為歐洲計算機制

造商協會,這個組織的目標是評估、開發和認可電信和計算機標準。1994 年後該

組織改名為 Ecma 國際

什麼是ECMAScript

ECMAScript 是由 Ecma 國際通過 ECMA-262 標準化的指令碼程式設計語言。

什麼是ECMA-262

Ecma 國際制定了許多標準,而 ECMA-262 只是其中的一個,所有標準列表檢視

http://www.ecma-international.org/publications/standards/Standard.htm

ECMA-262歷史版本

ECMA-262(ECMAScript)歷史版本檢視網址

http://www.ecma-international.org/publications/standards/Ecma-262-arch.htm

  • ES6 開始,每年釋出一個版本,版本號比年份最後一位大 1

誰在維護 ECMA-262

TC39(Technical Committee 39)是推進 ECMAScript 發展的委員會。其會員都是

公司(其中主要是瀏覽器廠商,有蘋果、谷歌、微軟、因特爾等)。TC39 定期

召開會議,會議由會員公司的代表與特邀專家出席

ES6相容性

  • ES6 的版本變動內容最多,具有里程碑意義

  • ES6 加入許多新的語法特性,程式設計實現更簡單、高效

  • 相容性

    http://kangax.github.io/compat-table/es6/

ECMAScript 6

let變數宣告以及特性

- 宣告物件型別使用 const,非物件型別宣告選擇 let

變數不能重複宣告

//宣告變數
        // let a;
        // let b,c,d;
        // let e = 100;
        // let f = 521, g = 'iloveyou', h = [];

        //1. 變數不能重複宣告
        let star = '羅志祥';
        let star = '小豬';
        //Identifier 'star' has already been declared

塊級作用域

  • 之前作用域: 全域性, 函式, eval(eveal,es5嚴格模式才出現)
  • 現在引入塊級作用域if else while for 都是塊級作用域
 // if else while for 都是塊級作用域
           {
                  girl = '周揚青';
           }
           console.log(girl);
        //girl is not defined

### 不存在變數提升

		console.log(song);
        let song = '戀愛達人';
 // Cannot access 'song' before initialization

不影響作用域鏈

 {
            let school = 'wangkai';
            function fn(){
                console.log(school);
            }
            fn();  //wangkai
        }

const宣告常量以及特點

  • 值不能修改的量叫常量

  • 宣告常量

     const SCHOOL = '你好啊';
            console.log(SCHOOL)  //你好啊
    

一定要賦初始值

 const A;
        //Missing initializer in const declaration

一般常量使用大寫(潛規則)

onst a = 100;

常量的值不能修改

 const SCHOOL = '你好啊';
        SCHOOL = 'ABCD';
        // console.log(SCHOOL)  //Assignment to constant variable.

塊級作用域

 {
            const PLAYER = 'UZI';
        }
        console.log(PLAYER);
        //PLAYER is not defined

改物件不會報錯

  • 對於陣列和物件的元素修改, 不算做對常量的修改, 不會報錯
  const TEAM = ['UZI','MXLG','Ming','Letme'];
        // TEAM.push('Meiko');

變數的解構賦值

  • ES6 允許按照一定模式從陣列和物件中提取值,對變數進行賦值,這被稱為解構賦值。

陣列的解構

 const F4 = ['小瀋陽','劉能','趙四','宋小寶'];
        let [xiao, liu, zhao, song] = F4;
        console.log(xiao); //小瀋陽
        console.log(liu); //劉能
        console.log(zhao); //趙四
        console.log(song); //宋小寶

### 物件的解構

 const zhao = {
            name: '趙本山',
            age: '不詳',
            xiaopin: function(){
                console.log("我可以演小品");
            }
        };

        let {name, age, xiaopin} = zhao;
        console.log(name); //趙本山
        console.log(age);  //不詳
        console.log(xiaopin); 
        //ƒ (){ console.log("我可以演小品");}

        // xiaopin(); //我可以演小品

        // 以前:zhao.xiaopin();
        //     zhao.xiaopin();
        //     zhao.xiaopin();
        //     zhao.xiaopin(); //我可以演小品

        // 現在:
        let {xiaopin} = zhao;  //我可以演小品
        xiaopin();

模板字串

``

  • ES6引入了新的宣告方式``
  • 以前: ''" "
let str = `我也是一個字串哦!`;
console.log(str, typeof str);

內容中可以直接出現換行

let str = `<ul>
                    <li>沈騰</li>
                    <li>瑪麗</li>
                    <li>魏翔</li>
                    <li>艾倫</li>
                    </ul>`;
        console.log(str)
                     // <ul>
                     //<li>沈騰</li>
                     //<li>瑪麗</li>
                     //<li>魏翔</li>
                     //<li>艾倫</li>
                     //</ul>

變數拼接

let lovest = '魏翔';
        let M = '呵呵呵'
        let out = `${lovest}是我心目中最搞笑的演員${M}!!`;
        console.log(out);
        // 魏翔是我心目中最搞笑的演員呵呵呵!!

簡化物件寫法

  • ES6 允許在大括號裡面,直接寫入變數和函式,作為物件的屬性和方法。這樣的書寫更加簡潔
 let name = '尚矽谷';
        let change = function(){
            console.log('我們可以改變你!!');
        }

        const school = {
            name,  //屬性名和變數名一樣可以省略一個
            change,
            improve(){    //省略了function和:
                console.log("我們可以提高你的技能");
            }
        }

        console.log(school);
        //{name: "尚矽谷", change: ƒ, improve: ƒ}

箭頭函式

宣告一個箭頭函式

  • ES6 允許使用「箭頭」(=>)定義函式。
//宣告一個函式
        // let fn = function(){

        // }    //以前

        let fn = (a,b) => {
            return a + b;
        }

        //呼叫函式
        let result = fn(1, 2);
        console.log(result);  //3

箭頭函式的this

箭頭函式適合與 this 無關的回撥.

比如 :定時器, 陣列的方法回撥

頭函式不適合與 this 有關的回撥(只是說不適合)

事件回撥, 物件的方法

  • this 是靜態的. this 始終指向函式宣告時所在作用域下的 this 的值
  • 並沒有自己的this
function getName(){
            console.log(this.name);  //普通方式的函式
        }
        let getName2 = () => {
            console.log(this.name);  //箭頭函式
        }

        //設定 window 物件的 name 屬性
        window.name = '尚矽谷';
        const school = {
            name: "ATGUIGU"
        }

        //直接呼叫
        getName();  //尚矽谷
        getName2();  //尚矽谷

        //call 方法呼叫
        getName.call(school);   //ATGUIGU  改變
        getName2.call(school);  //尚矽谷    箭頭函式this靜態的,不會變

不能作為構造例項化物件

let Person = (name, age) => {
            this.name = name;
            this.age = age;
        }
        let me = new Person('xiao',30);
        console.log(me);
        //Person is not a constructor

### 不能使用arguments變數

 let fn = () => {
            console.log(arguments);
        }
        fn(1,2,3);//arguments is not defined

省略小括號

  • 當形參有且只有一個的時候,可以省略小括號
let add = n => {
                return n + n;
            }
            console.log(add(9)); //18

省略花括號

  • 當程式碼體只有一條語句的時候可以省略花括號, 此時 return 必須省略
  • 而且語句的執行結果就是函式的返回值
 let pow = n => n * n;
                
            console.log(pow(8)); //64

實踐

  • 需求-1 點選 div 2s 後顏色變成『粉色』
//需求-1  點選 div 2s 後顏色變成『粉色』
        //獲取元素
        let ad = document.getElementById('ad');
        //繫結事件
        ad.addEventListener("click", function(){
            //以前儲存 this 的值
            // let _this = this;  

            //定時器
            setTimeout(() => {   //之前是function,現在是箭頭函式
                //修改背景顏色 this
                // console.log(this);  //window
                //this找不到就像外層找,儲存外部的this
                // _this.style.background = 'pink';
                this.style.background = 'pink';
                //現在this指向外層作用域,外層的this指向ad
            }, 2000);
        });
  • 從陣列中返回偶數的元素
  const arr = [1,6,9,10,100,25];
        // const result = arr.filter(function(item){
        //     if(item % 2 === 0){
        //         return true;
        //     }else{
        //         return false;
        //     }
        // });
        
        const result = arr.filter(item => item % 2 === 0);

        console.log(result); //(3) [6, 10, 100]

允許設定引數預設值

形參初始值

  • ES6 允許給函式引數賦值初始值
  • 形參初始值 具有預設值的引數, 一般位置要靠後(潛規則)
 function add(a,c=10,b) {
            return a + b + c;
        }
        let result = add(1,2); 
        // console.log(result);  //NaN  有預設值不會

與解構賦值結合

 function connect({host="127.0.0.1", username,password, port}){
            console.log(host) //atguigu.com
            console.log(username) //root
            console.log(password) //root
            console.log(port) //3306
        }
        connect({
            host: 'atguigu.com',
            username: 'root',
            password: 'root',
            port: 3306
        })

rest引數

  • ES6 引入 rest 引數,用於獲取函式的實參,用來代替 arguments

ES5 獲取實參的方式

  • 返回的是物件
 function date(){
            console.log(arguments);
        }
        date('白芷','阿嬌','思慧');
        // Arguments(3) ["白芷", "阿嬌", "思慧", callee: ƒ, Symbol(Symbol.iterator): ƒ]

rest 引數

  • 返回的是陣列,可以對陣列用下面方法
  • 可以用陣列的方法…filter some every map

        function date(...args){
            console.log(args);
            //(3) ["阿嬌", "柏芝", "思慧"] 
            //返回的是陣列,可以對陣列用下面方法
            // filter some every map 
        }

### rest引數必須要放到引數最後

function fn(a,b,...args){
            console.log(a);
            console.log(b);
            console.log(args);
        }
        fn(1,2,3,4,5,6); //1,2  (4) [3, 4, 5, 6]

spread擴充套件運算子

…擴充套件元素運算子

  • ...擴充套件運算子能將陣列轉換成為逗號分隔的引數序列
const tfboys = ['易烊千璽','王源','王俊凱'];
        // => '易烊千璽','王源','王俊凱'

        // 宣告一個函式
        function chunwan(){
            console.log(arguments);
        }

        chunwan(...tfboys);// chunwan('易烊千璽','王源','王俊凱')
        //rest ...是放在了形參,而這個是實參

------擴充套件運算子的應用------

陣列的合併

const kuaizi = ['王太利','肖央'];
        const fenghuang = ['曾毅','玲花'];

        // const zuixuanxiaopingguo = kuaizi.concat(fenghuang);  //以前方法
        //(4) ["王太利", "肖央", "曾毅", "玲花"]

        const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];
        console.log(zuixuanxiaopingguo);
        // //(4) ["王太利", "肖央", "曾毅", "玲花"]

陣列的克隆

  • 是一個淺拷貝
  const sanzhihua = ['E','G','M'];
        const sanyecao = [...sanzhihua];
        console.log(sanyecao);//  ['E','G','M']

### 將偽陣列轉為真正的陣列

const divs = document.querySelectorAll('div');
        console.log(divs);
        // __proto__(Nodelist).__proto__ (Object)

        const divArr = [...divs];
        console.log(divArr);
        //__proto__(Array).__proto__ (Object)

Symbol

ES6 引入了一種新的原始資料型別 Symbol,表示獨一無二的值。它是JavaScript 語言的第七種資料型別,是一種類似於字串的資料型別。

symbol特點

  • Symbol 的值是唯一的,用來解決命名衝突的問題
  • Symbol 值不能與其他資料進行運算

Symbol 定義 的 物件屬 性 不能 使 用 for…in 循 環遍 歷 ,但 是可 以 使 用Reflect.ownKeys 來獲取物件的所有鍵名

  • 遇到唯一性的場景時要想到 Symbol

建立Symbol

let s = Symbol();   //函式
        console.log(s, typeof s);
        //Symbol() "symbol"

Symbol唯一性

let s2 = Symbol('尚矽谷');
        let s3 = Symbol('尚矽谷');
        // console.log(s2 === s3)   //false

Symbol.for建立

 let s4 = Symbol.for('尚矽谷');  //函式物件
        let s5 = Symbol.for('尚矽谷');
        console.log(s4,typeof s4) 
        //Symbol(尚矽谷) "symbol"
        // console.log(s4 === s5)   //true

不能與其他資料進行運算

 let result = s + 100;
           let result = s > 100;
           let result = s + s;
//Identifier 'result' has already been declared

七種資料型別

USONB  you are so niubility 
        u  undefined
        s  string  symbol
        o  object
        n  null number
        b  boolean

------❥給物件新增Symbol屬性的兩種方式❥------

Symbol作用 給物件新增屬性和方法(獨一無二)

第一種

 //向物件中新增方法 up down
        let game = {
            name:'俄羅斯方塊',
            up: function(){},
            down: function(){}
        };
        
        //宣告一個物件
        let methods = {
            up: Symbol(),
            down: Symbol()
        };

        game[methods.up] = function(){
            console.log("我可以改變形狀");
        }

        game[methods.down] = function(){
            console.log("我可以快速下降!!");
        }

        console.log(game);
 //{name: "俄羅斯方塊", up: ƒ, down: ƒ, Symbol(): ƒ, Symbol(): ƒ}

第二種

let youxi = {
            name:"狼人殺",
            [Symbol('say')]: function(){
                console.log("我可以發言")
            },
            [Symbol('zibao')]: function(){
                console.log('我可以自爆');
            }
        }

        console.log(youxi)
//{name: "狼人殺", Symbol(say): ƒ, Symbol(zibao): ƒ}

------❥Symbol內建屬性❥------

Symbol.hasInstance

 class Person{
            static [Symbol.hasInstance](param){
                console.log(param);
                console.log("我被用來檢測型別了");
                return false;
            }
        }

        let o = {};

        console.log(o instanceof Person);
        // {}
        //我被用來檢測型別了
        //false

Symbol.isConcatSpreadable

 const arr = [1,2,3];
        const arr2 = [4,5,6];
        arr2[Symbol.isConcatSpreadable] = false;
        console.log(arr.concat(arr2));
        //(4) [1, 2, 3, Array(3)]

Iterator 迭代器

  • 需要自定義遍歷資料的時候,要想到迭代器。

遍歷器(Iterator)就是一種機制。它是一種介面,為各種不同的資料結構提供統一的訪問機制。任何資料結構只要部署 Iterator 介面,就可以完成遍歷操作。

  • Iterator介面 就是物件裡的一個屬性,這個屬性的名字叫做[Symbol.iterator]

  • ES6 創造了一種新的遍歷命令 for…of 迴圈,Iterator 介面主要供 for…of 消費

  • 原生具備 iterator 介面的資料(可用 for of 遍歷)

    1. Array
    2. Arguments
    3. Set
    4. Map
    5. String
    6. TypedArray
    7. NodeList

for…of 遍歷陣列

//宣告一個陣列
        const xiyou = ['唐僧','孫悟空','豬八戒','沙僧'];


        // 使用 for...of 遍歷陣列
        for(let v of xiyou){
            console.log(v);  //唐僧 孫悟空 豬八戒 沙僧
        }

        console.log(xiyou)
//[(4) ["唐僧", "孫悟空", "豬八戒", "沙僧"].__proto__
//Symbol(Symbol.iterator): ƒ values()]

迭代器工作原理

  1. 建立一個指標物件,指向當前資料結構的起始位置
  2. 第一次呼叫物件的 next 方法,指標自動指向資料結構的第一個成員
  3. 接下來不斷呼叫 next 方法,指標一直往後移動,直到指向最後一個成員
  4. 每呼叫 next 方法返回一個包含 value 和 done 屬性的物件
 const xiyou = ['唐僧','孫悟空','豬八戒','沙僧'];
        let iterator = xiyou[Symbol.iterator]();
        // console.log(iterator)
        //Array Iterator {}.__proto__
        //next: ƒ next()

        //呼叫物件的next方法
        console.log(iterator.next()); 
        //{value: "唐僧", done: false}
        console.log(iterator.next());
        //{value: "孫悟空", done: false}
        console.log(iterator.next());
        //{value: "豬八戒", done: false}
        console.log(iterator.next());
        //{value: "沙僧", done: false}
        console.log(iterator.next());{value: 
         //undefined, done: true} true表示遍歷迴圈完成

自定義迭代器遍歷物件

 //宣告一個物件
        const banji = {
            name: "終極一班",
            stus: [
                'xiaoming',
                'xiaoning',
                'xiaotian',
                'knight'
            ],
            // 加上Iterator介面(方法)
            [Symbol.iterator]() {
                //索引變數
                let index = 0;
                //
                let _this = this;
                //返回一個物件(對應1.建立一個指標物件,指向當前資料結構的起始位置)
                return {
                    //新增next方法(對應4.每呼叫 next 方法返回一個包含 value 和 done 屬性的物件)
                    next: function () {
                        if (index < _this.stus.length) {
                            const result = { value: _this.stus[index], done: false };
                            //下標自增
                            index++;
                            //返回結果
                            return result;
                        }else{
                            return {value: undefined, done: true};
                        }
                    }
                };
            }
        }

        //遍歷這個物件 
        for (let v of banji) {
            console.log(v); //xiaoming,xiaoning,xiaotian,knight
        }

生成器函式

  • 生成器函式是 ES6 提供的一種非同步程式設計解決方案

生成器本身是一個函式

生成器函式是 ES6 提供的一種非同步程式設計解決方案,語法行為與傳統函式完全不同

生成器其實就是一個特殊的函式(宣告特殊,執行特殊,調next方法才執行)

非同步程式設計 純回撥函式 node fs ajax mongodb

yield算作函式程式碼的分隔符

生成器函式的宣告

  • 程式碼說明
    • * 的位置沒有限制
    • 生成器函式返回的結果是迭代器物件,呼叫迭代器物件的 next 方法可以得到yield 語句後的值
    • yield 相當於函式的暫停標記,也可以認為是函式的分隔符,每呼叫一次 next方法,執行一段程式碼
    • next 方法可以傳遞實參,作為 yield 語句的返回值
function * gen(){
            console.log(111);
            yield '一隻沒有耳朵'; 
                       //(yield後面跟表示式或者跟字面量)
            console.log(222);
            yield '一隻沒有尾部';
            console.log(333);
            yield '真奇怪';
            console.log(444);
        }

        // let iterator = gen();
        // iterator.next(); //111
        // iterator.next(); //222
        // iterator.next(); //333
        // iterator.next(); //444

        // console.log(iterator.next());
        // 111
        //{value: "一隻沒有耳朵", done: false}
        // console.log(iterator.next());
        //222
        //{value: "一隻沒有尾部", done: false}
        // console.log(iterator.next());
        //333
        //{value: "真奇怪", done: false}
        // console.log(iterator.next());
        //444
        //{value: undefined, done: true}
        


        //遍歷
        for(let v of gen()){
            console.log(v);
        }
        //111
        //一隻沒有耳朵
        //222
        //一隻沒有尾部
        //333
        //真奇怪
        //444

### 生成器函式的呼叫

function * gen() {
            yield 111;
            yield 222;
            yield 333;
        }

        //執行獲取迭代器物件
        let iterator = gen();
        console.log(iterator.next())
        //{value: 111, done: false}
         console.log(iterator.next())
        //{value: 222, done: false}
         console.log(iterator.next())
        //{value: 333, done: false}
         console.log(iterator.next())
        //{value: undefined, done: true}

生成器函式傳參

  • 生成器整體函式傳參
  • next方法也是可以傳參的(實參),而且我們這個方法(實參)作為上一個yield語句的返回結果
  • 第二次呼叫next,yield傳入的引數作為第一個yield語句整體返回結果
function * gen(arg) {
            console.log(arg)  //undefined
            let one = yield 111;
            console.log(one) //BBB

            let two = yield 222;
            console.log(two)//CCC

            let three = yield 333;
            console.log(three)//DDD
        }

        let iterator = gen()  //undefined
        console.log(iterator.next('kkk')) 
        //經過測試,第一次傳參無用 
        //{value: 111, done: false}
        console.log(iterator.next('BBB'))  
        //{value: 222, done: false}
        console.log(iterator.next('CCC')) 
         //{value: 333, done: false}
        console.log(iterator.next('DDD'))  
        //{value: undefined, done: true}

回撥地獄

非同步程式設計:比如: 1.檔案操作 2.網路操作(ajax, request) 3.資料庫操作

  • 需求:1s後控制檯輸出 111 2s後輸出 222 3s後輸出 333
setTimeout(() => {
            console.log(111);
            setTimeout(() => {
                console.log(222);
                setTimeout(() => {
                    console.log(333);
                }, 3000);
            }, 2000);
        }, 1000);

生成器函式解決回撥地獄

需求: 1s後控制檯輸出 111 2s後輸出 222 3s後輸出 333

  • 生成器函式解決
    • 宣告三個函式.分別完成三個非同步任務
 //輸出1任務
        function one(){
            setTimeout(()=>{
                console.log(111);
                iterator.next();
            },1000)
        }
        //第二個非同步任務
        function two(){
            setTimeout(()=>{
                console.log(222);
                iterator.next();
            },2000)
        }
        //第三個非同步任務
        function three(){
            setTimeout(()=>{
                console.log(333);
                iterator.next();
            },3000)
        }

        function * gen(){
            yield one();
            yield two();
            yield three();
        }

        //呼叫生成器函式
        let iterator = gen();
        iterator.next(); 
        // 不在任務重加iterator.next()只輸出111
        //111/222/333

生成器函式在非同步任務的表現

  • 模擬獲取 使用者資料 訂單資料 商品資料
function getUsers(){
            setTimeout(()=>{
                let data = '使用者資料';
                //呼叫 next 方法, 並且將資料傳入
                iterator.next(data);
            }, 1000);
        }

        function getOrders(){
            setTimeout(()=>{
                let data = '訂單資料';
                iterator.next(data);
            }, 1000)
        }

        function getGoods(){
            setTimeout(()=>{
                let data = '商品資料';
                iterator.next(data);
            }, 1000)
        }

        function * gen(){
            let users = yield getUsers();  
                console.log(users) //使用者資料
            let orders = yield getOrders();
                console.log(orders) //訂單資料
            let goods = yield getGoods();
                console.log(goods) //商品資料
        }

        //呼叫生成器函式
        let iterator = gen();
        iterator.next();

Promise

Promise 是 ES6 引入的非同步程式設計的新解決方案(主要解決回撥地獄問題)。語法上 Promise 是一個建構函式,用來封裝非同步操作並可以獲取其成功或失敗的結果。

例項化Promise物件

  • 成功狀態
const p = new Promise(function(resolve,reject) {
            setTimeout(function() {
                let data = '資料庫中的使用者資料';
                // 呼叫resovle方法
                resolve(data)
//呼叫resolve函式以後,這個Promise物件狀態就會變為成功
//物件有三個狀態: 初始化 成功  失敗
            },1000);
        });
        
        //呼叫promise物件的then方法
        //成功的形參叫value,失敗的形參叫reason
        p.then(function(value){
            console.log(value); //資料庫中的資料
        },function(){

        })

  • 失敗狀態
const p = new Promise(function(resolve,reject) {
            setTimeout(function() {
                let data = '資料庫中的使用者資料';
                // 呼叫resovle方法
                reject(data)
//呼叫resolve函式以後,這個Promise物件狀態就會變為成功
//物件有三個狀態: 初始化 成功  失敗
            },1000);
        });
        
        //呼叫promise物件的then方法
        //成功的形參叫value,失敗的形參叫reason
        p.then(function(value){
            console.log(value); //資料庫中的資料
        },function(reason){
            console.error(reason); //資料庫中的使用者資料
        })

Promise封裝讀取檔案

  • 呼叫方法讀取檔案
//1. 引入 fs 模組
const fs = require('fs');

fs.readFile('./resources/為學.md', (err, data)=>{
    //如果失敗, 則丟擲錯誤
    if(err) throw err;
    //如果沒有出錯, 則輸出內容
    // console.log(data);  //buffer
    console.log(data.toString()); //一首詩
});
  • 使用Promise封裝
const p = new Promise(function(resolve, reject){
    fs.readFile("./resources/為學.md", (err, data)=>{
        //判斷如果失敗
        if(err) reject(err);
        //如果成功
        resolve(data);
    });
});

p.then(function(value){
    console.log(value.toString()); //一首詩
}, function(reason){
    console.log("讀取失敗!!");
});

Promise封裝AJAX

  • 傳送ajax請求
<script>
        // 介面地址: https://api.apiopen.top/getJoke
        const p = new Promise((resolve, reject) => {
            //1. 建立物件
            const xhr = new XMLHttpRequest();

            //2. 初始化
            xhr.open("GET", "https://api.apiopen.top/getJok(e)");

            //3. 傳送
            xhr.send();

            //4. 繫結事件, 處理響應結果
            xhr.onreadystatechange = function () {
                //判斷
                if (xhr.readyState === 4) {
                    //判斷響應狀態碼 200-299
                    if (xhr.status >= 200 && xhr.status < 300) {
                        //表示成功
                        // console.log(xhr.response);  文字
                        resolve(xhr.response);
                    } else {
                        //如果失敗
                        // console.error(xhr.status);  404  
                        reject(xhr.status);
                    }
                }
            }
        })
        
        //指定回撥
        p.then(function(value){
            console.log(value);
        }, function(reason){
            console.error(reason);
        });
    </script>

Promise.prototype.then

<script>
        //建立 promise 物件
        const p = new Promise((resolve, reject)=>{
            setTimeout(()=>{
                resolve('使用者資料');
                // reject('出錯啦');
            }, 1000)
        });
        // 呼叫then方法
        const result = p.then(value => {
            console.log(value);
            return '王凱';
        },reason => {
            console.warn(reason);
        })

        console.log(result)

        //Promise {<pending>}
        // __proto__: Promise
        //[[PromiseStatus]]: "fulfilled"
        //[[PromiseValue]]: undefined

        //呼叫 then 方法  then方法的返回結果是 Promise 物件, 物件狀態由回撥函式的執行結果決定
        //1. 如果回撥函式中返回的結果是 非 promise 型別的屬性, 狀態為成功, 返回值為物件的成功的值

        // const result = p.then(value => {
        //     console.log(value);
        //     //1. 非 promise 型別的屬性
        //     // return 'iloveyou';

        //     //2. 是 promise 物件
        //     // return new Promise((resolve, reject)=>{
        //     //     // resolve('ok');  then方法就chegng,返回值then成功的值
        //     //     reject('error');  //then方法就失敗,返回的值就是then方法的值
        //     // });

        //     //3. 丟擲錯誤
        //     // throw new Error('出錯啦!');
        //     throw '出錯啦!';
        // }, reason=>{
        //     console.warn(reason);
        // });

        //鏈式呼叫 then方法可以返回一個promise物件,所以可以鏈式呼叫
        // p.then(value=>{

        // }).then(value=>{

        // });


    </script>

實踐–讀取多個檔案

//引入 fs 模組
const fs = require("fs");

// fs.readFile('./resources/為學.md', (err, data1)=>{
//     fs.readFile('./resources/插秧詩.md', (err, data2)=>{
//         fs.readFile('./resources/觀書有感.md', (err, data3)=>{
//             let result = data1 + '\r\n' +data2  +'\r\n'+ data3;
//             console.log(result);  //三首詩拼接一起
//         });
//     });
// });

//使用 promise 實現
const p = new Promise((resolve, reject) => {
    fs.readFile("./resources/為學.md", (err, data) => {
        resolve(data);
    });
});

p.then(value => {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/插秧詩.md", (err, data) => {
            resolve([value, data]);
        });
    });
}).then(value => {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/觀書有感.md", (err, data) => {
            //壓入
            value.push(data);
            resolve(value);//三個檔案的陣列
        });
    })
}).then(value => {
    console.log(value.join('\r\n'));   //三首詩
});

Promise-catch方法

 <script>
        const p = new Promise((resolve, reject)=>{
            setTimeout(()=>{
                //設定 p 物件的狀態為失敗, 並設定失敗的值
                reject("出錯啦!");
            }, 1000)
        });

        // p.then(function(value){}, function(reason){
        //     console.error(reason);
        // });

        p.catch(function(reason){
            console.warn(reason);
        });
    </script>

Set 集合

ES6 提供了新的資料結構 Set(集合)。它類似於陣列,但成員的值都是唯一的,集合實現了 iterator 介面,所以可以使用『擴充套件運算子』和『for…of…』進行遍歷,集合的屬性和方法:

### new Set()

  • 宣告set
 let s = new Set();
            console.log(s,typeof s)
            //Set(0) "object"

set會自動去重

 s2 = new Set(['大事兒','小事兒','好事兒','壞事兒','小事兒']);
            console.log(s2)
            //它會自動去重
            //Set(4) {"大事兒", "小事兒", "好事兒", "壞事兒"}

.size

  • 元素的個數
    • 返回集合的元素個數

        console.log(s2.size); 
        //4

.add()

  • 新增元素
    • 增加一個新元素,返回當前集合
 s2.add('喜事兒');
        console.log(s2)
        //Set(5) {"大事兒", "小事兒", "好事兒", "壞事兒", "喜事兒"}

.delete()

  • 刪除元素
    • 刪除元素,返回boolean值
s2.delete('壞事兒');
        console.log(s2)
        //Set(4) {"大事兒", "小事兒", "好事兒", "喜事兒"}

.has()

  • 檢測
    • 檢測集合中是否包含某個元素,返回 boolean 值
  console.log(s2.has('糟心事'));
        // false

.clear()

  • 清空
    • 清空集合,返回 undefined
 // s2.clear();
        // console.log(s2);
        //Set(0) {}

for…of

for(let v of s2){
            console.log(v);
        }
        //大事兒, 小事兒, 好事兒, 喜事兒
        

❥集合實踐❥(

陣列去重

 let arr = [1,2,3,4,5,4,3,2,1];
        let result = [...new Set(arr)];
        console.log(result);
        //(5) [1, 2, 3, 4, 5]

交集

let arr = [1,2,3,4,5,4,3,2,1];
        let arr2 = [4,5,6,5,6];
        let result = [...new Set(arr)].filter(item => {
            let s2 = new Set(arr2);// 4 5 6
            if(s2.has(item)){
                return true;
            }else{
                return false;
            }
        });
        // console.log(result)  //(2) [4, 5]
 let arr = [1,2,3,4,5,4,3,2,1];
        let arr2 = [4,5,6,5,6];
        let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));
        // console.log(result);   // 4 5

並集

let arr = [1,2,3,4,5,4,3,2,1];
        let arr2 = [4,5,6,5,6];

        let union = [...new Set([...arr, ...arr2])];
        console.log(union);
        //[1, 2, 3, 4, 5, 6]

差集(和交集相反)

  let arr = [1,2,3,4,5,4,3,2,1];
        let arr2 = [4,5,6,5,6];
        let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
        console.log(diff);
        //(3) [1, 2, 3]

Map

  • 升級版的物件

ES6 提供了 Map 資料結構。它類似於物件,也是鍵值對的集合。但是“鍵”的範圍不限於字串,各種型別的值(包括物件)都可以當作鍵。Map 也實現了iterator 介面,所以可以使用『擴充套件運算子』和『for…of…』進行遍歷。

new Map()

  • 宣告Map
 let m = new Map();
        console.log(m)
        //Map(0) {}

.set()

  • 增加一個新元素,返回當前 Map
 m.set('name','尚矽谷');
        console.log(m)
        //Map(1) {"name" => "尚矽谷"}
        //key: "name"
        //value: "尚矽谷"
 m.set('change', function(){
            console.log("我們可以改變你!!");
        });
        //{"change" => function(){ console.log("我們可以改變你!!"); }}
        //key: "change"
let key = {
            school : 'ATGUIGU'
        };
        m.set(key, ['北京','上海','深圳']);
        //key: {school: "ATGUIGU"}
        //value: (3) ["北京", "上海", "深圳"]

.size

  • 返回Map的元素個數
  console.log(m.size);
        //3

.delte()

  • 刪除
m.delete('name');
        console.log(m)
        //Map(2) {"change" => ƒ, {…} => Array(3)}

.get()

  • 返回鍵名物件的鍵值
console.log(m.get('change'));
        //ƒ (){
            //console.log("我們可以改變你!!");
        //}
console.log(m.get(key));
        //(3) ["北京", "上海", "深圳"]

.has()

  • 檢測 Map 中是否包含某個元素,返回 boolean 值

.clear()

  • 清空集合,返回 undefined
 m.clear();
        //Map(0){}

for…of

for(let v of m){
            console.log(v);
        }

        // console.log(m);
        //(2) ["name", "尚矽谷"]
        //Map.html:65 (2) ["change", ƒ]
        //Map.html:65 (2) [{…}, Array(3)]

class 類

  • class 宣告類
  • constructor 定義建構函式初始化
  • extends 繼承父類
  • super 呼叫父級構造方法
  • static 定義靜態方法和屬性
  • 父類方法可以重寫

ES6 提供了更接近傳統語言的寫法,引入了 Class(類)這個概念,作為物件的模板。通過 class 關鍵字,可以定義類。基本上,ES6 的 class 可以看作只是一個語法糖,它的絕大部分功能,ES5 都可以做到,新的 class 寫法只是讓物件原型的寫法更加清晰、更像物件導向程式設計的語法而已

  • ES5例項化物件
 //ES5 例項化物件
        //手機  例項物件的屬性初始化
        function Phone(brand, price){
            this.brand = brand;
            this.price = price;
        }

        //新增方法
        Phone.prototype.call = function(){
            console.log("我可以打電話!!");
        }

        //例項化物件
        let Huawei = new Phone('華為', 5999);
        Huawei.call(); //我可以打電話!!
        console.log(Huawei);
        //Phone   brand: "華為"    price: 5999  __proto__: Object

宣告class

  • 構造方法 名字不能修改 必須叫constructor
    • 使用new加型別的時候,會自動執行例項物件上的constructor方法
  • 方法必須使用該語法, 不能使用 ES5 的物件完整形式
    • 方法名+()+{} 沒有function 和 :
 class Shouji{
            //構造方法 名字不能修改  必須叫constructor
            //使用new加型別的時候,會自動執行例項物件上的constructor方法
            constructor(brand, price){
                this.brand = brand;
                this.price = price;
            }

            //方法必須使用該語法, 不能使用 ES5 的物件完整形式
            //方法名+()+{}   沒有function 和 :
            call(){
                console.log("我可以打電話!!");
            }
        }

        let onePlus = new Shouji("1+", 1999);

        console.log(onePlus);
        //Shouji {brand: "1+", price: 1999}  brand: "1+"  price: 1999  __proto__: Object
        

static 類的靜態成員

  • 靜態屬性
  • static標註的屬性和方法它屬於類而不屬於例項物件
class Phone{
            //靜態屬性
            //static標註的屬性和方法它屬於類而不屬於例項物件
            static name = '手機';
            static change(){
                console.log("我可以改變世界");
            }
        }

        let nokia = new Phone();
        console.log(nokia.name); //undefined
        console.log(Phone.name); //手機
  • ES5裡面
    • 例項物件是例項物件 函式物件是函式物件 他們的屬性是不通的
    • 實力物件裡面的屬性 和函式物件裡面的屬性是不通的
 function Phone(){

        }
        Phone.name = '手機';
        Phone.change = function(){
            console.log("我可以改變世界");
        }
        //上面這些屬性屬於函式物件的,並不屬於例項物件 稱為靜態成員


        Phone.prototype.size = '5.5inch';

        let nokia = new Phone();
        console.log(nokia.name);
        //undefined

        nokia.change();
        console.log(nokia.size);
        //nokia.change is not a function

        console.log(nokia.size)
        //5.5inch

ES5類繼承

 //手機
        function Phone(brand, price){
            this.brand = brand;
            this.price = price;
        }

        Phone.prototype.call = function(){
            console.log("我可以打電話");
        }


        //智慧手機
        function SmartPhone(brand, price, color, size){
            Phone.call(this, brand, price);
            //this指向SmartPhone裡面的this,也就是SmartPhone例項化物件
            this.color = color;
            this.size = size;
        }

        //為了實現繼承 設定子級建構函式的原型
        SmartPhone.prototype = new Phone;
        // 不加也行
        SmartPhone.prototype.constructor = SmartPhone;

        //宣告子類的方法
        SmartPhone.prototype.photo = function(){
            console.log("我可以拍照")
        }

        SmartPhone.prototype.playGame = function(){
            console.log("我可以玩遊戲");
        }

        const chuizi = new SmartPhone('錘子',2499,'黑色','5.5inch');

        console.log(chuizi);

extends 繼承父類

  • extends 繼承父類
 <script>
        class Phone{
            //構造方法
            constructor(brand, price){
                this.brand = brand;
                this.price = price;
            }
            //父類的成員屬性
            call(){
                console.log("我可以打電話!!");
            }
        }

        class SmartPhone extends Phone {
            //構造方法
            constructor(brand, price, color, size){
                super(brand, price);// Phone.call(this, brand, price)
                this.color = color;
                this.size = size;
            }

            photo(){
                console.log("拍照");
            }

            playGame(){
                console.log("玩遊戲");
            }

            call(){
                console.log('我可以進行視訊通話');
            }
        }

        const xiaomi = new SmartPhone('小米',799,'黑色','4.7inch');
        // console.log(xiaomi);
        xiaomi.call();
        xiaomi.photo();
        xiaomi.playGame();
    </script>

子類是不能呼叫父類的同名方法的

<script>
        //js語法裡子類是不能呼叫父類的同名方法的
        class Phone{
            //構造方法
            constructor(brand, price){
                this.brand = brand;
                this.price = price;
            }
            //父類的成員屬性
            call(){
                console.log("我可以打電話!!");
            }
        }

        class SmartPhone extends Phone {
            //構造方法
            constructor(brand, price, color, size){
                super(brand, price);// Phone.call(this, brand, price)
                this.color = color;
                this.size = size;
            }

            photo(){
                console.log("拍照");
            }

            playGame(){
                console.log("玩遊戲");
            }

            call(){
                console.log('我可以進行視訊通話');
            }
        }

        const xiaomi = new SmartPhone('小米',799,'黑色','4.7inch');
        // console.log(xiaomi);
        xiaomi.call();
        xiaomi.photo();
        xiaomi.playGame();
    </script>

class的set 和 get

 <script>
        // get 和 set  
        class Phone{
            get price(){
                console.log("價格屬性被讀取了");
                return 'iloveyou';
            }

            set price(newVal){
                console.log('價格屬性被修改了');
            }
        }

        //例項化物件
        let s = new Phone();

        // console.log(s.price);
        s.price = 'free';
    </script>

數值擴充套件

Number.EPSILON

  • Number.EPSILON 是 JavaScript 表示的最小精度
  • EPSILON 屬性的值接近於 2.2204460492503130808472633361816E-16
function equal(a, b){
            if(Math.abs(a-b) < Number.EPSILON){
                return true;
            }else{
                return false;
            }
        }
        // console.log(0.1 + 0.2 === 0.3);  false
        // console.log(equal(0.1 + 0.2, 0.3)) //true

0b 0o

  • ES6 提供了二進位制和八進位制數值的新的寫法,分別用字首 0b 和 0o 表示。
 //1. 二進位制和八進位制
        let b = 0b1010;  //10
        let o = 0o777;  //511
        let d = 100;  //100
        let x = 0xff; //255
        // console.log(x);

Number.isFinite()

  • 用來檢查一個數值是否為有限數
nsole.log(Number.isFinite(100));   //true
        console.log(Number.isFinite(100/0));  //false
        console.log(Number.isFinite(Infinity));  //false

Number.isNaN()

  • 用來檢查一個值是否為 NaN
console.log(Number.isNaN(123));    //false

Number.parseInt()

  • ES6 將全域性方法 parseInt 和 parseFloat,移植到 Number 物件上面,使用不變。
console.log(Number.parseInt('5211314love'));  //5211314

Number.parseFloat()

console.log(Number.parseFloat('3.1415926神奇'));  //3.1415926

Math.trunc()

  • 用於去除一個數的小數部分,返回整數部分。
console.log(Math.trunc(3.5)); //3

Number.isInteger()

  • 用來判斷一個數值是否為整數
console.log(Number.isInteger(5));  //true
        console.log(Number.isInteger(2.5));  //false

Math.sign()

  • 判斷一個數到底為正數 負數 還是零
console.log(Math.sign(100));  //1
        console.log(Math.sign(0));    //0
        console.log(Math.sign(-20000));  //-1

物件方法擴充套件

ES6 新增了一些 Object 物件的方法

  • Object.is 比較兩個值是否嚴格相等,與『===』行為基本一致(+0 與 NaN)
  • Object.assign 物件的合併,將源物件的所有可列舉屬性,複製到目標物件
  • proto、setPrototypeOf、 setPrototypeOf 可以直接設定物件的原型

Object.is

  • 判斷兩個值是否完全相等
 console.log(Object.is(120, 120));// 類似於=== true
        console.log(Object.is(NaN, NaN));// 區別=== true
        console.log(NaN === NaN);// === //false

Object.assign

  • 物件的合併 同名有的覆蓋,沒有的新增
const config1 = {
            host: 'localhost',
            port: 3306,
            name: 'root',
            pass: 'root',
            test: 'test'
        };
        const config2 = {
            host: 'http://atguigu.com',
            port: 33060,
            name: 'atguigu.com',
            pass: 'iloveyou',
            test2: 'test2'
        }
        console.log(Object.assign(config1, config2));
 //{host: "http://atguigu.com", port: 33060, name: "atguigu.com", pass: "iloveyou", test: "test", …}

Object.setPrototypeOf

  • 設定原型物件,並不建議這樣去做
 const school = {
            name: '尚矽谷'
        }
        const cities = {
            xiaoqu: ['北京','上海','深圳']
        }
        Object.setPrototypeOf(school, cities);
        console.log(Object.getPrototypeOf(school));

        console.log(school);//{xiaoqu: Array(3)}
  • Object.getPrototypeof

模組化

模組化是指將一個大的程式檔案,拆分成許多小的檔案,然後將小檔案組合起來

模組化的好處

  1. 防止命名衝突
  2. 程式碼複用
  3. 高維護性

模組化規範產品

  • ES6之前的模組化規範有
CommonJSNodeJS、Browserify
AMDrequireJS
CMDseaJS

使用ES6模組化引入模組

❥通用的匯入方式❥

  • 瀏覽器使用ES6模組化引入模組
  <script type="module">
        //引入wk.js模組內容
        import * as wk from './wk.js'
        console.log(wk);
    </script>

export 分別暴露

export let name = 'wangkai';
export function home() {
    console.log('萬科歡迎您');
}
<script type="module">
        //引入wk.js模組內容
        import * as wk from './wk.js'
        console.log(wk);
        wk.default.home()  //萬科歡迎您
    </script>

export{} 統一暴露

let name = 'wangkai';
function home() {
    console.log('萬科歡迎您');
}

export{name,home}
<script type="module">
        //引入wk.js模組內容
        import * as wk from './wk.js'
        console.log(wk);
        wk.default.home()  //萬科歡迎您
    </script>

export default{} 預設暴露

  • 花括號裡面可以使任意型別 值
  • 呼叫方法需要將加default : xxx.default.xxx()
export default{
     name : 'wangkai',
    home:function() {
       console.log('萬科歡迎您');
   }
 }
 <script type="module">
        //引入wk.js模組內容
        import * as wk from './wk.js'
        console.log(wk);
        wk.default.home()  //萬科歡迎您
    </script>

### ❥解構賦值形式引入❥

export 分別暴露

import {name,home} from './wk.js';

// console.log(name);  //wangkai
// console.log(home);  //ƒ home() {  console.log('萬科歡迎您');}
export let name = 'wangkai';
export function home() {
    console.log('萬科歡迎您');
}

export{} 統一暴露

  • Identifier ‘name’ has already been declared
  • 使用as 加別名,就不會和上面name衝突
 import {name as namee,house} from './wkk.js';
 
 // console.log(name);  //wangkai
// console.log(home);  //ƒ home() {  console.log('萬科歡迎您');}
let name = 'wangkai';
function home() {
    console.log('萬科歡迎您');
}

export{name,home}

export default{} 預設暴露

//default必須使用別名
        import {default as kgg} from './wkkk.js';
        console.log(kgg);  //{name: "wangkai", home: ƒ}
        
// console.log(name);  //wangkai
// console.log(home);  //ƒ home() {  console.log('萬科歡迎您');} 
  • 花括號裡面可以使任意型別 值
  • 呼叫方法需要將加default : xxx.default.xxx()
export default{
     name : 'wangkai',
    home:function() {
       console.log('萬科歡迎您');
   }
 }

簡便形式,只能針對預設形式

 import wkkk from './wkkk.js';
        console.log(wkkk); //{name: "wangkai", home: ƒ}

單獨建立一個文件

  • html
<script src="./app.js" type="module"></script>
  • js
// 入口檔案

// 模組引入
import * as wk from './wk.js';
import * as wkk from './wkk.js';
import * as wkkk from './wkkk.js';
console.log(wk);
console.log(wkk);
console.log(wkkk);

ES6-ES6模組化引入NPM包

<!-- 
        1. 安裝工具 npm i babel-cli babel-preset-env browserify(webpack) -D
        2. 編譯 npx babel src/js -d dist/js --presets=babel-preset-env
        3. 打包 npx browserify dist/js/app.js -o dist/bundle.js
     -->
//修改背景顏色為粉色
import $ from 'jquery';// const $ = require("jquery");
$('body').css('background','pink');

ECMAScript7

.includes

  • Array.prototype.includes
  • Includes 方法用來檢測陣列中是否包含某個元素,返回布林型別值
// includes   indexOf(以前用indexOf)
        const mingzhu = ['西遊記','紅樓夢','三國演義','水滸傳'];

        //判斷
        console.log(mingzhu.includes('西遊記'));
        //true
        console.log(mingzhu.includes('金瓶梅'));
        //false

** 冪運算子

  • 在 ES7 中引入指數運算子「**」,用來實現冪運算,功能與 Math.pow 結果相同
 console.log(2 ** 10);// 1024
        //效果一樣的  **更簡單
        console.log(Math.pow(2, 10));//1024

ECMAScript8

  • async 和 await 兩種語法結合可以讓非同步程式碼像同步程式碼一樣

async 函式

  • async用來宣告一個特殊的函式
  • async 函式的返回值為 promise 物件,
  • promise 物件的結果由 async 函式執行的返回值決定
<script>
        async function fn(){
            // 返回一個字串
            // return '尚矽谷';
            // 返回的結果不是一個 Promise 型別的物件, 返回的結果就是成功 Promise 物件
            // return;

            //丟擲錯誤, 返回的結果是一個失敗的 Promise
            // throw new Error('出錯啦!');

            //返回的結果如果是一個 Promise 物件
            return new Promise((resolve, reject)=>{
                resolve('成功的資料');
                // reject("失敗的錯誤");
            });
        }

        const result = fn();

        //呼叫 then 方法
        result.then(value => {
            console.log(value);
        }, reason => {
            console.warn(reason);
        })
    </script>

await 表示式

  • await 必須寫在 async 函式中
  • await 右側的表示式一般為 promise 物件
  • await 返回的是 promise 成功的值
  • await 的 promise 失敗了, 就會丟擲異常, 需要通過 try…catch 捕獲處理
//建立 promise 物件
        const p = new Promise((resolve, reject) => {
            // resolve("使用者資料");
            reject("失敗啦!");
        })



        // await 要放在 async 函式中.
        async function main() {
           // let result =  await p;
           // console.log(result)  //使用者資料
            try {
                let result = await p; //使用者資料
                //
                console.log(result);
            } catch (e) {
                console.log(e);  //失敗啦!
            }
        }
        //呼叫函式
        main();

async和await結合讀取檔案

//1. 引入 fs 模組
const fs = require("fs");

//讀取『為學』
function readWeiXue() {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/為學.md", (err, data) => {
            //如果失敗
            if (err) reject(err);
            //如果成功
            resolve(data);
        })
    })
}

function readChaYangShi() {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/插秧詩.md", (err, data) => {
            //如果失敗
            if (err) reject(err);
            //如果成功
            resolve(data);
        })
    })
}

function readGuanShu() {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/觀書有感.md", (err, data) => {
            //如果失敗
            if (err) reject(err);
            //如果成功
            resolve(data);
        })
    })
}

//宣告一個 async 函式
async function main(){
    //獲取為學內容
    let weixue = await readWeiXue();
    //獲取插秧詩內容
    let chayang = await readChaYangShi();
    // 獲取觀書有感
    let guanshu = await readGuanShu();

    console.log(weixue.toString());
    console.log(chayang.toString());
    console.log(guanshu.toString());
}

main();

async和await封裝AJAX請求

 <script>
        // 傳送 AJAX 請求, 返回的結果是 Promise 物件
        function sendAJAX(url) {
            return new Promise((resolve, reject) => {
                //1. 建立物件
                const x = new XMLHttpRequest();

                //2. 初始化
                x.open('GET', url);

                //3. 傳送
                x.send();

                //4. 事件繫結
                x.onreadystatechange = function () {
                    if (x.readyState === 4) {
                        if (x.status >= 200 && x.status < 300) {
                            //成功啦
                            resolve(x.response);
                        }else{
                            //如果失敗
                            reject(x.status);
                        }
                    }
                }
            })
        }
    
        //promise then 方法測試
        // sendAJAX("https://api.apiopen.top/getJoke").then(value=>{
        //     console.log(value);
        // }, reason=>{})
  
        // async 與 await 測試  axios
        async function main(){
            //傳送 AJAX 請求
            let result = await sendAJAX("https://api.apiopen.top/getJoke");
            //再次測試
            let tianqi = await sendAJAX('https://www.tianqiapi.com/api/?version=v1&city=%E5%8C%97%E4%BA%AC&appid=23941491&appsecret=TXoD5e8P')

            console.log(tianqi);
        }
        main();
        
    </script>

//宣告物件
        const school = {
            name:"尚矽谷",
            cities:['北京','上海','深圳'],
            xueke: ['前端','Java','大資料','運維']
        };

        //獲取物件所有的鍵
        console.log(Object.keys(school));
        //0: "name"1: "cities"2: "xueke"

Object.values

  • Object.values()方法返回一個給定物件的所有可列舉屬性值的陣列
//獲取物件所有的值
        // console.log(Object.values(school));
        //["尚矽谷", Array(3), Array(4)]

Object.entries

  • Object.entries()方法返回一個給定物件自身可遍歷屬性 [key,value] 的陣列
 console.log(Object.entries(school));
        // (3) [Array(2), Array(2), Array(2)]
        // 0: (2) ["name", "尚矽谷"]
        // 1: (2) ["cities", Array(3)]
        // 2: (2) ["xueke", Array(4)]
//建立 Map
        // const m = new Map(Object.entries(school));
        // console.log(m.get('cities'));

Object.getOwnPropertyDescriptors

  • Object.getOwnPropertyDescriptors
  • 該方法返回指定物件所有自身屬性的描述物件
 //物件屬性的描述物件
        console.log(Object.getOwnPropertyDescriptors(school));
        //{name: {…}, cities: {…}, xueke: {…}}

        // const obj = Object.create(null, {
        //     name: {
        //         //設定值
        //         value: '尚矽谷',
        //         //屬性特性
        //         writable: true,
        //         configurable: true,
        //         enumerable: true
        //     } 
        // });

ECMAScript9

Rest/Spread屬性

  • Rest 引數與 spread 擴充套件運算子在 ES6 中已經引入,不過 ES6 中只針對於陣列,在 ES9 中為物件提供了像陣列一樣的 rest 引數和擴充套件運算子
//rest 引數
        function connect({host, port, ...user}){
            console.log(host);  //127.0.0.1
            console.log(port);  //3306
            console.log(user);  //{username: "root", password: "root", type: "master"}
        }

        connect({
            host: '127.0.0.1',
            port: 3306,
            username: 'root',
            password: 'root',
            type: 'master'
        });

物件合併

const skillOne = {
            q: '天音波'
        }

        const skillTwo = {
            w: '金鐘罩'
        }

        const skillThree = {
            e: '天雷破'
        }
        const skillFour = {
            r: '猛龍擺尾'
        }

        const mangseng = {...skillOne, ...skillTwo, ...skillThree, ...skillFour};

        console.log(mangseng)
        //{q: "天音波", w: "金鐘罩", e: "天雷破", r: "猛龍擺尾"}

        // ...skillOne   =>  q: '天音波', w: '金鐘罩'

正則命名分組

let str = '<a href="http://www.atguigu.com">尚矽谷</a>';
        //分組命名
        const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/;

        const result = reg.exec(str);

        console.log(result.groups.url);
        //http://www.atguigu.com
        console.log(result.groups.text);
        //尚矽谷
  • 以前辦法
 //宣告一個字串
        let str = '<a href="http://www.atguigu.com">尚矽谷</a>';

        //提取 url 與 『標籤文字』
        const reg = /<a href="(.*)">(.*)<\/a>/;

        // //執行
        const result = reg.exec(str);

        console.log(result);  
        //["<a href="http://www.atguigu.com">尚矽谷</a>", "http://www.atguigu.com", "尚矽谷", index: 0, input: "<a href="http://www.atguigu.com">尚矽谷</a>", groups: undefined]

        console.log(result[1]);
        //http://www.atguigu.com
        console.log(result[2]);
        // 尚矽谷

正則 正向斷言

 //宣告字串
        let str = 'JS5211314你知道麼555啦啦啦';
        //正向斷言
        const reg = /\d+(?=啦)/;
        const result = reg.exec(str); 
        console.log(result)
        //["555", index: 13, input: "JS5211314你知道麼555啦啦啦", groups: undefined]

正則 反向斷言

 //反向斷言
        const reg = /(?<=麼)\d+/;
        const result = reg.exec(str);
        console.log(result);
         //["555", index: 13, input: "JS5211314你知道麼555啦啦啦", groups: undefined]

. dotAll模式

  • dot . 元字元 除換行符以外的任意單個字元

  • 正規表示式中點.匹配除回車外的任何單字元,標記『s』改變這種行為,允許行

    終止符出現

let str = `
        <ul>
            <li>
                <a>肖生克的救贖</a>
                <p>上映日期: 1994-09-10</p>
            </li>
            <li>
                <a>阿甘正傳</a>
                <p>上映日期: 1994-07-06</p>
            </li>
        </ul>`;
        //宣告正則
        // const reg = /<li>\s+<a>(.*?)<\/a>\s+<p>(.*?)<\/p>/;
        const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs;
        //執行匹配
        // const result = reg.exec(str);
        let result;
        let data = [];
        while(result = reg.exec(str)){
            data.push({title: result[1], time: result[2]});
        }
        //輸出結果
        console.log(data);

ECMAScript10

Object.fromEntries

  • Object.entries和它相反

  • 二維陣列

const result = Object.fromEntries([
            ['name','尚矽谷'],
            ['xueke', 'Java,大資料,前端,雲端計算']
        ]);
        console.log(result)
        //Object
        //name: "尚矽谷"
        //xueke: "Java,大資料,前端,雲端計算"
  • Map
 const m = new Map();
        m.set('name','ATGUIGU');
        const result = Object.fromEntries(m);
        console.log(result)
        //{name: "ATGUIGU"}
  • Object.entries和它相反
const arr = Object.entries({
            name: "尚矽谷"
        })
        console.log(arr);
        //[Array(2)]
        //0: (2) ["name", "尚矽谷"]
        //length: 1

trimStart trimEnd

  • 清除左邊和右邊空白
 <script>    
        // trim
        let str = '   iloveyou   ';

        console.log(str);
        console.log(str.trimStart());
        console.log(str.trimEnd());
    </script>

Array.prototype.flat

  • flat 平

  • 將多維陣列轉化為低位陣列

  • 引數為深度 是一個數字

    • 三維轉1維輸入2
    • 預設值是1
const arr = [1,2,3,4,[5,6]];
        console.log(arr.flat()); 
        (6) [1, 2, 3, 4, 5, 6]
const arr = [1,2,3,4,[5,6,[7,8,9]]];
        console.log(arr.flat());  
        (7) [1, 2, 3, 4, 5, 6, Array(3)]
const arr = [1,2,3,4,[5,6,[7,8,9]]];
        console.log(arr.flat(2)); 
        //(9) [1, 2, 3, 4, 5, 6, 7, 8, 9]

flatMap

  • 跟Map很像,只是把維度降低

  • 兩個操作結合

		const arr = [1,2,3,4];
        const result = arr.map(item => item * 10);
        console.log(result)
        //(4) [10, 20, 30, 40]
----------------------------------------------------
        const arr = [1,2,3,4];
        const result = arr.map(item => [item * 10]);
        console.log(result)
        //0: [10]
        //1: [20]
        //2: [30]
        //3: [40]
--------------------------------------------------------------
        const arr = [1,2,3,4];
        const result = arr.flatMap(item => [item * 10]);
        console.log(result);
        //(4) [10, 20, 30, 40]

Symbol.prototype.description

  • 獲取Symbol的描述字串
<script>
        //建立 Symbol
        let s = Symbol('尚矽谷');

        console.log(s.description);
        //尚矽谷
    </script>

ECMAScript11

類的私有屬性

 <script>
        class Person{
            //公有屬性
            name;
            //私有屬性
            #age;
            #weight;
            //構造方法
            constructor(name, age, weight){
                this.name = name;
                this.#age = age;
                this.#weight = weight;
            }

            intro(){
                console.log(this.name);
                console.log(this.#age);
                console.log(this.#weight);
            }
        }

        //例項化
        const girl = new Person('曉紅', 18, '45kg');

        // console.log(girl.name);
        // console.log(girl.#age);
        // console.log(girl.#weight);
        //Private field '#age' must be declared in an enclosing class

        girl.intro();  //曉紅 18  45
    </script>

Promise.allSettled

  • 接收promise一個陣列,返回的promise結果也是物件,不過返回的結果永遠是一個成功的狀態.而且成功的值是裡邊每一個promise狀態和結果
<script>
        //宣告兩個promise物件
        const p1 = new Promise((resolve, reject)=>{
            setTimeout(()=>{
                resolve('商品資料 - 1');
            },1000)
        });

        const p2 = new Promise((resolve, reject)=>{
            setTimeout(()=>{
                resolve('商品資料 - 2');
                // reject('出錯啦!');
            },1000)
        });

        //呼叫 allsettled 方法
        // const result = Promise.allSettled([p1, p2]);
        
        // const res = Promise.all([p1, p2]);

        console.log(res);

    </script>

String.prototype.matchAll

  • 用來得到正則批量匹配的結果
<script>
        let str = `<ul>
            <li>
                <a>肖生克的救贖</a>
                <p>上映日期: 1994-09-10</p>
            </li>
            <li>
                <a>阿甘正傳</a>
                <p>上映日期: 1994-07-06</p>
            </li>
        </ul>`;

        //宣告正則
        const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/sg

        //呼叫方法
        const result = str.matchAll(reg);

        // for(let v of result){
        //     console.log(v);
        // }

        const arr = [...result];

        console.log(arr);

    </script>

.? 可選鏈操作符

<script>
        // ?.
        function main(config){
            // const dbHost = config && config.db && config.db.host;
            const dbHost = config?.db?.host;

            console.log(dbHost);
        }

        main({
            db: {
                host:'192.168.1.100',
                username: 'root'
            },
            cache: {
                host: '192.168.1.200',
                username:'admin'
            }
        })
    </script>

動態 import 匯入

<body>
    <button id="btn">點選</button>
    <script src="./js/app.js" type="module"></script>
</body>
export function hello(){
    alert('Hello');
}
// import * as m1 from "./hello.js";
//獲取元素
const btn = document.getElementById('btn');

btn.onclick = function(){
    import('./hello.js').then(module => {
        module.hello();
    });
}

BigInt 大整形

  • 不能直接與數值計算
  • 不能使用浮點數計算
 <script>
        //大整形
        let n = 521n;
        console.log(n, typeof(n));
        //521n "bigint"

        //函式
        let n = 123;
        console.log(BigInt(n)); //123n
        console.log(BigInt(1.2));

        //大數值運算
        let max = Number.MAX_SAFE_INTEGER;
        console.log(max);
        console.log(max + 1);
        console.log(max + 2);

        console.log(BigInt(max))
        console.log(BigInt(max) + BigInt(1))
        console.log(BigInt(max) + BigInt(2))
    </script>

絕對全域性物件globalThis

  • 始終指向全域性物件
 <script>
        console.log(globalThis);   //window
 </script>
console.log(globalThis);  //globakThis

相關文章