es5/es6中新增的方法

ES5中的新增方法

ES5 中給咱們新增了一些方法,能夠很方便的操做數組或者字符串,這些方法主要包括:html

  • 數組方法
  • 字符串方法
  • 對象方法

1.1 數組方法

迭代(遍歷)方法:forEach()、map()、filter()、some()、every();ios

array.forEach(function(currentValue, index, arr))
  • 讓數組中每一個元素都執行一次 fn,至關於 for 循環
  • 不會佔用全局變量,結合箭頭函數賊舒服
  • currentValue:當前項的值
  • index:當前項的索引
  • arr:當前數組對象自己
array.map(function(currentValue, index, arr))
  • map() 方法會獲得一個新數組, 新數組中包含每次函數調用返回的結果
  • 它返回的是一個新數組
array.filter(function(currentValue, index, arr))
  • filter() 方法建立一個新的數組,新數組中的元素是經過檢查指定數組中符合條件的全部元素,主要用於篩選數組
  • 注意它直接返回一個新數組
  • currentValue: 當前項的值
  • index:當前項的索引
  • arr:當前數組對象自己
array.some(function(currentValue, index, arr))
  • some() 方法用於檢測數組中的元素是否知足指定條件,即查找數組中是否有知足條件的元素。
  • 它的返回值是布爾值,若是查找到這個元素,就返回true , 若是查找不到就返回false。
  • 若是找到第一個知足條件的元素,則終止循環,再也不繼續查找。
  • currentValue: 當前項的值
  • index:當前項的索引
  • arr:當前數組對象自己
array.every(function(currentValue, index, arr))
  • every() 方法檢測數組中的全部元素是否知足指定條件。
  • 全部的元素都返回true,結果纔是true

1.2 字符串方法

  • trim() 方法會從一個字符串的兩端刪除空白字符。
  • trim() 方法不影響原字符串自己,它返回的是一個新的字符串es6

    str.trim()

1.3 對象方法

  1. Object.keys() 用於獲取對象自身全部的屬性面試

    Object.keys(obj)
    • 效果相似 for…in
    • 返回一個由屬性名組成的數組axios

  2. Object.defineProperty() 定義對象中新屬性或修改原有的屬性。數組

    Object.defineProperty(obj, prop, descriptor)
    • obj:必需。目標對象
    • prop:必需。需定義或修改的屬性的名字
    • descriptor:必需。目標屬性所擁有的特性,以對象形式 { } 書寫promise

      • value: 設置屬性的值 默認爲undefined
      • writable: 值是否能夠重寫。true | false 默認爲false
      • enumerable: 目標屬性是否能夠被枚舉。true | false 默認爲 false
      • configurable: 目標屬性是否能夠被刪除或是否能夠再次修改特性 true | false 默認爲false數據結構

ES6的新增語法

1. let

  ES6中新增的用於聲明變量的關鍵字。併發

  • let聲明的變量只在所處於的塊級有效。異步

    if (true) { 
        let a = 10;
    }
    console.log(a) // a is not defined

    注意:使用 var 聲明的變量不具有塊級做用域特性,使用 let 關鍵字聲明的變量具備塊級做用域,能夠防止循環變量變成全局變量。

  • 不存在變量提高

    console.log(a); // a is not defined 
    let a = 20;
  • 暫時性死區

    var num = 10;
    if(true) {
        console.log(num); // num is not defined
        let num = 20;
    }
    // 在if的{}中不會向上一級查找num,由於在這個塊級做用域中用了let關鍵字聲明瞭num,變量num就和{}這個塊級進行了總體綁定,因此在聲明以前使用它會報錯
  • 經典面試題

    // 題1
    var arr = [];
    for(var i = 0; i < 2; i++) {
        arr[i] = function() {
            console.log(i);
        }
    }
    arr[0](); // 2
    arr[1](); // 2
    // 解析:變量 i 是全局的,函數執行時輸出的都是全局做用域下的 i 值。
    
    // 題2
    let arr = [];
    for(let i = 0; i < 2; i++) {
        arr[i] = function() {
            console.log(i);
        }
    }
    arr[0](); // 0
    arr[1](); // 1
    // 解析:每次循環都會產生一個塊級做用域,每一個塊級做用域中的變量都是不一樣的,函數執行時輸出的是本身上一級(循環產生的塊級做用域)做用域下的值。

2. const

  const 用於聲明常量,常量就是值(內存地址)不能變化的量。

  • 具備塊級做用域

    if (true) { 
         const a = 10;
    }
    console.log(a) // a is not defined
  • 聲明常量時必須賦值

    const PI; // Missing initializer in const declaration
  • 常量賦值後,值不能修改。

    const PI = 3.14;
    PI = 100; // Assignment to constant variable.
    const ary = [100, 200];
    ary[0] = 'a';
    ary[1] = 'b';
    console.log(ary); // ['a', 'b']; 
    ary = ['a', 'b']; // Assignment to constant variable.

let、const、var 的區別

  • 使用var聲明的變量,其做用域爲該語句所在的函數內,且存在變量提高現象
  • 使用let聲明的變量,其做用域爲該語句所在的代碼塊內,不存在變量提高
  • 使用const聲明的是常量,在後面出現的代碼中不能再修改該常量的值
var let const
函數級做用域 塊級做用域 塊級做用域
變量提高 不存在變量提高 不存在變量提高
值可更改 值可更改 值不可更改

3. 解構賦值

  ES6中容許從數組中提取值,按照對應位置,對變量賦值。對象也能夠實現解構。

  按照必定模式,從數組中或對象中提取值,將提取出來的值賦值給另外的變量。

 3.1 數組解構

  • 若是解構不成功,變量的值爲undefined。

    let [a, b, c] = ['pink', 'yellow', 'blue']; //正常解構賦值
    console.log(a, b, c);
    let [foo] = [];
    let [bar, foo] = [1];
    let [, c] = ['red', 'yellow'];  //選擇性解構賦值

 3.2 對象解構

  • 使用變量的名字匹配對象的屬性,匹配成功,將對象屬性的值賦值給變量。

    let {name, age} = {name: 'andy', age: 18};  // 正常解構賦值
    console.log(name, age); // andy 18
    ​
    let {name: myName, age: myAge} = {name: 'andy', age: 18}; //myName myAge 屬於別名
    ​
    let {name = 'lily', age } = {name: 'andy', age: 18};  //給name設置了默認值'lily'

4. 箭頭函數

  • ES6中新增的定義函數的方式。

    // 語法:() => {}
    const fn = () => {}
    fn();
  • 函數體中只有一句代碼,且代碼的執行結果就是返回值,能夠省略大括號

    function sum(a, b) {
        return a + b;
    }
    const sum = (a, b) => a + b;
    sum(10, 20);
  • 若是形參只有一個,能夠省略小括號

    function fn (v) {
        return v;
    } 
    const fn = v => v;
  • 箭頭函數不綁定 this 關鍵字,它的 this 值是繼承自它的父做用域的,因此箭頭函數不能做爲構造函數

    箭頭函數的 this 值是詞法做用域,也就是說它在定義的時候就被指定了的,並且也不會隨着它調用方法的改變而改變。因此箭頭函數中的this,指向的是函數定義位置的上下文this

    const obj = {name: 'andy'};
    function fn() {
        console.log(this); // obj
        return () => {
            console.log(this); // obj
        }
    }
    const resFn = fn.call(obj);
    resFn();
  • 面試題解析:

    var obj = {
        age: 20,
        say: () => {
            console.log(this.age)
        }
    }
    obj.say(); // undefined
    // 解析:箭頭函數中沒有本身的this,它的this指向箭頭函數定義區域的this。此例中的箭頭函數定義在了obj這個對象中,它是一個對象,不能產生做用域,因此這個箭頭函數被定義在了全局做用域下,因此在調用這個方法的時候this指向window

5. 剩餘參數

  • 剩餘參數語法容許咱們將一個不定數量的參數表示爲一個數組。

    const sum = (...args) => {
        let total = 0;
        args.forEach(item => total += item);
        return total;
    }
    console.log(sum(10, 20)); // 30
    console.log(sum(1, 2, 3, 4)); // 10
  • 剩餘參數和解構配合使用

    let students = ['andy', 'jack', 'lily'];
    let [s1, ...s2] = students;
    console.log(s1, s2); // 'andy', ['jack', 'lily']

6. ES6的內置對象擴展

 6.1 擴展運算符(展開語法)

  • 擴展運算符能夠將數組或者對象轉爲用逗號分隔的參數序列。

    let ary = [1, 2, 3];
    ...ary  // 1, 2, 3
    console.log(...ary);    // 1 2 3
  • 擴展運算符能夠應用於合併數組

    // 方法一 
    let ary1 = [1, 2, 3];
    let ary2 = [3, 4, 5];
    let ary3 = [...ary1, ...ary2];
    // 方法二 
    ary1.push(...ary2);
  • 將類數組或可遍歷對象轉換爲真正的數組

    let oDivs = document.getElementsByTagName('div'); 
    oDivs = [...oDivs];

 6.2 構造函數方法:Array.from()

  • 將類數組或可遍歷對象轉換爲真正的數組

    let arrayLike = {
        '0': 'a',
        '1': 'b',
        '2': 'c',
        length: 3
    }; 
    let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
  • 方法還能夠接受第二個參數,做用相似於數組的map方法,用來對每一個元素進行處理,將處理後的值放入返回的數組。

    let arrayLike = { 
        "0": 1,
        "1": 2,
        "length": 2
    }
    let newAry = Array.from(aryLike, item => item *2)

 6.3 實例方法:find()

  • 用於找出第一個符合條件的數組成員,若是沒有找到返回undefined

    let ary = [
        { id: 1, name: 'andy' },
        { id: 2, name: 'lily' }
    ]
    let target = ary.find(item => item.id === 2);

 6.4 實例方法:findIndex()

  • 用於找出第一個符合條件的數組成員的位置,若是沒有找到返回-1

    let ary = [1, 5, 10, 15];
    let index = ary.findIndex((value, index) => value > 9); 
    console.log(index); // 2

 6.5 實例方法:includes()

  • 判斷字符串是否包含另外一個字符串,傳統的 js 方法: indexOf 返回值是否等於 -1 ,若是等於 -1說明不包含
  • es6 中提供了方法 includes() 返回布爾值,表示是否包含給定的值。

    [1, 2, 3].includes(2) // true 
    1, 2, 3].includes(4) // false
    ​
    let s = 'hello world'
    s.includes('hello', 6) // false  第一個參數是須要匹配的數據,第二個參數是從第幾個開始

7. 模板字符串

  • ES6新增的建立字符串的方式,使用反引號定義 ``。
  • 模板字符串中能夠解析變量。

    let name = '張三'; 
    let sayHello = `hello,my name is ${name}`; // hello, my name is zhangsan
  • 模板字符串中能夠保留空格和換行

    let result = { 
        name: 'zhangsan', 
        age: 20,
        sex: '男' 
    } 
    let html = ` <div>
        <span>${result.name}</span>
        <span>${result.age}</span>
        <span>${result.sex}</span>
    </div> `;
  • 在模板字符串中能夠調用函數。

    const sayHello = function () { 
       return '哈哈哈哈 追不到我吧 我就是這麼強大';
    }; 
    let greet = `${sayHello()} 哈哈哈哈`;
    console.log(greet); // 哈哈哈哈 追不到我吧 我就是這麼強大 哈哈哈哈

8. String的擴展方法

 8.1 實例方法:startsWith()和endsWith()

  • startsWith():表示參數字符串是否在原字符串的頭部,返回布爾值
  • endsWith():表示參數字符串是否在原字符串的尾部,返回布爾值

    let str = 'Hello world!';
    str.startsWith('Hello') // true 
    str.endsWith('!')       // true

 8.2 實例方法:repeat()

  • repeat() 方法表示將原字符串重複n次,返回一個新字符串。

    'x'.repeat(3)      // "xxx" 
    'hello'.repeat(2)  // "hellohello"

9.Set數據結構

  ES6 提供了新的數據結構 Set。它相似於數組,可是成員的值都是惟一的,沒有重複的值。

  • Set自己是一個構造函數,用來生成 Set 數據結構。

    const s = new Set();
  • Set函數能夠接受一個數組做爲參數,用來初始化。

    const set = new Set([1, 2, 3, 4, 4]);
  • 例如:利用set去重,獲得一個新數組

    let set = new Set([1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1])
    console.log(set)
    console.log([...set])

    注:set 去重以後獲得的 set 類型的數據,因此還得把這個 set 數據類型轉換成數組類型,這個時候又能夠用到展開符這個好東西了

    實例方法

    • add(value):添加某個值,返回 Set 結構自己
    • delete(value):刪除某個值,返回一個布爾值,表示刪除是否成功
    • has(value):返回一個布爾值,表示該值是否爲 Set 的成員
    • clear():清除全部成員,沒有返回值
    const s = new Set();
    s.add(1).add(2).add(3); // 向 set 結構中添加值 
    s.delete(2)             // 刪除 set 結構中的2值 
    s.has(1)                // 表示 set 結構中是否有1這個值 返回布爾值 
    s.clear()               // 清除 set 結構中的全部值
  • Set 結構的實例與數組同樣,也擁有 forEach 方法,用於對每一個成員執行某種操做,沒有返回值。

    s.forEach(value => console.log(value))

10. Promise

  promise 用於更優雅的處理異步請求,其實就是對於回調函數的另外一種寫法,能夠幫助咱們避免回調地獄

  回調地獄:好比第二個請求依賴第一個請求的結果進行請求,第三個請求依賴第二個,這樣一層一層嵌套,。。。​爲了解決回調順序的不肯定性以及地獄,就有了 promise 機制。

  1. Promise 通常來說是一個對象, .then方法其實就是 promise 對象的一個
  2. Promise 構造函數接受一個函數做爲參數,在這個函數中,能夠進行異步的操做的代碼
  3. 在這個函數中執行完成異步操做以前,並非要調用用戶提供的回調函數(不關心回調究竟是什麼),而是在這個函數中,異步完成以後,只須要去修改當前的promise 的狀態
  4. Promise的狀態:

    • pendding :掛起,當前 promise 執行的任務,正在執行中
    • fullfilled: 完成,當前 promise 對象執行的任務,已經完成,而且是成功狀態
    • rejected: 完成,當前 promise 對象執行的任務,已經完成,而且是失敗的狀態
  5. Promise 對象的 .then 方法中接收到的成功的回調函數,會在當前的 promise 對象處於成功(fullfilled)狀態的時候自動執行;Promise對象的 .then 方法中接收到的失敗的回調函數,會在當前的 promise 對象處於失敗(rejected)狀態的時候自動執行.
  6. resolve 是一個函數,調用這個函數,就能夠把當前 promise 對象標記成功reject 也是一個函數,調用這個函數,能夠把當前 promise 對象標記失敗

    var p = new Promise(function(resolve, reject) {
        resolve() // 成功時調用
        reject() // 失敗時調用
    });
    p.then(function(res) {
        // 從resolve獲得正常結果
    }, function(res) {
        // 從reject獲得錯誤信息
    })

    resolve 和 reject在調用的時候,能夠傳遞數據,這個數據會最終被傳遞到成功或者失敗的回調函數中。

    // 封裝一個支持Promise APi的延時函數
    function timeOut(time){
        return new Promise(function(resolve, reject){
            setTimeout(function(){
                // 這個回調函數中,不須要涉及任何具體的業務操做
                // resolve(123); // 可傳遞數據,這個數據會最終被傳遞到成功回調函數中
                reject();
            }, time);
        });
    }
  7. 在 then 方法中,咱們能夠直接return 數據而不是 Promise 對象,在後面的 then 中就能夠接收到數據了。
    then 參數中的函數返回值:
      1. 返回 Promise 實例對象:返回的該實例對象會調用下一個 then

      2. 返回普通值:返回的普通值會直接傳遞給下一個 then,經過 then 參數中函數的參數接受該值

    timeOut(1000)
    .then(num => {
        console.log(num + '這是1s後打印的內容')
        return timeOut(1000)
    })
    .then(num => {
        console.log(num + '這是2s後打印的內容')
        return timeOut(1000)
    })
    .then(num => {
        console.log(num + '這是3s後打印的內容')
        return timeOut(1000)
    })
  8. 語法
  • 語法一:

    promise.then(
        function() {
            console.log('成功的回調')
        },
        function() {
            console.log('失敗的回調')
        }
    )
  • 語法二:

    Promise
    .then(function() {
        console.log('成功的回調')
    })
    .catch(function() {
        consloe.log('失敗的回調')
    })

    語法二和語法一的效果同樣。不過它還有另一個做用:在執行 resolve 的回調(也就是上面then中的參數)時,若是拋出異常了(代碼出錯了),那麼並不會報錯卡死,而是會進到這個catch方法中。

  9. promise 的其餘用法

  • Promise.all: 只有當傳入的全部 promise 的結果爲 reslove,纔會執行這個 all 的回調函數(即觸發 then 方法執行裏面的代碼),不然只要有一個是 reject,就會執行 catch 方法。

    Promise
        .all([t1, t2, t3, t4, t5])
        .then(function(){
            console.log("全部異步操做完成了");
        }
        .catch(function() {
            console.log("嗷嗷~~~有操做出錯了");
        })
    )
  • Promise.race:由第一個 promise 返回的狀態決定,若是第一個 promise 返回的結果爲 reslove 就會執行這個race的回調

    Promise.race([t1, t2, t3, t4, t5]).then(function(){
        console.log("有一個異步率先完成了");
    })

  經常使用API:

  • .then() 獲得異步任務的成功信息
  • .catch() 獲取異常信息
  • .finally() 成功與否都會執行(還不是正式標準)
  • Promise.all() 併發處理多個異步任務,全部任務都執行完成才能獲得結果
  • Promise.race() 只要有一個任務完成就能獲得結果

    Promise.all([p1, p2, p3]).then(res => {
        console.log(res); //三個結果的數組
    })
    Promise.race([p1, p2, p3]).then(res => {
        console.log(res);
    })
  • 示例:基於Promise處理Ajax請求:

    function queryData(url) {
    return new Promise(function(resolve, reject){
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
            if(xhr.readystate !== 4) return;
            if(xhr.readystate === 4 && xhr.status === 200){
                resolve(xhr.responseText);
            }else{
                reject('出錯了');
            }
        }
        xhr.open('get', url);
        xhr.send(null);
    })
    }
    queryData('http://localhost:3000/data')
    .then(function(res){
        console.log(res);
    }, function(err){
        console.log(err)
    })
    ​
    //發送屢次請求
    queryData('url1')
    .then(function(data){
        return queryData('url2');
    })
    .then(function(data){
        return queryData('url3');
    })
    .then(function(data){
        console.log(data);
    })

  這裏順便叨叨一下 Promise 的語法糖:async/await 的基本用法

  • async 關鍵字用於函數上(async 函數的返回值是 Promise 實例對象)
  • await 關鍵字用於 async 函數中(await 能夠獲得異步的結果)

    async function queryData(id){
        const ret = await axios.get('/data');
        return ret;
    }
    queryData.then(ret => {
        console.log(ret);
    })

    使用async後,代碼變得更簡潔,代碼的邏輯和數據流都變得更加清晰。因爲 async 的原理仍是以 Promise 爲基礎,因此部分時候,async 是要和 Promise 配合使用的,它並不能徹底脫離 Promise 獨立運行;await 必須在 async 函數裏使用,不能單獨使用。

  • 多個異步請求的場景

    async function queryData(id){
        const info = await axios.get('/async1');
        const ret = await axios.get(`/async2?info=`+info.data);
        return ret;
    }
    queryData.then(ret => {
        console.log(ret);
    })

11. 模塊化

  模塊化就是把單獨的一個功能封裝到一個模塊(文件)中,模塊之間相互隔離,可是能夠經過特定的接口公開內部成員,也能夠依賴別的模塊。

  模塊化開發的好處:方便代碼的重用,從而提高開發效率,而且方便後期的維護。

  ES6默認導出與默認導入

  • 默認處處語法 export default 默認導出的成員
  • 默認導入語法 import 接收名稱 from ‘模塊標識符’

    //當前文件模塊爲 m1.js//定義私有成員a和c
    let a = 10;
    let c = 20;
    let d = 30;
    function show(){}
    ​
    //將本模塊中的私有成員暴露出去,供其餘模塊使用
    export default {
        a,
        c,
        show
    }
    ​
    //導入模塊成員
    import m1 from './m1.js'
    ​
    console.log(m1)
    //打印輸出的結果爲{a: 10, b: 20, show: [function: show]}
    //外界訪問不到d,由於它沒有被暴露出去

   注意:每一個模塊中,只容許使用惟一的一次 export default,不然會報錯

  按需導出與按需導入

  • 默認導出語法export let s1 = 10
  • 默認導入語法import { s1 } from '模塊標識符'

    //當前文件模塊爲 m1.js
    export let s1 = 'aaa'
    export let s2 = 'bbb'
    export function say = function(){}
    ​
    //導入模塊成員
    import {s1, s2 as ss2, say} from './m1.js'
    console.log(s1); // aaa
    console.log(ss2); // bbb
    console.log(say); // [function: say]

   注意:每一個模塊中,可使用屢次按需導出

  直接導入並執行模塊代碼

  • 只執行模塊中的代碼,並不須要獲得模塊中向外暴露的成員,此時能夠直接導入並執行模塊代碼。

    //當前文件模塊爲 m2.js
    //在當前模塊中執行一個 for 循環操做
    for(let i = 0; i < 3; i++) {
        console.log(i);
    }
    ​
    //直接導入並執行模塊代碼
    import './m2.js'
相關文章
相關標籤/搜索