1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        8 種技巧讓你編寫更簡潔的 JavaScript 代碼

        共 9118字,需瀏覽 19分鐘

         ·

        2022-05-16 04:07

        在本文中,我們將介紹 8 種不同的技術(shù)來幫助您編寫更簡潔的 JavaScript 代碼。

        現(xiàn)在讓我們討論每種技術(shù),一次一個。

        純函數(shù)

        純函數(shù)是在給定相同輸入的情況下始終返回相同輸出的函數(shù)。除了提供的輸入之外,它不依賴于任何外部變量,也不影響/更改任何外部變量。擁有純函數(shù)使測試變得更加容易,因為它們使測試變得超級容易,因為您可以隨時存根/模擬輸入并測試您的預(yù)期值。讓我們看看下面的例子

        let?name?=?"Yu?DongSu";
        const?splitName?=?()?=>?{
        ??name?=?name.split('?');
        }
        name?=?splitName();
        console.log(name);?//?outputs?[?'Yu',?'DongSu'?]

        雖然上面的代碼看起來很合適。不是開玩笑。這是因為該splitName函數(shù)依賴于一個名為的外部變量name,如果其他人開始更改此變量,該函數(shù)將splitName開始提供不同的輸出。使它成為一個非純函數(shù),因為我們?nèi)匀粫{(diào)用splitName()它,但輸出會有所不同。

        讓我們把它改成一個純函數(shù),看看它是什么樣子的:

        let?name?=?"Yu?DongSu";
        const?splitName?=?(nameString)?=>?{
        ??return?nameString.split('?');
        }
        name?=?splitName(name);
        console.log(name);?//?outputs?[?'Yu',?'DongSu'?]

        通過上述更改,splitName現(xiàn)在是一個純函數(shù),因為:

        • 它僅依賴于輸入(nameString輸入)。
        • 它不會更改/重新分配任何外部變量

        更少或命名參數(shù)

        使用函數(shù)時,我們經(jīng)常使用位置參數(shù),這些參數(shù)必須在函數(shù)聲明中聲明時提供。例如,在 call中,如果不提供and arithmaticOp(num1, num2, operator),我們就無法提供operator參數(shù)。雖然這適用于這個例子,但對于許多功能來說,這會成為一個問題。考慮以下示例:

        const?createButton?=?(title,?color,?disabled,?padding,?margin,?border,?shadow)??=>?{
        ??console.log(title,?color,?disabled,?padding,?margin,?border,?shadow)
        }

        查看上面的代碼,您已經(jīng)可以看到,如果我們想在調(diào)用createButton+ 時將任何參數(shù)設(shè)為可選(使用默認(rèn)值),那將是一場災(zāi)難,可能看起來像這樣:

        createButton('Sudongyu?er',?undefined?/*?optional?color?*/,?true?,'2px....',?undefined??/*?optional?margin*/);

        你可以看到上面的語句看起來一點也不干凈。此外,從函數(shù)調(diào)用語句中很難看出哪個參數(shù)對應(yīng)于函數(shù)的哪個參數(shù)。所以這是我們可以遵循的做法:

        • 如果我們有 2 個或更少的參數(shù),我們可以將它們保留為位置參數(shù)
        • 否則,我們提供一個帶有鍵值對的對象

        讓我們在上面的例子中使用這個技術(shù),看看它是什么樣子的:

        const?createButton?=?({title,?color,?disabled,?padding,?margin,?border,?shadow})??=>?{
        ??console.log(title,?color,?disabled,?padding,?margin,?border,?shadow)
        }

        createButton({
        ??title:?'Sudongyu?er',
        ??disabled:?true,
        ??shadow:?'2px....'
        });

        請注意,調(diào)用createButton函數(shù)的語句現(xiàn)在更簡潔了。我們可以很容易地看到鍵值對中的哪個值對應(yīng)于函數(shù)的參數(shù)。耶耶!??

        對象/數(shù)組解構(gòu)

        考慮以下 javascript 示例,其中我們從對象中獲取一些屬性并分配給它們的各個變量:

        const?user?=?{
        ??name:?'Sudongyu',
        ??email:?'hi@xxx',
        ??designation:?'Software?Architect',
        ??loves:?'The?Code'
        }

        const?name?=?user.name;
        const?email?=?user.email;
        const?loves?=?user.loves;

        在上面的例子中,多次使用這個user.*符號是非常令人惡心的。這就是對象解構(gòu)的用武之地。我們可以使用對象解構(gòu)將上面的示例更改如下:

        const?user?=?{
        ??name:?'Sudongyu',
        ??email:?'hi@xxx',
        ??designation:?'Software?Architect',
        ??loves:?'The?Code'
        }

        const?{name,?email,?loves}?=?user;

        看!好多了。對?讓我們考慮另一個例子:

        const?getDetails?=?()?=>?{
        ??return?['xxx',?'sudongyu',?'Some?Street',?'Some?City',?'Some?Zip',?'Some?Country'];
        }

        const?details?=?getDetails();
        const?uName?=?details[0];
        const?uEmail?=?details[1];
        const?uAddress?=?`${details[2]},?${details[3]},?${details[4]},?${details[5]}`;
        const?uFirstName?=?uName.split('?')[0];
        const?uLastName?=?uName.split('?')[1];

        啊。我什至討厭編寫上述示例的代碼??。雖然不得不這樣做。您可以看到代碼看起來非常怪異且難以閱讀。我們可以使用 Array Destructuring 將其寫得更簡潔,如下所示:

        const?getDetails?=?()?=>?{
        ??return?['xxx',?'sudongyu',?'Some?Street',?'Some?City',?'Some?Zip',?'Some?Country'];
        }
        const?[uName,?uEmail,?...uAddressArr]?=?getDetails();
        const?uAddress?=?uAddressArr.join(',?');
        const?[uFirstName,?uLastName]?=?uName.split('');
        console.log({
        ??uFirstName,
        ??uLastName,
        ??uEmail,
        ??uAddress
        });

        你可以看到這有多干凈??

        避免硬編碼值

        /**
        ?*?阿巴阿巴
        ?*?
        ?*?
        ?*?
        ?*?
        ?*?
        ?*/


        setInterval(()?=>?{
        ??//?do?something
        },?86400000);
        //?WHAT?IS?THIS?86400000???????

        看代碼的人可能不知道這個數(shù)字代表什么,它是如何計算的,以及它背后的業(yè)務(wù)邏輯是什么。我們可以創(chuàng)建一個常量,而不是硬編碼這個值,如下所示:

        const?DAY_IN_MILLISECONDS?=?3600?*?24?*?1000;?//?86400000

        setInterval(()?=>?{
        ??//?do?something
        },?DAY_IN_MILLISECONDS);
        //?now?this?makes?sense

        讓我們考慮另一個例子:

        const?createUser?=?(name,?designation,?type)?=>?{
        ??console.log({name,?designation,?type});
        }

        createUser('SudongYu',?'Software?Architect',?'1');
        //?WHAT?IS?this?'1'????

        查看調(diào)用createUser方法。閱讀代碼的人很難理解這'1'代表什么。即type這是什么用戶。因此,我們可以創(chuàng)建一個我們擁有的用戶類型的對象映射,而不是在這里對值進行硬編碼'1',如下所示:

        const?USER_TYPES?=?{
        ??REGULAR_EMPLOYEE:?'1'
        }

        const?createUser?=?(name,?designation,?type)?=>?{
        ??console.log({name,?designation,?type});
        }

        createUser('Sudongyu',?'Software?Architect',?USER_TYPES.REGULAR_EMPLOYEE);
        //?smoooooooth???

        避免使用簡寫變量名

        速記變量在需要它們的地方才有意義。就像如果你有像xand這樣的位置坐標(biāo)y,那是可行的。p但是,如果我們在沒有上下文的情況下創(chuàng)建像,t之類的變量c,那么真的很難閱讀、跟蹤和維護這樣的代碼。例如看這個例子:

        const?t?=?25;

        let?users?=?['Sudongyuer',?'xxx'];

        users?=?users.map((user)?=>?{
        ??/**
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*?
        ???*/


        ??return?{
        ????...user,
        ????tax:?user.salary?*?t?/?100?//?WHAT?IS?`t`?again????
        ??}
        })

        上面的例子表明,現(xiàn)在開發(fā)人員/讀者必須一直向上滾動或轉(zhuǎn)到定義來嘗試?yán)斫膺@個變量是什么。因此是不干凈的代碼??。這也稱為對變量進行思維導(dǎo)圖,其中只有作者知道它們的含義。因此,我們可以給它一個適當(dāng)?shù)拿Q,而不是簡寫變量名稱,如下所示:

        const?taxFactor?=?25;

        let?users?=?['Sudongyuer',?'xxx'];

        users?=?users.map((user)?=>?{
        ??//?some?code
        ??return?{
        ????...user,
        ????tax:?user.salary?*?taxFactor?/?100
        ??}
        })

        現(xiàn)在這更有意義了。

        使用 Object.assign() 設(shè)置默認(rèn)對象值

        在某些情況下,您可能希望從另一個對象創(chuàng)建一個新對象,如果源對象沒有它們,則提供一些默認(rèn)值??紤]以下示例:

        const?createButton?=?({title,?color,?disabled,?padding})??=>?{
        ??const?button?=?{};
        ??button.color?=?color?||?'#333';
        ??button.disabled?=?disabled?||?false;
        ??button.title?=?title?||?'';
        ??button.padding?=?padding?||?0;
        ??return?button;
        }

        const?buttonConfig?=?{
        ??title:?'Click?me!',
        ??disabled:?true
        }

        const?newButton?=?createButton(buttonConfig);
        console.log('newButton',?newButton)

        Object.assign()如果源對象提供了默認(rèn)屬性,我們可以使用如下方式覆蓋默認(rèn)屬性,而不是做所有這些:

        const?createButton?=?(config)??=>?{
        ??return?{
        ????...{
        ??????color:?'#dcdcdc',
        ??????disabled:?false,
        ??????title:?'',
        ??????padding:?0
        ????},
        ????...config?
        ??};
        }

        const?buttonConfig?=?{
        ??title:?'Click?me!',
        ??disabled:?true
        }

        const?newButton?=?createButton(buttonConfig);
        console.log('newButton',?newButton)

        使用方法鏈(尤其是類)

        如果我們知道類/對象的用戶將一起使用多個函數(shù),則方法鏈接是一種很有用的技術(shù)。您可能已經(jīng)在諸如 moment.js 之類的庫中看到了這一點。讓我們看一個例子:

        class?Player?{
        ??constructor?(name,?score,?position)?{
        ????this.position?=?position;
        ????this.score?=?score;
        ????this.name?=?name;
        ??}
        ??setName(name)?{
        ????this.name?=?name;
        ??}
        ??setPosition(position)?{
        ????this.position?=?position;
        ??}
        ??setScore(score)?{
        ????this.score?=?score;
        ??}
        }

        const?player?=?new?Player();
        player.setScore(0);
        player.setName('Sudongyuer');
        player..setPosition([2,?0]);
        console.log(player)

        在上面的代碼中,您可以看到我們需要為播放器一起調(diào)用一堆函數(shù)。如果您的對象/類是這種情況,請使用方法鏈接。您需要做的就是從要鏈接的函數(shù)中返回對象的實例。上面的例子可以修改如下來實現(xiàn):

        class?Player?{
        ??constructor?(name,?score,?position)?{
        ????this.position?=?position;
        ????this.score?=?score;
        ????this.name?=?name;
        ??}
        ??setName(name)?{
        ????this.name?=?name;
        ????return?this;?//?<--?THIS
        ??}
        ??setPosition(position)?{
        ????this.position?=?position;
        ????return?this;?//?<--?THIS
        ??}
        ??setScore(score)?{
        ????this.score?=?score;
        ????return?this;?//?<--?THIS
        ??}
        }

        const?player?=?new?Player();
        player.setScore(0).setName('Sudongyuer').setPosition([2,?0]);
        //?SUPER?COOL???
        console.log(player)

        在回調(diào)上使用 Promise

        承諾讓我們的生活更輕松。幾年前我們有一個叫做回調(diào)地獄的東西,這使得代碼很難閱讀。它看起來像這樣:

        圖片描述

        即使我正在使用具有回調(diào)的庫,我也會嘗試在那里添加一個包裝器來保證這一點(是的,現(xiàn)在這是一個術(shù)語)。讓我們考慮以下示例:

        ?const?getSocials?=?(callback)?=>?{
        ??setTimeout(()?=>?{
        ??????callback({socials:?{youtube:?'xxx',?twitter:?'xxx'}});
        ????},?1500);
        }

        const?getBooks?=?(callback)?=>?{
        ??setTimeout(()?=>?{
        ????callback({books:?['React?Cookbook']});
        ??},?1500);
        }

        const?getDesignation?=?(callback)?=>?{
        ??setTimeout(()?=>?{
        ????callback({designation:?'Software?Architect'});
        ??},?1500);
        }

        const?getUser?=?(callback)?=>?{
        ??setTimeout(()?=>?{
        ????callback({user:?'Sudongyuer'});
        ??},?1500);
        }

        ?getUser(({user})?=>?{
        ????console.log('user?retrieved',?user)
        ????getDesignation(({designation})?=>?{
        ??????console.log('designation?retrieved',?designation)
        ??????getBooks(({books})?=>?{
        ????????console.log('books?retrieved',?books)
        ????????getSocials(({socials})?=>?{
        ??????????console.log('socials?retrieved',?socials)
        ????????})
        ??????})
        ????})
        ??})

        上述代碼中的所有函數(shù)都是異步的,它們會在 1.5 秒后發(fā)回數(shù)據(jù)?,F(xiàn)在,如果涉及 15 個不同的功能,想象一下它會是什么樣子??赡芫拖裎以谏厦娣窒淼膱D像??。為了更好的可讀性,我們可以promisify我們的函數(shù)并使用promises,而不是這個回調(diào)地獄:

        const?getSocials?=?()?=>?{
        ??return?new?Promise(resolve?=>?{
        ????setTimeout(()?=>?{
        ??????resolve({socials:?{youtube:?'xxx',?twitter:?'xxx'}});
        ????},?1500);
        ??})

        }

        const?getBooks?=?()?=>?{
        ??return?new?Promise(resolve?=>?{
        ????setTimeout(()?=>?{
        ??????resolve({books:?['React?Cookbook']});
        ????},?1500);
        ??})
        }

        const?getDesignation?=?()?=>?{
        ??return?new?Promise(resolve?=>?{
        ????setTimeout(()?=>?{
        ??????resolve({designation:?'Software?Architect'});
        ????},?1500);
        ??})
        }

        const?getUser?=?()?=>?{
        ??return?new?Promise(resolve?=>?{
        ????setTimeout(()?=>?{
        ??????resolve({user:?'Sudongyuer'});
        ????},?1500);
        ??})
        }

        ??getUser()
        ????.then(({user})?=>?{
        ??????console.log('user?retrieved',?user);
        ??????return?getDesignation();
        ????})
        ????.then(({designation})?=>?{
        ??????console.log('designation?retrieved',?designation)
        ??????return?getBooks();
        ????})
        ????.then(({books})?=>?{
        ??????console.log('books?retrieved',?books);
        ??????return?getSocials();
        ????})
        ????.then(({socials})?=>?{
        ??????console.log('socials?retrieved',?socials)
        ????})

        您可以看到代碼現(xiàn)在已經(jīng)非常可讀,因為所有語句都縮進并顯示了在每個步驟.then()中檢索到的數(shù)據(jù)。.then()我們可以很容易地看到使用這種語法的步驟,因為每次.then()調(diào)用都會返回下一個函數(shù)調(diào)用及其承諾。

        現(xiàn)在我們可以把它提升一個檔次,讓我們的代碼更具可讀性。如何?通過使用async await. 我們將修改我們的代碼如下來實現(xiàn):

        const?getSocials?=?()?=>?{
        ??return?new?Promise(resolve?=>?{
        ????setTimeout(()?=>?{
        ??????resolve({socials:?{youtube:?'xxx',?twitter:?'xxx'}});
        ????},?1500);
        ??})

        }

        const?getBooks?=?()?=>?{
        ??return?new?Promise(resolve?=>?{
        ????setTimeout(()?=>?{
        ??????resolve({books:?['React?Cookbook']});
        ????},?1500);
        ??})
        }

        const?getDesignation?=?()?=>?{
        ??return?new?Promise(resolve?=>?{
        ????setTimeout(()?=>?{
        ??????resolve({designation:?'Software?Architect'});
        ????},?1500);
        ??})
        }

        const?getUser?=?()?=>?{
        ??return?new?Promise(resolve?=>?{
        ????setTimeout(()?=>?{
        ??????resolve({user:?'Sudongyuer'});
        ????},?1500);
        ??})
        }

        const?performTasks?=?async?()?=>?{
        ??const?{user}?=?await?getUser();
        ??console.log('user?retrieved',?user);

        ??const?{designation}?=?await?getDesignation();
        ??console.log('designation?retrieved',?designation);

        ??const?{books}?=?await?getBooks();
        ??console.log('books?retrieved',?books);

        ??const?{socials}?=?await?getSocials();
        ??console.log('socials?retrieved',?socials);
        }

        請注意,我們將代碼包裝在performTasks()函數(shù)中,這是一個async函數(shù),您可以看到async關(guān)鍵字的用法。在內(nèi)部,我們使用await關(guān)鍵字進行每個函數(shù)調(diào)用,這基本上會在執(zhí)行下一行代碼之前等待函數(shù)的承諾得到解決。使用這種語法,我們的代碼看起來好像都是同步的,但實際上是異步的。而且我們的代碼更干凈??

        最后



        如果你覺得這篇內(nèi)容對你挺有啟發(fā),我想邀請你幫我個小忙:

        1. 點個「喜歡」或「在看」,讓更多的人也能看到這篇內(nèi)容

        2. 我組建了個氛圍非常好的前端群,里面有很多前端小伙伴,歡迎加我微信「sherlocked_93」拉你加群,一起交流和學(xué)習(xí)

        3. 關(guān)注公眾號「前端下午茶」,持續(xù)為你推送精選好文,也可以加我為好友,隨時聊騷。



        點個喜歡支持我吧,在看就更好了


        瀏覽 37
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            91狠狠综合久久久久久 | 人人插人人 | 惩罚女仆扒开打屁股二次元 | 国产玖玖精品视频 | 欧美性猛交xxxx乱大交游戏 | 精品国产乱码久久久久久中文 | 成人ac在线 | 一级少妇全黄性色生活片 | 国产亚洲视频一区 | 国产一级啪啪 |