溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

寫(xiě)JavaScript的小技巧有哪些

發(fā)布時(shí)間:2021-11-06 15:57:51 來(lái)源:億速云 閱讀:135 作者:iii 欄目:web開(kāi)發(fā)

本篇內(nèi)容介紹了“寫(xiě)JavaScript的小技巧有哪些”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

1. async / await

如果你還陷入到回調(diào)地獄中,那么你應(yīng)該回到2014年去開(kāi)發(fā)你的代碼。除非絕對(duì)必要(像第三方庫(kù)需要或者性能原因),否則不要使用回調(diào)。Promise是非常好的解決回調(diào)地獄,但是當(dāng)你的代碼變得越來(lái)越大時(shí),它也會(huì)變得不太好用。我現(xiàn)在的解決方案就是async / await,它極大提高了代碼可讀性以及簡(jiǎn)潔性。在所有使用Promise的地方你都可以替換成await,在你需要返回Promise對(duì)象,簡(jiǎn)單await它并返回,為了使它不報(bào)錯(cuò),你需要在定義函數(shù)的開(kāi)頭添加async。事實(shí)上,async / await就是Promise的語(yǔ)法糖。下面就是一個(gè)簡(jiǎn)單的例子:

async function getData() {
    const result = await axios.get('https://dube.io/service/ping')
    const data = result.data
    
    console.log('data', data)
    
    return data
}
getData()

await 操作符用于等待一個(gè)Promise 對(duì)象。它只能在異步函數(shù) async function 中使用。 async / await是屬于ES2017的內(nèi)容,所以可能需要babel編譯你的代碼。不過(guò)現(xiàn)在的主流瀏覽器都已經(jīng)支持了。

2. 異步控制流

經(jīng)常地,我們會(huì)遇到這樣的需求,請(qǐng)求獲取多個(gè)數(shù)據(jù)集并對(duì)每個(gè)數(shù)據(jù)集進(jìn)行各自處理或者需要等所有異步回調(diào)完成后返回一個(gè)值。遇到這些情況,我是這么處理的:

for…of

假設(shè)我們的頁(yè)面有多個(gè)Pokemon(口袋妖怪),需要獲取到它們的詳細(xì)的信息。我們不想等所有調(diào)用結(jié)束,特別是不知道它有多少次調(diào)用,我們僅想在它有調(diào)用返回時(shí)就更新我們的數(shù)據(jù)集??梢杂胒or…of來(lái)遍歷數(shù)組,在代碼塊里執(zhí)行async,這樣的話(huà),只有每次await執(zhí)行成功,代碼才會(huì)繼續(xù)往下執(zhí)行。
這里要著重說(shuō)明,這樣做可能會(huì)導(dǎo)致性能瓶頸(當(dāng)請(qǐng)求很多的時(shí)候),但像這樣做才能到達(dá)預(yù)期的效果。請(qǐng)看下面的例子:

import axios from 'axios'
let myData = [{id: 0}, {id: 1}, {id: 2}, {id: 3}]
async function fetchData(dataSet) {
    for(entry of dataSet) {
        const result = await axios.get(`https://ironhack-pokeapi.herokuapp.com/pokemon/${entry.id}`)
        const newData = result.data
        updateData(newData)
        
        console.log(myData)
    }
}
function updateData(newData) {
    myData = myData.map(el => {
        if(el.id === newData.id) return newData
        return el
    })
}
    
fetchData(myData)

這個(gè)代碼是能正常運(yùn)行,你可以輕松地復(fù)制它到 code sandbox運(yùn)行。

Promise.all

如果你想同時(shí)獲取所有口袋妖怪的詳情呢?你需要等待所有的請(qǐng)求的完成返回,這時(shí)簡(jiǎn)單使用Promise.all:

import axios from 'axios' 
let myData = [{id: 0}, {id: 1}, {id: 2}, {id: 3}]
async function fetchData(dataSet) {
    const pokemonPromises = dataSet.map(entry => {
        return axios.get(`https://ironhack-pokeapi.herokuapp.com/pokemon/${entry.id}`)
    })
    const results = await Promise.all(pokemonPromises)
    
    results.forEach(result => {
        updateData(result.data)
    })
    
    console.log(myData) 
}
function updateData(newData) {
    myData = myData.map(el => {
        if(el.id === newData.id) return newData
        return el
    })
}
    
fetchData(myData)

for...of 和 Promise.all都是ES6以后提出來(lái)的,請(qǐng)確保你的環(huán)境能運(yùn)行。

3. 解構(gòu)(Destructuring ) & 默認(rèn)值

我們接著上面的那個(gè)例子,提取一部分代碼:

const result = axios.get(`https://ironhack-pokeapi.herokuapp.com/pokemon/${entry.id}`)
const data = result.data

有一種簡(jiǎn)單的方法,解構(gòu)從數(shù)組,或?qū)ο笾蝎@取一些屬性(值)。像這樣:

const { data } = await axios.get(...)

注意當(dāng)解構(gòu)的時(shí)候,通常要賦給它一個(gè)默認(rèn)值。這樣確保你不會(huì)得到undefined以及你不用自己手動(dòng)地檢查變量。

const { id = 5 } = {}
console.log(id) // 5

這個(gè)技巧也被運(yùn)用到了函數(shù)參數(shù)中。例如:

function calculate({operands = [1, 2], type = 'addition'} = {}) {
    return operands.reduce((acc, val) => {
        switch(type) {
            case 'addition':
                return acc + val
            case 'subtraction':
                return acc - val
            case 'multiplication':
                return acc * val
            case 'division':
                return acc / val
        }
    }, ['addition', 'subtraction'].includes(type) ? 0 : 1)
}
console.log(calculate()) // 3
console.log(calculate({type: 'division'})) // 0.5
console.log(calculate({operands: [2, 3, 4], type: 'multiplication'})) // 24

這個(gè)例子起初看起來(lái)可能有點(diǎn)混亂,但是慢慢觀察。當(dāng)我們沒(méi)有給函數(shù)傳遞參數(shù)的時(shí)候,就會(huì)使用默認(rèn)值。一旦我們開(kāi)始傳遞參數(shù),僅會(huì)使用那些沒(méi)有傳遞的參數(shù)的默認(rèn)值。這樣,減少了你對(duì)異常狀態(tài)的處理。

4. 真值 & 假值

當(dāng)使用默認(rèn)值,就可以不用對(duì)現(xiàn)有值進(jìn)行一些額外的檢查。但是了解你的變量是真值還是假值是非常棒的。它能提高你的代碼擴(kuò)展性,更具有說(shuō)服力的以及簡(jiǎn)潔。我??吹较旅嬉恍?xiě)法:

if(myBool === true) {
  console.log(...)
}
// OR
if(myString.length > 0) {
  console.log(...)
}
// OR
if(isNaN(myNumber)) {
  console.log(...)
}

為了用這些簡(jiǎn)潔的判斷,你要充分理解js中真值,假值具體有哪些?這里概述一下:

假值:

1.字符串,但長(zhǎng)度為0
2.數(shù)字0
3.false
4.undefined
5.null
6.NaN

真值

1.空數(shù)組
2.空對(duì)象
3.其他有值的數(shù)據(jù).注意:在判斷真/假值,還應(yīng)該注意到你使用的是等于'==',還是全等'===',這經(jīng)常會(huì)導(dǎo)致bug。對(duì)我而言,經(jīng)常是數(shù)字0。

  1. 邏輯運(yùn)算與三元運(yùn)算符

邏輯運(yùn)算
邏輯運(yùn)算是基于多個(gè)表達(dá)式真假的判斷,注意到j(luò)s是惰性求值的策略。邏輯運(yùn)算一般返回一個(gè)布爾值。&& 和 || 運(yùn)算符會(huì)返回一個(gè)指定操作數(shù)的值。來(lái)看這里:

console.log(true && true) // true
console.log(false && true) // false
console.log(true && false) // false
console.log(false && false) // false
console.log(true || true) // true
console.log(true || false) // true
console.log(false || true) // true
console.log(false || false) // false

進(jìn)行的邏輯運(yùn)算,是按照下面的規(guī)則進(jìn)行的:

  • &&:第一個(gè)值為假值,則直接返回;如果為真值,則直接返回第二的值

  • ||:第一個(gè)值為真,則直接返回;如果為假,則直接返回第二的值。

console.log(0 && {a: 1}) // 0
console.log(false && 'a') // false
console.log('2' && 5) // 5
console.log([] || false) // []
console.log(NaN || null) // null
console.log(true || 'a') // true

三元運(yùn)算符

三元運(yùn)算符和邏輯運(yùn)算是相似的,但是它有3個(gè)部分:
condition ? expr1 : expr2

condition為進(jìn)行條件判斷的部分,將會(huì)得到真值或者假值
expr1為條件判斷為真時(shí)返回的值
expr2為條件判斷為假時(shí)返回的值

例如:

const lang = 'German'
console.log(lang === 'German' ? 'Hallo' : 'Hello') // Hallo
console.log(lang ? 'Ja' : 'Yes') // Ja
console.log(lang === 'French' ? 'Bon soir' : 'Good evening') // Good evening

6. Optional Chaining

過(guò)去在 Object 屬性鏈的調(diào)用中,很容易因?yàn)槟硞€(gè)屬性不存在而導(dǎo)致之后出現(xiàn)Cannot read property xxx of undefined的錯(cuò)誤。為了確認(rèn)需要向這樣處理:

let data
if(myObj && myObj.firstProp && myObj.firstProp.secondProp && myObj.firstProp.secondProp.actualData) data = myObj.firstProp.secondProp.actualData

這樣事冗余的,有一個(gè)新的提案的方法就是Optional Chaining,如下的形式:

