尷尬,通篇使用 if


以給博客園頭部導航條鏈接添加圖標為例, 接下來看看如何分別使用對象、數組、Map 優化它的。

前置

1.接下來給頭部導航條添的圖標包含:

  • 博客園首頁
  • 新隨筆
  • 博客首頁
  • 聯系
  • 訂閱
  • 管理

2.這里封裝了一個返回 svg 的 function, 下文的 iconInSvg(icon) 即是調用了這個方法。

function iconInSvg(icon) {
    return `
            <svg class="icon" aria-hidden="true">
                <use xlink:href="${icon}"></use>
            </svg>

            `
}

用if羅列

博客園可以在 管理 -> 選項 界面禁用一些鏈接, 所以在添加 svg 圖標之前需要判斷鏈接是否存在。

import { cnblog, home, pens, contact, rss, admin } from '../constants/icons'
import { iconInSvg } from '@tools'

function setNavIcons() {
    // 博客園首頁
    if ($('#blog_nav_sitehome').length !== 0) {
        $('#blog_nav_sitehome').prepend(iconInSvg(cnblog))
    }
    // 博客首頁
    if ($('#blog_nav_myhome').length !== 0) {
        $('#blog_nav_myhome').prepend(iconInSvg(home))
    }
    // 新隨筆
    if ($('#blog_nav_newpost').length !== 0) {
        $('#blog_nav_newpost').prepend(iconInSvg(pens))
    }
    // 聯系
    if ($('#blog_nav_contact').length !== 0) {
        $('#blog_nav_contact').prepend(iconInSvg(contact))
    }
    // 訂閱
    if ($('#blog_nav_rss').length !== 0) {
        $('#blog_nav_rss').prepend(iconInSvg(rss))
    }
    // 管理
    if ($('#blog_nav_admin').length !== 0) {
        $('#blog_nav_admin').prepend(iconInSvg(admin))
    }
}

export default setNavIcons

可以發現代碼有大量重復,思考如何優化代碼。將選擇器和圖標抽離,以 key value 的形式一一對應,然后進行遍歷,執行相同的邏輯:先判斷再插入圖標。

使用對象

const items = {
    '#blog_nav_sitehome': cnblog,
    '#blog_nav_myhome': home,
    '#blog_nav_newpost': pens,
    '#blog_nav_contact': contact,
    '#blog_nav_rss': rss,
    '#blog_nav_admin': admin,
}

for (let selector in items) {
    if ($(selector).length !== 0) {
        $(selector).prepend(iconInSvg(items[selector]))
    }
}
  • js的對象本質上是鍵值對的集合(Hash結構),如果給對象設置為一個不為字符串的 key,會自動轉為字符串
  • 這里直接設置 key 為字符串,需要使用[]來取其值

使用數組

針對給頭部導航條添加圖標的場景,使用對象重寫這段代碼應該是最方便的解法了。接下來使用數組對象的形式將它重寫,並進行對比。

const items = [
    { selector: '#blog_nav_sitehome', icon: cnblog },
    { selector: '#blog_nav_myhome', icon: home },
    { selector: '#blog_nav_newpost', icon: pens },
    { selector: '#blog_nav_contact', icon: contact },
    { selector: '#blog_nav_rss', icon: rss },
    { selector: '#blog_nav_admin', icon: admin },
]

for (let { selector, icon } of items) {
    if ($(selector).length !== 0) {
        $(selector).prepend(iconInSvg(icon))
    }
}
  • 數組對象的形式描述的更加清晰
  • 在這種數據結構下,通過結構賦值能夠快速取到值
  • 循環體內的代碼更易讀

相比后面的 Map 數據結構,在這個場景下我更喜歡用數組對象的形式。

試試 Map

由於 js 對象的 key 本質上只能使用字符串,這就帶來一定的局限性。Map 結構提供了“值—值”的對應,是一種更完善的 Hash 結構實現。“鍵”的范圍不限於字符串,各種類型的值(包括對象)都可以當作鍵。接下來使用 Map 重寫這段代碼。

const items = new Map([
    ['#blog_nav_sitehome', cnblog],
    ['#blog_nav_myhome', home],
    ['#blog_nav_newpost', pens],
    ['#blog_nav_contact', contact],
    ['#blog_nav_rss', rss],
    ['#blog_nav_admin', admin],
])

for (let [selector, icon] of items.entries()) {
    if ($(selector).length !== 0) {
        $(selector).prepend(iconInSvg(icon))
    }
}

這個小項目雖然使用了 babel 來處理 es6,但 Map 無法像class那樣被轉化,class 是語法糖。Map 真是個好東西,如果你不需要兼容IE9以下的話。

總結

各有好處。需要注意的是,for of的效率沒有帶索引的遍歷方式高,當你需要遍歷大量數據時,最好換用其它方式遍歷數據。如有錯誤,歡迎指正!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM