ES6讀書筆記彙總系列(一)

前言

溫故而知新,可以爲師矣. 相信大家都會有這種感覺,很多學過的知識經常不使用就會慢慢遺忘!!!本文把以前自己關於 ES6的入門讀書筆記重新彙總了一下,並結合了工作中常用的使用場景...

變量聲明方式 let,const

ES5中聲明變量: 
    a. var命令會發生”變量提升“現象,即變量可以在聲明之前使用,值爲undefined。
    b. es5中變量只有兩種作用域: 全局 和 局部(函數內聲明); 全局和局部都有變量提升現象;先提前,再進行賦值.
    不合理場景1: 局部內層變量 可能覆蓋掉 全局變量
    不合理場景2: for循環中 用var聲明的 變量i; 會泄露成全局變量,循環結束並沒有消失

ES6中聲明變量:
1.聲明的變量a的作用域爲塊級,並且只在自己所在的塊級作用域起作用; 外層作用域不能訪問內層, 內層可以訪問外層的;
2.內&&外層的同名變量互不干擾; 內層重新賦值也不會對外層造成影響;
3.變量必須先聲明,再使用,否則報錯...(暫時性死區特性), 沒有所謂的變量提升
4.同一作用域不能重複聲明同一個變量; 函數function第一層作用域變量聲明不能和形參一樣; 否則報錯

//注意:
1. es6中,變量在for循環中的使用
    每一輪的i值 只在當前的循環中有效; 相當於每一次循環i都是一個新變量 
    // 1.循環變量在設置的時候是: 一個父作用域
    // 2.循環體內部又是一個單獨的子作用域
    // 3.所以當同時兩個塊級作用域如使用相同的變量i,循環體內部會使用自己作用域聲明的i

2.ES6 規定,塊級作用域之中,函數聲明語句的行爲類似於let,在塊級作用域之外不可引用。
    // 1.避免在塊級作用域內使用函數時聲明的方式(function fn(){xxx})聲明函數
    // 2.可以使用表達式方式 let f = function(){}
    // 也就是外層無法調用內層聲明的函數...

3.const聲明一個常量: 該變量不能變化,是一個恆定值
    const NUM_100 = 100; // 定義時就需要初始化
    // const實際上保證的並不是變量的值不得改動,而是變量指向的那個內存地址所保存的數據不得改動。
    // 值類型:   數據就 等同於 這個常量的地址的值
    // 引用類型: 這個常量 是一直指向一個固定的地址, 不能變的(修改指向就保錯,即賦值操作); 只不過對象本身可變

變量的解構賦值語法

解構賦值,我按照字面意思就是 解析數據結構, 然後給一一對應的變量進行賦值的一種語法

  • 解構的語法:

    =號左邊是: 匹配模式; =號右邊是: 實際的數據(或者數據對應的變量);
    
    解構的結果:
       解構成功: 左邊變量的值 就是右邊對應變量的值
       解構不成功: 即沒有對應值匹配, 變量的值變爲undefined
       不完全解構: 左邊的模式之匹配到右邊數組的一部分
  • 變量是複雜數據類型(數組,對象)

    1.數組解構賦值
      1.右邊的值需要能夠被遍歷 
      2.允許左邊給默認值: let [x=1, y=x] = ['xxxx'];
      3.支持嵌套結構的 解構賦值
     注意:
      let [x, y=true] = ['xxxx']; // 右邊數組對應成員要 === undefined
      // console.log(x,y); // 如果是null, 則默認值不會生效;
      // 如果右邊 不是undefined, 則左邊 會取到值
    
    2.對象的解構賦值
      1.對象本身就是無序的, 是根據左右同名變量 來做賦值操作,匹配規則和數組類似
      // 對象的解構賦值的內部機制,是先找到同名屬性,然後再賦給對應的變量。真正被賦值的是後者
      例: let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };
      2.持嵌套結構的 解構賦值
          let obj = {};
          let arr = [];
          ({foo: obj.num, bool: arr[0]} = {foo: 123, bool: true}); // 圓括號
          console.log(obj, arr);
    
    3.對象的解構賦值,可以很方便地將現有對象的方法,賦值到某個變量,幾個例子
      3-1 let {sin, cos} = Math; // 將math對象中方法給對象
      3-2 取出數組的首尾2項
          let list = [1,2,323,123,12,2];
          let {0: first, [list.length-1]: last} = list;
  • 變量是簡單數據類型(字符串,數值,布爾值)

    1.字符串的解構賦值
      字符串被轉換成了一個類似數組的對象: 可以理解未僞數組
      let [a,b,c,d,e] = 'hello'; // 每個變量對應一個字符
    
    2.數值和布爾值的解構賦值
      解構賦值的規則: 只要等號右邊的值不是對象或數組,就先將其轉爲對象。
      由於undefined 和 null無法轉爲對象,所以對它們進行解構賦值,都會報錯
      所以, 數值和布爾值會先轉成其包裝對象Number 和 Boolean對象;然後可以賦值對象的屬性
  • 函數參數的解構

    1.會將實參與形參一一對應
    console.log([[1, 2], [3, 4]].map(([a, b]) => a + b));
  • 常用的使用場景

       變量之間值的交換; 函數中傳參和接受返回值(對象的方式); 對象遍歷等等...
       
       1.交換變量的值
       let v100 = 100;
       let v1 = 1;
    
       [v1, v100] = [v100, v1];
       console.log(v1, v100);
    
       2.接受函數的多個返回值: 比如數組,對象
       // 函數只能返回一個值,如果要返回多個值,只能將它們放在數組或對象裏返回。
       // 有了解構賦值,取出這些值就非常方便。
       function example() {
       return [1, 2, 3];
       }
       // let [a, b, c] = example();
    
       3.函數傳參
       // 解構賦值可以方便地將一組參數與變量名對應起來
       // 參數是一組有次序的值
       function f([x, y, z]) {  }
       f([1, 2, 3]);
    
       // 參數是一組無次序的值
       function f({x, y, z}) {  }
       f({z: 3, y: 2, x: 1});
    
       4.json數據的處理
       // 解構賦值對提取 JSON 對象中的數據,尤其有用。
       let jsonData = {
           id: 42,
           status: "OK",
           data: [867, 5309]
       };
    
       let {id, status, data: arr1} = jsonData;
       console.log(id, status, arr1);
    
       5.設置函數參數的默認值
       // 避免了在函數體內部再寫var foo = config.foo || 'default foo';
       // 在傳參時; 特別是傳一個對象參數時, 可以事先配置好參數的默認值
       // func({參數1 = true, 參數2 = false, ...} = {外部實參沒有傳值的就是用默認值}){}
    
       6.遍歷 Map 結構
       // 可迭代對象, 都可以用for...of 來遍歷
       const map = new Map();
       map.set('first', 'hello');
       map.set('second', 'world');
    
       for (let [key, value] of map) {
           console.log(key + " is " + value);
       }
       // 獲取鍵名
       for (let [key] of map) {
           console.log(key);
       }
       // 獲取鍵值
       for (let [,value] of map) {
           console.log(value);
       }
    
       7.模塊導入
       // 加載模塊時,往往需要指定輸入哪些方法。解構賦值使得輸入語句非常清晰
       // const { SourceMapConsumer, SourceNode } = require("source-map"); 
       

字符串,數組,對象的擴展

字符串方法

1. 處理4個字節存儲的單個字符
// 測試一個字符由兩個字節還是由四個字節組成的最簡單方法 (Unicode 編號大於0xFFFF)
// codePointAt(下標): 返回10機制字節碼;
function is_32bit(char) {
    return char.codePointAt(0) > 0xFFFF;
}
console.log(is_32bit('𠮷a')); // true
// 識別4個字節(32位)組成的單個字符
console.log(String.fromCodePoint(0x20BB7)); // 𠮷 

2.字符串的遍歷for of
let text = '我的名字';
for (const char of text) {
    console.log(char);
}

3.確定一個字符串中是否包含另一個目標字符串
// includes(), startsWith(), endsWith() // 返回true和false
console.log(text.startsWith('我'));
console.log(text.endsWith('我'));
console.log(text.includes('我'));

4.repeat(num); 將字符串重複num次並返回
console.log(text.repeat(3));

5.字符串補全長度的功能
// padStart()用於頭部補全,padEnd()用於尾部補全
// 參數1: 補全後的生效長度; 參數2: 用於補全的字符串(沒有參數默認空格)
// 長度過了; 會截取超出位數的字符串
// 長度 <= 原長度; 返回自己

// 用途1: 將數值補全爲指定位數
console.log("1".padStart(10, '0')); // 0000000001
// 場景2: 日期補全
console.log('09-12'.padStart(10, '2018-MM-DD')); // 2018-09-12

模板字符串

模板字符串: 反引號 ` 標識; 
// 變量名使用 ${變量名}; 可以省去字符串的拼接了
let name = "bob";
let age = 24;
console.log(`Hello ${name}, how are you ${age}?`);

// ${這裏面可以進行運算; 函數調用; 放對象的屬性等}; 相當於執行js代碼
// 還可以相互嵌套

當然,模板字符串的用法比較複雜,後續再深入總結

數值類型方法

// 1.檢查數字爲有限值
Number.isFinite(12); // true; 其他類型都爲false

// 2.檢查數值是不是NAN
Number.isNaN(1+NaN); // true; NaN 數值與非數值運算的結果NaN

// 3.Number.parseFloat 和 Number.parseInt; 將ES5的全局方法移到Number對象上

// 4.Number.EPSILON * Math.pow(2, 2): 兩個浮點數之間的最小誤差; 
// 差值小於它, 就可以認爲時相等

// 5.Math方法的擴展
console.log(Math.round(4.5)); // 5; 四捨五入

// Math.trunc方法用於去除一個數(正負都可以)的小數部分,返回整數部分。
console.log(Math.trunc(3.1)); 
// 兼容性寫法
// Math.trunc = Math.trunc || function(x) {
//     return x < 0 ? Math.ceil(x) : Math.floor(x);
//  };

// Math.sign()
// 判斷正負, 還是0; 對非數值,能轉化的轉化; 不能轉的就是NaN
// 返回值: 正 +1; 負 -1; 0; -0; 其他值 NaN

數組的擴展方法

ES6中會將數組空位轉爲undefined

1.Array.from(param1, param2)方法用於將兩類對象轉爲真正的數組:
    參數1: 一個對象 ==> 僞數組對象和可遍歷(iterable)的對象
    參數2: 回調函數 ==> 類似於數組的map方法,對每個元素進行處理,將處理後的值放入返回的數組。
    return值: 一個數組;
示例:
    let arrayLike = {
        '0': 'a',
        '1': 'b',
        '2': 'c',
        length: 3
        // 0: 'a',
        // 1: 'b',
        // 2: 'c',
        // length: 3
    };
    let real_arr = Array.from(arrayLike);

2.Array.of(傳一組數值); 用於將一組值,轉換爲數組。彌補了構造函數Array()傳數值的缺點
    參數: 一組數值,如: 1,2,3,4...
    return值: 一個數組

3.實例方法

    3.1 arr.find(): 類似過濾函數filter(function(value, index, arr))
        使用: 傳入一個回調函數, 返回第一個符合要求的成員
        示例: var res = [1,2,3,4,-100].find( n => n < 0 ); // -100

    3.2 arr.findIndex(): 同上,只不過是返回第一個符合條件的數組成員的位置
        注意: 第二個參數是傳一個對象,回調函數中若使用了 this, 則指向這個對象

    3.3 arr.includes(): 判斷數組中是否包含我們給定的值;這樣以後就不用indexOf了

    3.4 實例數組的遍歷方法: entries(),keys() 和 values() 用於遍歷數組 返回一個遍歷器對象
            // keys()是對鍵名的遍歷:   對應索引
            // values()是對鍵值的遍歷: 對應值
            // entries()是對鍵值對的遍歷: 索引+值

4.數組擴展方法 [a, b, c]
    map映射, reduce彙總, filter過濾, forEach迭代

    1. map: 一個映射一個 
    // [100, 59, 22] => [及格, 不及格, 不及格]

    let score = [100, 59, 22];
    let res = score.map( item => item>60? '及格':'不及格' );console.log(res);

    2. reduce: 一堆變成一個

    // temp爲中間結果; 如果不設置,則爲第一個下標爲0的數
    let res1 = score.reduce(function(temp, item, index, arr) {
        if (index != arr.length - 1) {
            return item + temp;
        } else {
            return (temp + item) / arr.length;
        }
    }); 
    console.log(res1);

    3.filter: 保留我想要的結果
    let res2 = score.filter( item => item%11!=0);
    console.log(res2);

    4.forEach: 只是操作一下每一項; 返回值爲undefined
    let arr = [1,2,3,4]
    arr.forEach(function (item, index, arr) {
        // 這裏可以用外部變量接受 這裏面操作的值
        console.log(index +':'+ item);
    });
    console.log(res3); // undefined

對象的擴展

這裏主要介紹一下對象的多種遍歷方法;其他內容在擴展運算符...中總結.

1.for...in
    for...in循環遍歷對象自身的和繼承的可枚舉屬性(不含 Symbol 屬性)。

2.Object.keys(obj),values(obj),entries(obj)
    返回一個數組,包括對象自身的(不含繼承的)所有可枚舉屬性(不含 Symbol 屬性)的鍵名,值,鍵值對。

3.Object.getOwnPropertyNames(obj)
    返回一個數組,包含對象自身的所有屬性(不含 Symbol 屬性,但是包括不可枚舉屬性)的鍵名。

4.Object.getOwnPropertySymbols(obj)
    返回一個數組,包含對象自身的所有 Symbol 屬性的鍵名。

5.Reflect.ownKeys(obj)
    返回一個數組,包含對象自身的所有鍵名,不管鍵名是 Symbol 或字符串,也不管是否可枚舉。

擴展運算符...

1.擴展運算符是什麼?
    擴展運算符用三個點...表示: 相當於函數rest參數的逆運算, 可以將數組,對象中的成員序列化出來
    我這裏暫且把它理解爲一種運算符吧, 用來解析各種數據類型的成員

2.擴展運算符的使用場景?
    2.1 將數組成員轉爲一個逗號分隔的參數序列:
        這樣調用一些數組的API時; 可以直接傳一個...arr進去,省去了傳參的麻煩
        例1: console.log(...[1,2,3]); // 1 2 3
        例2: var date = new Date(...[2015, 01, 01]); 
            console.log(date); // 2015-01-31T16:00:00.000Z

    2.2 取代apply方法: 
        // ES5 的寫法
        let max1 = Math.max.apply(null, [14, 3, 77]);
        // ES6 的寫法
        let max2 = Math.max(...[14, 3, 77]);

    2.3 數組的深拷貝: 將對象全部拷貝一份,是一個獨立的內存空間
        let arr1 = [0, 1], arr2 = [...arr1]; // 用變量去接受經過擴展運算符運算的數組
        arr1[0] = 100; // 修改數組arr1
        console.log(arr1); // [ 100, 1 ] 發送改變
        console.log(arr2); // [ 0, 1 ]   未改變

    2.4 數組的合併
        注意: 合併操作是淺拷貝: 是對數組中對象成員的引用
        淺拷貝: (分爲簡單數據類型引用: 修改數據另一個不會變; 複雜數據類型引用: 修改後會改變)
        arr3 = [...arr1, ...arr2]; // 此時arr3 爲一個新數組; [ 100, 1, 0, 1 ],因爲內部成員都是數值,
        所以修改了arr1或者arr2中的元素也不會變

        那麼,如果數組中成員是對象; 則會改變成員屬性,合併生成的數組成員也會變
        const a1 = [{ foo: 1 }];
        const a2 = [{ bar: 2 }];
        const a3 = [...a1, ...a2];

        console.log(a3); // [ { foo: 1 }, { bar: 2 } ]
        a1[0].foo = 100;
        console.log(a3); // [ { foo: 100 }, { bar: 2 } ]

    2.5 可以和變量的解構賦值一起使用; 右邊是對象也是可以的
        let [first, second, ...rest] = [1,2,3,4,5,6];
        console.log(first); // 1
        console.log(second); // 2
        console.log(rest); // [3,4,5,6]

    2.6 還有與Array.from()方法類似的作用, 將 類似數組的對象和可迭代對象 轉爲真數組
        console.log([...'hello']); // [ "h", "e", "l", "l", "o" ]
        注意: 如果涉及到操作四個字節的 Unicode 字符的函數; 可以使用[...string], ...能夠識別;

    2.7 擴展運算符在對象中的使用
        // 解構賦值, 如果右邊數據是undefined或null 則解構會失敗
        let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; // x,1; y,2; z,{a:3, b:4}

        // 注意: 如果擴展運算符後面不是對象,則會自動將其轉爲對象。
        {...1}, {...true}, {...undefined}, {...null} 都會轉爲 空對象{}

函數擴展

函數參數設置默認值

語法: function(x=默認值x, y=默認值y); 當然也可以使用解構賦值,使用對象的形式設置,({x=xxx, y=yyy})
默認值參數放在括號尾部

1. ES5中設置默認值的方式

    function fn1(x, y) {
        y = y || "world"; // ES5中,在函數體內賦值一個默認值
        console.log(x, y);
    }
    fn1('hello'); // hello world
    fn1('hello', 'bob'); // hello bob
    fn1('hello', ''); // 傳空值時也使用默認值
    fn1('hello', false); // 傳false時也使用默認值

// ES6中 直接給()中參數賦默認值, 相當於初始化形參, 函數體內不允許let和const再次聲明
// ES6中會事先對參數y進行類型判斷: typeof y === 'undefined'; 是纔給默認值

    function fn2(x, y = 'ES6') {
        console.log(x, y);
    }
    fn2('learning'); //learning ES6 
    fn2('learning', ''); //learning 空也能輸出
    fn2('learning', false); //learning false 布爾值也可以

2. 構造函數中用來初始化 函數的屬性function Person(name='bob') {this.name = name};
    也是可以直接在()中傳默認值的

3.解構賦值形式給函數傳參
例1:
    function fn3({x, y = 100}) {
        // 函數的形參接受一個對象; 函數傳值也要傳一個對象;
        console.log(x, y);
    };

    // ES5中我們是傳一個對象,然後再定義變量 保存 對象中對應的屬性值
    // ES6可以直接在形參中 去接受對應的屬性值
    fn3({}); // undefined 100; 
    fn3();  // 保錯
例2:
    // 下面我們重寫一下, 注意:::這種方式的傳參是設置了對象解構賦值的默認值爲空對象,這樣直接調用便不會報錯
    function fn4 ({x, y = 101} = {}) {
    // 不傳值的情況下: 給函數一個默認參數: 空對象
    console.log(x, y);
    };
    fn4(); //undefined 101; 相當於 fn4({});

4.默認參數的作用域
    函數()中式一個單獨的作用域, ES6中函數體中的運算會先去()中找對應的變量進行運算

rest參數

ES6 引入 rest 參數(形式爲...變量名),用於獲取函數的多餘參數,這樣就不需要使用arguments對象了。
rest 參數搭配的變量是一個數組,參數都放在這個數組中。要使用的話,直接在函數體中遍歷即可,當然...rest放在()尾部

    舉個栗子:
        function add (...number) {
            let sum = 0;
            // number變量相當於一個存放形參的數組
            // 可以使用數組的方法,也就是說,我們可以當作數組來操作這個參數number
            // 基本方法 和 迭代方法都能使用
            for (let num of number) {
                sum += num;
            }
            return sum;
        } 
        console.log(add(1,2,3,4,5)); // 15

箭頭函數 () => {}

1.箭頭函數基本語法: 
    var 變量指向這個函數 = (參數1,參數2...) => {函數體大於一行時用大括號} 

理解: ES6中箭頭函數 相當於函數的簡寫,省略了function關鍵字,只有一個參數時還可以省略()
    箭頭左邊是 (參數) => 箭頭右邊是函數體(一行代碼可以省略大括號,直接寫返回值表達式) 
    //如果返回的是一個對象則加括號({對象})

2.常用的使用場景
    2.1 回調函數的簡化
        // 比如數組常用的迭代方法map: 常規方法是 傳入一個回調函數 function(x) {return x**2};
        var arr1 = [1,2,5,3,6,0];
        var result1 = arr1.map(x => x**2);
        // 排序
        var result2 = arr1.sort((a, b) => a - b); // [0,1,2,3,5,6]
        // 箭頭函數傳rest參數
        let arr3 = (...numbers) => numbers; // 自動將參數序列轉爲數組

    2.2 嵌套使用; 函數式編程
        例如:要實現將一個值 插入到數組 某個值的後面, 然後返回一個新數組
        function insert (value) {
            return {into: function (array) {
                return {after: function (after_value) {
                    // 起始位, 要刪除的項, 替換項
                    array.splice(array.indexOf(after_value) + 1, 0, value);
                    return array;
                }}
            }}
        }

        // 用箭頭函數實現; 簡化了很多
        // 聲明一個變量指向函數; 不要忘記對象用()包起來
        var insert = (value) => ({into: (array) => ({after: (after_value) => {
            array.splice(array.indexOf(after_value) + 1, 0, value);
            return array;
        }})});

        var res = insert(100).into([1, 2, 3]).after(2);
        console.log(res); // [ 1, 2, 100, 3 ]

3.箭頭函數注意事項; 

    1.this對象 ==> 指向定義時的對象, 而不是誰調用就指向誰了; 相當於固定了this指向
        箭頭函數根本沒有自己的this,導致內部的this就是外層代碼塊的this
        箭頭函數中的this 相當於ES5中 引用了外層函數的this; 在外層函數用var _this = this; 然後在箭頭函數中使用

    2.箭頭函數不能當作構造函數,不能使用new去聲明
    3.沒有arguments對象了, 使用rest參數替代
    4.不能使用yield, 不可以作爲生成器函數

函數的尾調用

函數的尾調用優化
function f(x){
    return g(x);
    // 函數f的最後一步是 調用函數g,這就叫尾調用。
}
function f(x){
    g(x);
    // 函數沒有明確返回值, 默認回返回undefined; 所以不是尾調用
    return undefined;
}

優化思路: 用內層函數的調用幀,取代外層函數的調用幀(保存了函數調用後的信息)
         相當於可以不用調用外層函數
注意:
    只有不再用到外層函數的內部變量,內層函數的調用幀纔會取代外層函數的調用幀,
    否則就無法進行“尾調用優化”。


尾遞歸優化
思路: 把所有用到的內部變量改寫成函數的參數
    1.參數設置成默認值的方式;  
    2.函數柯里化currying;意思是將多參數的函數轉換成單參數的形式
function Fibonacci (n , ac1 = 1 , ac2 = 1) {
    if( n <= 1 ) {return ac2};
    // 尾部調用自身; 並且參數中保存了上一次調用幀; 節省內存
    return Fibonacci (n - 1, ac2, ac1 + ac2);
}

console.log(Fibonacci(100)); 
// 注意:
// ES6 的尾調用優化只在嚴格模式下開啓,正常模式是無效的。

Set 和 Map 數據結構

set

Set數據結構: 可以理解爲沒有重複成員的一個類似數組的對象; 就叫集合吧
結構形式: {1, 2, 3, 4}

使用方法:
// 使用構造函數Set; 參數爲一個可遍歷的對象
const set = new Set([1,2,3,4]); // 實例化一個set; set結構是可迭代的對象
// 返滬值: {1, 2, 3, 4}

Set的屬性和方法

1. size: 返回set集合的大小, 即成員個數

2. Set的增刪查
// add(value):添加某個值,返回 Set 結構本身。
// delete(value):刪除某個值,返回一個布爾值,表示刪除是否成功。
// has(value):返回一個布爾值,表示該值是否爲Set的成員。
// clear():清除所有成員,沒有返回值。

3. Set遍歷成員; Set的遍歷順序就是插入順序。
// keys():返回鍵名的遍歷器
// values():返回鍵值的遍歷器
// entries():返回鍵值對的遍歷器
// forEach():使用回調函數遍歷每個成員, 回調參數爲鍵值和set自身

使用場景:

Set作爲一種數據結構,主要用來存放數據,並且內部成員不重複; 我們可以利用它的這個特性來做一些事.
1.比如去重
    let arr = [1,2,2,3,1,1,14];
    let str = 'dsadaedwdwa';
    console.log([...new Set(arr)]);
    console.log([...new Set(str)].join());

Map

其實Map有點類似 python中的字典結構;
ES6中Map類似於對象,也是鍵值對的集合,但是“鍵”的範圍不限於字符串,各種類型的值(包括對象)都可以當作鍵。
也就是說,Object 結構提供了“字符串: 值”的對應,Map 結構提供了“值 => 值”的對應

結構形式: Map: { [ 1, 2, 3 ] => '數組', 'name' => { name: 'bob' } }

使用方法:
使用構造函數Map 進行實例化; 參數爲雙元素的可迭代對象(能夠調用next方法的對象)

const newMap = new Map([['name', 'Blob'], ['age', 24]]);
// 也可實例化一個空map對象,通過set(值1, 值2)方法去添加成員

Map的屬性和方法: 基本與上面的Set一致

1.Map的增刪查
// set(key1, value1):添加一個鍵值對
// get(key); 獲取某個鍵值對
// delete(key):刪除某個鍵值對
// has(key):返回一個布爾值,表示該值是否爲Map的成員。
// clear():清除所有成員,沒有返回值。

常用場景:

可以使用擴展運算符...Map 可以實現與數組,對象,json對象的互轉;
我們定義固定格式的數據時可以使用, 也可以用來簡化判斷語句
#  set 中來判斷 code
const NEED_LOGIN_CODE_SET = new Set([10007,100011])
if (NEED_LOGIN_CODE_SET.has(code)) {  }
# map 取值
let buildEnv = process.env.VUE_APP_ENV
const K_V = [
    ['development', 'address1'],
    ['test', 'address2'],
    ['production', 'address3']
]
const URL_MAP = new Map(K_V)
export default URL_MAP.get(buildEnv)

for...of

for...of是ES6新增的語法;用來遍歷具有Iterator 接口的對象; 這種對象有next()方法,\
可以對自身進行遍歷,每一次調用便返回對應的值...

for...of循環可以使用的範圍包括數組、Set 和 Map 結構、某些類似數組的對象(比如arguments對象、DOM NodeList 對象)、Generator 對象,以及字符串。

class關鍵字: 類

  • ES5中的類實現

    // ES5中對象實例化的方法: 通過構造函數實例化

      function Func(x, y) {
          this.x = x;
          this.y = y;
      }
      // 給構造函數的原型添加屬性
      Func.prototype.toString = function() {
          // 把對象轉爲字符串
          return '(' + this.x + ',' + this.y + ')';
      }
      // 實例化一個對象
      var f = new Func(1,100);
      console.log(f.toString());
    
  • ES6的類實現

      // ES6中 通class來定義類; 其實就是構造函數的改寫,是js的語法更像後臺語言
      class Func1 {
          // 構造實例對象的方法; 相當於初始化
          constructor(x, y) {
              this.x = x;
              this.y = y;
          }
    
          // 添加類方法: toString()方法
          toString() {
              return '(' + this.x + ',' + this.y + ')';
          }
      }
    
      // 類: 就是一個函數, 本身爲一個構造函數; 也是通過new來實例化一個對象
      console.log(typeof Func1);
      console.log(Func1 === Func1.prototype.constructor); 
      let f1 = new Func1();
      console.log(f1.__proto__.constructor); // 省略了__proto__
    
      // 類的方法都定義在prototype對象上
    
  • ES6中的繼承

      // ES6面向對象寫法: class 替換 構造函數
    
      class User {
          // 構造器, 初始化
          constructor(name, pass) {
              this.name = name;
              this.pass = pass;
          }
          // 添加方法和屬性
          showName() {
              console.log(this.name);
          }
    
          showPass() {
              console.log(this.pass);
          }
    
      }
    
      // 在繼承 和 封裝上的優勢;  擴展性強...;  不用從0開始;; 可以使用前人造好的輪子
      // 繼承超類的屬性和方法
          class VipUser extends User {
              // 子類的初始化
              constructor(level, ...args) {
                  // 相當於調用父類的constructor(name, pass)
                  super(...args); 
                  // super作爲函數調用時,代表父類的構造函數
                  // super作爲對象時,在普通方法中,指向父類的原型對象;在靜態方法中,指向父類。
                  this.level = level;
              }
              // 方法
              showLevel() {
                  console.log(this.level);
              }
          }
          let vip = new VipUser(77, 'huhua', '123'); // 實例化
          vip.showLevel();
          vip.showName();
          vip.showPass();
    
          // 面向對象中類的應用實例
          // 比如一個組件: 就是一個 class 繼承一個組件
          // JSX: == babel;  browser.js
    

json簡寫模式

// 1.JSON對象: 兩個方法

let json = {"name": '哈哈', "sex": "女"}; // json對象鍵值必須是雙引號
let str1 = 'http://www.baidu.com?data=' + encodeURIComponent(JSON.stringify(json)) ; // JSON對象轉爲json字符串
console.log(str1);

let str2 = JSON.parse('{"a": 12, "b": "hello world"}');
console.log(str2); // JSON字符串 轉爲 對象
console.log(str2.a);

// 2.JSON簡寫
// 簡寫:  如果key值和value是一樣的; 直接寫一個就可以了...
// 可以省略一個funcion; 即 success: function(obj) {}  ==> 可以寫成 success(obj){}

模塊化加載方式

這裏說兩種常用的模塊加載方式

    - commonJS模塊
        CommonJS 模塊就是對象,輸入時必須查找對象屬性
        導出: 
            module.exports = { m1: 'xxx', m2: function(){}}
        導入: 
            const { m1, m2 } = require('模塊名')
        模塊輸出的是一個值的拷貝: 如果輸出一個值,模塊內部的變化就影響不到這個值
        模塊是運行時加載(整個對象全部加載)
        
    - ES6模塊化
        export導出模塊: 
            默認導出:export default Person(導入時可任意命名)
            單獨導出:export const name = 'xxoo'
            按需導出:export { age, name, sex } 前提是得先定義好
            改名導出:export { name as newName }
        import導入模塊:
            默認導入:import Person from "person"
            整體導入:import * as Person from "person"
            按需導入:import { age, name, sex } from "person"
            改名導入:import { name as newName } from "person"
            自執行導入:import "person"
            複合導入:import Person, { name } from "person"
        ES6 模塊是編譯時輸出接口(按需導入)
        ES6 模塊輸出的是值的引用, 即動態引用,並且不會緩存值,模塊裏面的變量綁定其所在的模塊
        如果原始模塊的變量變化,就會影響引入了這個變量的模塊中的值

未完待續...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章