const data = myObj?.firstProp?.secondProp?.actualData

我認(rèn)為它是檢查嵌套屬性最佳方法,代碼是如此的簡(jiǎn)潔。

這個(gè)特性可以說(shuō)是非常實(shí)用了,不過(guò)它現(xiàn)在處于 stage-1 階段。你可以在.babelrc文件中引入  @babel/plugin-proposal-optional-chaining 插件來(lái)使用它。

7. Class properties & binding

在JavaScript中函數(shù)綁定也是經(jīng)常的工作任務(wù)?,F(xiàn)在,大家應(yīng)該都是用箭頭函數(shù)自動(dòng)綁定this到這個(gè)類(lèi)上的(這里可能有歧義,首先箭頭函數(shù)里面是沒(méi)有this 和arguments的,這里的this把它當(dāng)成一個(gè)參數(shù)就行)。如果不用箭頭函數(shù),我們就需要在構(gòu)造函數(shù)綁定this,當(dāng)類(lèi)的方法很多的時(shí)候,這就顯得很冗余。因此,建議和提倡在類(lèi)里面用箭頭函數(shù)。如:

class Counter extends React.Component {
    constructor(props) {
        super(props)
        this.state = { count: 0 }
    }
    
    render() {
        return(
            <div>
                <h2>{this.state.count}</h2>  
                <button onClick={this._increaseCount}>Increase Count</button>
            </div>
        )
    }
    
    _increaseCount = () => {
        this.setState({ count: this.state.count + 1 })
    }
}

使用箭頭函數(shù)聲明類(lèi)中方法,它現(xiàn)在處于 stage-3 階段。你可以在.babelrc文件中引入 @babel/plugin-proposal-class-properties 插件來(lái)使用它。

8.使用parcel

作為一個(gè)前端,你也肯定會(huì)遇到打包和編譯代碼情況。似乎webpack成為標(biāo)準(zhǔn)已經(jīng)很長(zhǎng)時(shí)間了。我從webpack 1版本就開(kāi)始使用它了,當(dāng)然那是痛苦的。為了弄懂它所有的配置項(xiàng),我花了無(wú)數(shù)的時(shí)間才讓它正常打包和編譯。如果還有選擇的機(jī)會(huì),我是不會(huì)學(xué)習(xí)webpack的。恰巧幾個(gè)月前用了 parcel ,從來(lái)沒(méi)有發(fā)現(xiàn)配置可以如此簡(jiǎn)單!你不需要改動(dòng)什么便能得到你預(yù)期的效果,當(dāng)然你也可以修改配置項(xiàng)。它也是和webpack或babel一樣是可配置的,同時(shí)也是快速的。如果你不知道parcel,我明確建議你去學(xué)習(xí)它!

當(dāng)然,現(xiàn)在的主流標(biāo)準(zhǔn)還是webpack,webpack 4之后配置也簡(jiǎn)潔了,可以在學(xué)習(xí)parcel之后了解webpack,不說(shuō)了,又要開(kāi)始學(xué)習(xí)webpack 5

9. 寫(xiě)更多你自己的代碼

談到這個(gè)話(huà)題,我有很多想要分享討論的東西。對(duì)于css,許多人更傾向于使用第三方組件庫(kù)像bootstrap。對(duì)于JavaScript,我也看到很多人喜歡用jQuery以及一些小型的驗(yàn)證,滾動(dòng)的庫(kù)等等。雖然使用庫(kù)是方便的,但是我強(qiáng)烈建議你能自己實(shí)現(xiàn)它,而不是盲目的安裝npm包。當(dāng)它變成一個(gè)很大的庫(kù)或者框架的時(shí)候,整個(gè)團(tuán)隊(duì)都要構(gòu)建它,像 moment.js 或者 react-datepicker ,而且當(dāng)需求發(fā)生改變時(shí),你想要改動(dòng)它是困難的。所以,你應(yīng)該寫(xiě)更多自己的組件。這將會(huì)帶來(lái)三個(gè)重要的優(yōu)點(diǎn):

  1. 你很清楚你的代碼發(fā)生了什么

  2. 同時(shí),在你自己動(dòng)手實(shí)現(xiàn)的過(guò)程中,你也能真正開(kāi)始明白何為編程,以及庫(kù)中代碼是怎么運(yùn)行的

  3. 你能阻止你的代碼變得臃腫

在開(kāi)始,使用npm包是方便的。你能花更多時(shí)間去實(shí)現(xiàn)自己的業(yè)務(wù)邏輯。但當(dāng)那個(gè)包沒(méi)有按照預(yù)期運(yùn)行時(shí),你又換了一個(gè)包,這時(shí)不得不花更多時(shí)間去讀它的API才能使用它。當(dāng)是你自己實(shí)現(xiàn)的庫(kù)(組件)時(shí),你能百分百用自己的用例來(lái)定制化開(kāi)發(fā)它。

“寫(xiě)JavaScript的小技巧有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI