JavaScript闖關筆記

介紹

通過Array/Object/Function基礎類型編寫。

看到自己不瞭解的或者比較新穎的用法便會寫上。

不定時更新內容。

本文首發於我的個人網站: Timbok.top

目錄

Array

迭代方法

  1. every()方法對數組中的每一項運行給定函數,如果該函數對每一項都返回 true,則返回 true
const arr = [1,2,3,4];
const result = arr.every((item, index, arr)=>{
    return item > 2;
});
console.log(result); // false
  1. some()方法 對數組中的每一項運行給定函數,如果該函數對任一項返回 true,則返回 true
const arr = [1, 2, 3, 4];
const result = arr.some((item, index, arr)=>{
    return item > 2;
});
console.log(result); // true
  1. filter()方法對數組中的每一項運行給定函數,返回該函數會返回 true 的項組成的數組
const arr = [1, 2, 3, 4];
const result = arr.filter((item, index)=>{
    return item > 2;
});
console.log(result); // [3, 4]
  1. map()方法 對數組中的每一項運行給定函數,返回每次函數調用的結果組成的數組
const arr = [1, 2, 3, 4];
const result = arr.map((item, index)=>{
    return item * index;
});
console.log(result); // [0, 2, 6, 12]
  1. forEach()方法 對數組中的每一項運行給定函數。這個方法沒有返回值,本質上與使用 for 循環迭代數組一樣
const arr = [1, 2, 3, 4];
const result = arr.forEach((item, index)=>{
    // 執行某些操作
});
  1. reduce() 方法接收一個函數作爲累加器,數組中的每個值(從左到右)開始縮減,最終計算爲一個值。對空數組是不會執行回調函數的。
arr.reduce(callback,[initialValue])
  • callback (執行數組中每個值的函數,包含四個參數)

    • previousValue (上一次調用回調返回的值,或者是提供的初始值(initialValue))
    • currentValue (數組中當前被處理的元素)
    • index (當前元素在數組中的索引)
    • array (調用 reduce 的數組)
  • initialValue (作爲第一次調用 callback 的第一個參數。)

無返回值

const arr = [1, 2, 3];
arr.reduce((pev, item)=>{
    console.log(pev, item);
}, 0);
// 運行結果依次爲:0 1; undefined 2; undefined 3; 

有返回值

// pev爲上次迭代return的值
const arr = [1, 2, 3, 4];
const result = arr.reduce((pev, item)=>{
    console.log(pev);
    return pev + item;
}, 0);
console.log(result); // 10
// pev運行結果依次爲:0, 1, 3, 6

split和join

split(): 用於把一個字符串分割成字符串數組。

const string = '1, 2, 3, 4, 5';
string.split(','); // ["1", "2", "3", "4", "5"]

如果string爲空,則返回一個空數組

const string = '';
string.split(','); // [""]
string.split(); // [""]

join(): 用於把數組中的所有元素放入一個字符串。

const array = [1, 2, 3, 4, 5];
array.join(); // '1,2,3,4,5' 默認用,分割
array.join('|'); // "1|2|3|4|5" 默認用,分割

Object

object映射

定義一個object作爲配置對象來存放不同狀態,通過鏈表查找

const statusMap = {
    1:()=>{
        console.log('a1')
    },
    2:()=>{
        console.log('b2')
    }
    /* n.... */
}
// 執行
let a = 1 
statusMap[a]() // a1

這樣比較清晰,將條件配置與具體執行分離。如果要增加其他狀態,只修改配置對象即可。

Function

promise

ECMAscript 6 原生提供了 Promise 對象。

Promise 對象代表了未來將要發生的事件,用來傳遞異步操作的消息。

Promise 對象有以下兩個特點:

1、對象的狀態不受外界影響。Promise 對象代表一個異步操作,有三種狀態:

  • pending: 初始狀態,不是成功或失敗狀態。
  • fulfilled: 意味着操作成功完成。
  • rejected: 意味着操作失敗。

只有異步操作的結果,可以決定當前是哪一種狀態,任何其他操作都無法改變這個狀態。這也是 Promise 這個名字的由來,它的英語意思就是「承諾」,表示其他手段無法改變。

2、一旦狀態改變,就不會再變,任何時候都可以得到這個結果。Promise 對象的狀態改變,只有兩種可能:從 Pending 變爲 Resolved 和從 Pending 變爲 Rejected。只要這兩種情況發生,狀態就凝固了,不會再變了,會一直保持這個結果。就算改變已經發生了,你再對 Promise 對象添加回調函數,也會立即得到這個結果。這與事件(Event)完全不同,事件的特點是,如果你錯過了它,再去監聽,是得不到結果的。

簡單實現:

function _promise(params) {
  return new Promise((resolve, reject)=>{
    params>0 ? resolve('正數') : reject('負數');
  });
}
_promise(1).then(res=>console.log(res)) // 正數

_promise(-1).catch(res=>console.log(res)) // 負數

Promise.all

Promise.all可以將多個Promise實例包裝成一個新的Promise實例。同時,成功和失敗的返回值是不同的,成功的時候返回的是一個結果數組,而失敗的時候則返回最先被reject失敗狀態的值。

let p1 = new Promise((resolve, reject) => {
  resolve('成功了')
})

let p2 = new Promise((resolve, reject) => {
  resolve('success')
})

let p3 = Promise.reject('失敗')

Promise.all([p1, p2]).then((result) => {
  console.log(result)               //['成功了', 'success']
}).catch((error) => {
  console.log(error)
})

Promise.all([p1,p3,p2]).then((result) => {
  console.log(result)
}).catch((error) => {
  console.log(error)      // '失敗'
})

需要特別注意的是,Promise.all獲得的成功結果的數組裏面的數據順序和Promise.all接收到的數組順序是一致的,即p1的結果在前,即便p1的結果獲取的比p2要晚。這帶來了一個絕大的好處:在前端開發請求數據的過程中,偶爾會遇到發送多個請求並根據請求順序獲取和使用數據的場景,使用Promise.all毫無疑問可以解決這個問題。

Promise.race

顧名思義,Promse.race就是賽跑的意思,意思就是說,Promise.race([p1, p2, p3])裏面哪個結果獲得的快,就返回那個結果,不管結果本身是成功狀態還是失敗狀態。

let p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('success')
  },1000)
})

let p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('failed')
  }, 500)
})

Promise.race([p1, p2]).then((result) => {
  console.log(result)
}).catch((error) => {
  console.log(error)  // 打開的是 'failed'
})

async-await

ES2017 標準引入了async 函數,使得異步操作變得更加方便。

async 函數是什麼?一句話,它其實就是promiseGenerator 函數的語法糖。

async

async 用來表示函數是異步的,定義的函數會返回一個promise對象,可以使用then方法添加回調函數。

async function test() {
    return 123;
}

test().then(res => {
    console.log(res);// 123
});
若 async 定義的函數有返回值,return 123;相當於Promise.resolve(123),沒有聲明式的 return則相當於執行了Promise.resolve();

await

await 可以理解爲是 async wait 的簡寫。await 必須出現在 async 函數內部,不能單獨使用。

function notAsyncFunc() {
    await Math.random();
}
notAsyncFunc();//Uncaught SyntaxError: Unexpected identifier

await 後面可以跟任何的JS 表達式。雖然說 await 可以等很多類型的東西,但是它最主要的意圖是用來等待 Promise 對象的狀態被 resolved。如果await的promise對象會造成異步函數停止執行並且等待 promise 的解決,如果等的是正常的表達式則立即執行。

function sleep(second) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(' enough sleep~');
        }, second);
    })
}
function normalFunc() {
    console.log('normalFunc');
}
async function awaitDemo() {
    await normalFunc();
    console.log('something, ~~');
    let result = await sleep(2000);
    console.log(result);// 兩秒之後會被打印出來
}
awaitDemo();
// normalFunc
// VM4036:13 something, ~~
// VM4036:15  enough sleep~

希望通過上面的 demo,大家可以理解我上面的話。

錯誤處理

上述的代碼好像給的都是resolve的情況,那麼reject的時候我們該如何處理呢?

function sleep(second) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject('want to sleep~');
        }, second);
    })
}

async function errorDemo() {
    let result = await sleep(1000);
    console.log(result);
}
errorDemo();// VM706:11 Uncaught (in promise) want to sleep~

// 爲了處理Promise.reject 的情況我們應該將代碼塊用 try catch 包裹一下
async function errorDemoSuper() {
    try {
        let result = await sleep(1000);
        console.log(result);
    } catch (err) {
        console.log(err);
    }
}

errorDemoSuper();// want to sleep~
// 有了 try catch 之後我們就能夠拿到 Promise.reject 回來的數據了。

最後一點,await必須在async函數的上下文中的。

參考文章

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