<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          實(shí)例詳解你不知道的十個(gè) JS 小技巧

          共 18435字,需瀏覽 37分鐘

           ·

          2022-06-28 04:21

          大廠技術(shù)  高級(jí)前端  Node進(jìn)階

          點(diǎn)擊上方 程序員成長(zhǎng)指北,關(guān)注公眾號(hào)

          回復(fù)1,加入高級(jí)Node交流群

          原文鏈接: https://juejin.cn/post/7021047385337888775

          我是加菲貓?? ,如果你喜歡我的文章,歡迎點(diǎn)贊分享哦

          總結(jié)了一些開(kāi)發(fā)常用的 JS 小技巧,讓你的代碼更優(yōu)雅!

          1. 使用 const 定義

          在開(kāi)發(fā)中不要過(guò)度聲明變量,盡量使用表達(dá)式和鏈?zhǔn)秸{(diào)用形式。然后一般能用 const 就不要用 let 。這種模式寫(xiě)多了之后,你會(huì)發(fā)現(xiàn)在項(xiàng)目中幾乎找不到幾個(gè)用 let 的地方:

          // bad
          let result = false;
          if (userInfo.age > 30) {
            result = true;
          }
          // good
          const result = userInfo.age > 30;

          在項(xiàng)目中很多同事都會(huì)這樣寫(xiě),

          handleFormChange(e) {
            let isUpload;
            if (e.target.value === 'upload') {
              isUpload = true;
            } else {
              isUpload = false;
            }
          }

          但實(shí)際上 ===== 的表達(dá)式可以直接給變量賦值:

          handleFormChange(e) {
            const isUpload = (e.target.value === 'upload');
          }

          如果要取反也很簡(jiǎn)單:

          handleFormChange(e) {
            const isManual = (e.target.value !== 'upload');
          }

          2. 有條件地向?qū)ο蟆?shù)組添加屬性

          1) 向?qū)ο筇砑訉傩?/span>

          可以使用展開(kāi)運(yùn)算符來(lái)有條件地向?qū)ο笾刑砑訉傩裕?/p>

          const condition = true;
          const person = {
            id1,
            name"dby",
            ...(condition && { age12 }),
          };

          如果 conditiontrue ,則 { age: 16 } 會(huì)被添加到對(duì)象中;如果 conditionfalse ,相當(dāng)于展開(kāi) false ,不會(huì)對(duì)對(duì)象產(chǎn)生任何影響

          2) 向數(shù)組添加屬性

          這是 CRA 中 Webpack 配置的源碼:

          module.exports = {
            plugins: [
              new HtmlWebpackPlugin(),
              isEnvProduction &&
                new MiniCssExtractPlugin(),
              useTypeScript &&
                new ForkTsCheckerWebpackPlugin(),
            ].filter(Boolean),
          }

          上面代碼中,只有 isEnvProductiontrue 才會(huì)添加 MiniCssExtractPlugin 插件;當(dāng) isEnvProductionfalse 則會(huì)添加 false 到數(shù)組中,所以最后使用了 filter 過(guò)濾

          上面這樣寫(xiě),邏輯上是沒(méi)有問(wèn)題,但是在 TS 項(xiàng)目中使用的時(shí)候,類型推斷會(huì)有點(diǎn)問(wèn)題。因?yàn)榇嬖谝环N布爾值添加到數(shù)組的中間狀態(tài),而 TS 只能靜態(tài)分析,不能執(zhí)行代碼。

          試問(wèn)下面 arr 數(shù)組的類型:

          const arr = ['111'true && '222'].filter(Boolean); // string[]
          const arr = ['111'false && '222'].filter(Boolean); // (string | boolean)[]

          下面是一種類型安全的做法:

          module.exports = {
            plugins: [
              new HtmlWebpackPlugin(),
              ...(isEnvProduction ? [new MiniCssExtractPlugin()] : []),
              ...(useTypeScript ? [new ForkTsCheckerWebpackPlugin()] : []),
            ],
          }

          3. 數(shù)組小技巧

          1) 訪問(wèn)數(shù)組最后一個(gè)元素

          在開(kāi)發(fā)中我們常常需要訪問(wèn)數(shù)組最后一個(gè)元素,常規(guī)的做法是這樣:

          const rollbackUserList = [1234];
          const lastUser = rollbackUserList[rollbackUserList.length - 1]; // 4

          上面這樣寫(xiě)邏輯上沒(méi)問(wèn)題,但是我們發(fā)現(xiàn)當(dāng)數(shù)組的變量名很長(zhǎng)的時(shí)候,整個(gè)表達(dá)式會(huì)變得非常長(zhǎng),影響代碼可讀性。一種方法是把上述邏輯封裝一下:

          // 將獲取數(shù)組最后一個(gè)元素的邏輯封裝為一個(gè)函數(shù)
          const getLastEle = (arr) => arr[arr.length - 1];
          const lastUser = getLastEle(rollbackUserList); // 4

          可以看到這樣語(yǔ)義性就比較好了。還有一種是利用 Array.prototype.slice 方法,通過(guò)傳遞負(fù)索引,從右往左定位到最后一個(gè)元素:

          const lastUser = rollbackUserList.slice(-1)[0]; // 4
          // 或者使用解構(gòu)賦值
          const [lastUser] = rollbackUserList.slice(-1); // 4

          注意 slice 方法返回的是一個(gè) 新數(shù)組 而不是元素本身,需要手動(dòng)從數(shù)組中取出元素,看起來(lái)不是很優(yōu)雅。實(shí)際上 ES2022 專門(mén)提供了一個(gè) Array.prototype.at 方法,用于根據(jù)給定索引獲取數(shù)組元素:

          const lastUser = rollbackUserList.at(-1); // 4

          at 方法傳遞索引為正時(shí)從左往右定位(這與直接通過(guò)下標(biāo)訪問(wèn)的作用一致),索引為負(fù)時(shí)從右往左定位。在訪問(wèn)數(shù)組最后一個(gè)元素的場(chǎng)景中非常好用。從 Chrome 92 開(kāi)始已經(jīng)支持 at 方法,core-js 也提供了 polyfill。

          developer.mozilla.org/en-US/docs/…[1]

          2) 異步函數(shù)組合(異步串行調(diào)用)

          我們知道,在函數(shù)式編程中有一個(gè)函數(shù)組合 compose 的技巧,可以把多個(gè)函數(shù)組合為一個(gè)函數(shù),創(chuàng)建一個(gè)從右到左的數(shù)據(jù)流,右邊函數(shù)執(zhí)行的結(jié)果作為參數(shù)傳入左邊。例如:

          /**
           * 給定參數(shù):[A, B, C, D]
           * 調(diào)用順序:A(B(C(D())))
           */

          const compose = (middlewares) => (initialValue) => middlewares.reduceRight(
              (accu, cur) => cur(accu),
              initialValue
          );

          從上面的代碼可以看出 compose 是不能用于 Promise,因?yàn)?compose 需要將上一次調(diào)用的返回值,作為參數(shù)傳入下一次調(diào)用,但 Promise 本身是一個(gè)包裝過(guò)的數(shù)據(jù)結(jié)構(gòu),只有通過(guò) then 方法才能拿到返回值。所以如果是異步的情況,我們通常會(huì)把 reduce 改成普通 FOR 循環(huán)。

          如果遇到異步的情況,例如想做一系列串行的請(qǐng)求,是否可以更優(yōu)雅呢?本人在 Vite 源碼中找到了答案,在 Vite 源碼中有這么一段:

          await postBuildHooks.reduce(
            (queue, hook) => queue.then(() => hook(build as any)),
            Promise.resolve();
          )

          參考: github.com/vitejs/vite…[2]

          可以看出,這里對(duì) reducer 函數(shù)進(jìn)行了包裝,將 hook 的執(zhí)行放到 then 方法回調(diào)中,這樣就可以保證調(diào)用順序。按照這個(gè)思路,我們對(duì)上面 compose 方法稍微改動(dòng)一下,就可以得到一個(gè) asyncCompose

          /**
           * 給定參數(shù):[A, B, C, D]
           * 調(diào)用順序:Promise.resolve().then(res => D(res)).then(res => C(res)).then(res => B(res)).then(res => A(res))
           * 以上只是為了讓大家看清楚,簡(jiǎn)化之后如下:Promise.resolve().then(D).then(C).then(B).then(A)
           */

          const asyncCompose = (middlewares) => (initialValue) => middlewares.reduceRight(
              (queue, hook) => queue.then(res => hook(res)),
              Promise.resolve(initialValue)
          );

          4. 解構(gòu)賦值

          解構(gòu)賦值很方便,項(xiàng)目中經(jīng)常會(huì)用到,可以分為以下兩個(gè)場(chǎng)景:

          • 對(duì)象/數(shù)組的解構(gòu);
          • 函數(shù)參數(shù)解構(gòu);

          這里介紹四種常用技巧。

          1) 深度解構(gòu)

          大部分時(shí)候我們只會(huì)解構(gòu)一層,但實(shí)際上解構(gòu)賦值是可以深度解構(gòu)的:

          let obj = {
            name"dby",
            a: {
              b1
            }
          }
          const { a: { b } } = obj;
          console.log(b); // 1

          2) 解構(gòu)時(shí)使用別名

          假如后端返回的對(duì)象鍵名不是我們想要的,可以使用別名:

          const obj = {
            // 這個(gè)鍵名太長(zhǎng)了,我們希望把它換掉
            aaa_bbb_ccc: {
              name"dby",
              age12,
              sextrue
            }
          }
          const { aaa_bbb_ccc: user } = obj;
          console.log(user); // { name: "dby", age: 12, sex: true }

          3) 解構(gòu)時(shí)使用默認(rèn)值

          對(duì)象的解構(gòu)可以使用默認(rèn)值,默認(rèn)值生效的條件是,對(duì)象的屬性值嚴(yán)格等于 undefined

          fetchUserInfo()
            .then(({ aaa_bbb_ccc: user = {} }) => {
              // ...
            })

          以上三個(gè)特性可以結(jié)合使用

          4) 使用短路避免報(bào)錯(cuò)

          解構(gòu)賦值雖然好用,但是要注意解構(gòu)的對(duì)象不能為 undefinednull ,否則會(huì)報(bào)錯(cuò),故要給被解構(gòu)的對(duì)象一個(gè)默認(rèn)值:

          const {a,b,c,d,e} = obj || {};

          5. 展開(kāi)運(yùn)算符

          使用展開(kāi)運(yùn)算符合并兩個(gè)數(shù)組或者兩個(gè)對(duì)象:

          const a = [1,2,3];
          const b = [1,5,6];
          // bad
          const c = a.concat(b);
          // good
          const c = [...new Set([...a,...b])];

          const obj1 = { a:1 };
          const obj2 = { b:1 };
          // bad
          const obj = Object.assign({}, obj1, obj2);
          // good
          const obj = { ...obj1, ...obj2 };

          這里要注意一個(gè)問(wèn)題,對(duì)象和數(shù)組合并雖然看上去都是 ... ,但是實(shí)際上是有區(qū)別的。

          ES2015 擴(kuò)展運(yùn)算符只規(guī)定了在數(shù)組函數(shù)參數(shù)中使用,但并沒(méi)有規(guī)定可以在對(duì)象中使用,并且是基于 for...of 的,因此被展開(kāi)的只能是數(shù)組、字符串、Set、Map 等可迭代對(duì)象,假如將普通對(duì)象展開(kāi)到數(shù)組就會(huì)報(bào)錯(cuò)。

          對(duì)象中的 ... 實(shí)際上是 ES2018 中的對(duì)象展開(kāi)語(yǔ)法,相當(dāng)于 Object.assign

          babeljs.io/docs/en/bab…[3]

          6. 檢查屬性是否存在對(duì)象中

          可以使用 in 關(guān)鍵字檢查對(duì)象中是否存在某個(gè)屬性:

          const person = { name"dby"salary1000 };
          console.log('salary' in person); // true
          console.log('age' in person); // false

          但是 in 關(guān)鍵字其實(shí)并不安全,會(huì)把原型上的屬性也包括進(jìn)去,例如:

          "hasOwnProperty" in {}; // true
          "toString" in {}; // true

          所以推薦使用下面的方法進(jìn)行判斷:

          Object.prototype.hasOwnProperty.call(person, "salary"); // true

          不過(guò)上面這樣的問(wèn)題就是太長(zhǎng)了,每次使用都要這樣寫(xiě)很麻煩。ECMA 有一個(gè)新的提案 Object.hasOwn() ,相當(dāng)于 Object.prototype.hasOwnProperty.call() 的別名:

          Object.hasOwn(person, "salary"); // true

          developer.mozilla.org/en-US/docs/…[4]

          需要注意這個(gè)語(yǔ)法存在兼容性問(wèn)題(Chrome > 92),不過(guò)只要正確配置 polyfill 就可以放心使用。

          7. 對(duì)象的遍歷

          項(xiàng)目中很多同事都會(huì)這樣寫(xiě):

          for (let key in obj) {
            if (Object.prototype.hasOwnProperty.call(obj, key)) {
              // ...
            }
          }

          吐槽:用 Object.keys 或者 Object.entries 轉(zhuǎn)成數(shù)組就可以用數(shù)組方法遍歷了,而且遍歷的是自身屬性,不會(huì)遍歷到原型上。

          Object.keys(obj).forEach(key => {
            // ...
          })

          Object.entries(obj).forEach(([key, val]) => {
            // ...
          })

          舉個(gè)例子,將對(duì)象的 key、value 拼接為查詢字符串:

          const _stringify = (obj) => Object.entries(obj).map(([key, val]) => `${key}=${val}`).join("&");

          _stringify({
              a1,
              b2,
              c"2333"
          });
          // 'a=1&b=2&c=2333'

          反駁:有時(shí)候不想遍歷整個(gè)對(duì)象,數(shù)組方法不能用 break 終止循環(huán)呀。

          吐槽:看來(lái)你對(duì)數(shù)組方法掌握還是不夠徹底,使用 find 方法找到符合條件的項(xiàng)就不會(huì)繼續(xù)遍歷。

          Object.keys(obj).find(key => key === "name");

          總結(jié):在開(kāi)發(fā)中盡量不要寫(xiě) for 循環(huán),無(wú)論數(shù)組和對(duì)象。對(duì)象就通過(guò) Object.keysObject.valuesObject.entries 轉(zhuǎn)為數(shù)組進(jìn)行遍歷。這樣可以寫(xiě)成 JS 表達(dá)式,充分利用函數(shù)式編程。

          8. 使用 includes 簡(jiǎn)化 if 判斷

          在項(xiàng)目中經(jīng)常看到這樣的代碼:

          if (a === 1 || a === 2 || a === 3 || a === 4) {
              // ...
          }

          可以使用 includes 簡(jiǎn)化代碼:

          if ([1234].includes(a)) {
              // ...
          }

          9. Promise 三點(diǎn)總結(jié)

          1) async/await 優(yōu)雅異常處理

          async 函數(shù)中,只要其中某個(gè) Promise 報(bào)錯(cuò),整個(gè) async 函數(shù)的執(zhí)行就中斷了,因此異常處理非常重要。但實(shí)際上 async 函數(shù)的異常處理非常麻煩,很多同事都不愿意寫(xiě)。有沒(méi)有一種簡(jiǎn)單的方法呢?看到一個(gè) await-to-js 的 npm 包,可以優(yōu)雅處理 async 函數(shù)的異常,不需要手動(dòng)添加 try...catch 捕獲異常:

          import to from 'await-to-js';

          async function asyncFunctionWithThrow({
            const [err, user] = await to(UserModel.findById(1));
            if (!user) throw new Error('User not found');
          }

          www.npmjs.com/package/awa…[5]

          實(shí)際上就是在 await 前面返回的 Promise 封裝了一層,提前處理異常。源碼非常簡(jiǎn)單,本人自己也實(shí)現(xiàn)了下:

          function to(awaited{
            // 不管是不是 Promise 一律轉(zhuǎn)為 Promise
            const p = Promise.resolve(awaited);
            // await-to-js 采用 then...catch 的用法
            // 但實(shí)際上 then 方法第一個(gè)回調(diào)函數(shù)里面并不包含會(huì)拋出異常的代碼
            // 因此使用 then 方法第二個(gè)回調(diào)函數(shù)捕獲異常,不需要額外的 catch
            return p.then(
              res => {
                return [null, res];
              },
              err => {
                return [err, undefined];
              }
            )
          }

          2) Promise 作為狀態(tài)機(jī)

          看到有同事寫(xiě)過(guò)這樣的代碼:

          function validateUserInfo(user{
            if (!userList.find(({ id }) => id === user.id)) {
              return {
                code-1,
                message"用戶未注冊(cè)"
              }
            }
            if (
              !userList.find(
                ({ username, password }) =>
                  username === user.username &&
                  password === user.password
              )
            ) {
              return {
                code-1,
                message"用戶名或密碼錯(cuò)誤"
              }
            }
            return {
              code0,
              message"登錄成功"
            }
          }

          觀察發(fā)現(xiàn)這邊其實(shí)就是兩個(gè)狀態(tài),然后還需要一個(gè)字段提示操作結(jié)果。這種情況下我們可以使用 Promise 。有人說(shuō)為啥咧,明明沒(méi)有異步邏輯啊。我們知道,Promise 其實(shí)就是一個(gè)狀態(tài)機(jī),即使不需要處理異步邏輯,我們也可以使用狀態(tài)機(jī)的特性:

          function validateUserInfo(user{
            if (!userList.find(({ id }) => id === user.id)) {
              return Promise.reject("用戶未注冊(cè)");
            }
            if (
              !userList.find(
                ({ username, password }) =>
                  username === user.username &&
                  password === user.password
              )
            ) {
              return Promise.reject("用戶名或密碼錯(cuò)誤");
            }
            return Promise.resolve("登錄成功");
          }

          // 使用如下
          validateUserInfo(userInfo)
            .then(res => {
              message.success(res);
            })
            .catch(err => {
              message.error(err);
            })

          明顯這樣代碼就變得非常優(yōu)雅了,但其實(shí)還可以更優(yōu)雅。我們知道 async 函數(shù)返回值是一個(gè) Promise 實(shí)例,因此下面兩個(gè)函數(shù)是等價(jià)的:

          // 普通函數(shù)返回一個(gè) Promsie.resolve 包裹的值
          const request = (x) => Promise.resolve(x);

          // async 函數(shù)返回一個(gè)值
          const request = async (x) => x;

          既然最后返回一個(gè) Promise ,為何不直接在函數(shù)前面加 async 修飾符呢。這樣成功的結(jié)果只要直接返回就行,不用 Promise.resolve 包裹:

          async function validateUserInfo(user{
            if (!userList.find(({ id }) => id === user.id)) {
              return Promise.reject("用戶未注冊(cè)");
            }
            if (
              !userList.find(
                ({ username, password }) =>
                  username === user.username &&
                  password === user.password
              )
            ) {
              return Promise.reject("用戶名或密碼錯(cuò)誤");
            }
            return "登錄成功";
          }

          對(duì) async 函數(shù)不熟悉的同學(xué),可以參考 阮一峰 ES6 教程[6]

          更進(jìn)一步,由于在 Promise 內(nèi)部拋出異常等同于被 reject ,因此我們可以使用 throw 語(yǔ)句替代 Promise.reject()

          async function validateUserInfo(user{
            if (!userList.find(({ id }) => id === user.id)) {
              throw "用戶未注冊(cè)";
            }
            if (
              !userList.find(
                ({ username, password }) =>
                  username === user.username &&
                  password === user.password
              )
            ) {
              throw "用戶名或密碼錯(cuò)誤";
            }
            return "登錄成功";
          }

          throw 語(yǔ)句的用法可以參考 MDN 文檔[7]

          3) Promise 兩點(diǎn)使用誤區(qū)

          不建議在 Promise 里面使用 try...catch,這樣即使 Promise 內(nèi)部報(bào)錯(cuò),狀態(tài)仍然是 fullfilled,會(huì)進(jìn)入 then 方法回調(diào),不會(huì)進(jìn)入 catch 方法回調(diào)。

          function request({
            return new Promise((resolve, reject) => {
              try {
                // ...
                resolve("ok");
              } catch(e) {
                console.log(e);
              }
            })
          }

          request()
            .then(res => {
              console.log("請(qǐng)求結(jié)果:", res);
            })
            .catch(err => {
              // 由于在 Promise 中使用了 try...catch
              // 因此即使 Promise 內(nèi)部報(bào)錯(cuò),也不會(huì)被 catch 捕捉到
              console.log(err);
            })

          Promise 內(nèi)部的異常,老老實(shí)實(shí)往外拋就行,讓 catch 方法來(lái)處理,符合單一職責(zé)原則

          不建議在 async 函數(shù)中,既不使用 await,也不使用 return,這樣就算內(nèi)部的 Promise reject 也無(wú)法捕捉到:

          async function handleFetchUser(userList{
            // 這里既沒(méi)有使用 await,也沒(méi)有使用 return
            Promise.all(userList.map(u => request(u)));
          }

          handleFetchUser(userList)
            .then(res => {
              // 由于沒(méi)有返回值,這里拿到的是 undefined
              console.log(res);
            })
            .catch(err => {
              // 即使 handleFetchUser 內(nèi)部的 Promise reject
              // async 函數(shù)返回的 Promise 仍然是 fullfilled
              // 此時(shí)仍然會(huì)進(jìn)入 then 方法回調(diào),無(wú)法被 catch 捕捉到
              console.log(err);
            })

          如果確實(shí)有這種需求,建議不要使用 async 函數(shù),直接改用普通函數(shù)即可

          10. 字符串小技巧

          1) 字符串不滿兩位補(bǔ)零

          這個(gè)需求在開(kāi)發(fā)中挺常見(jiàn)。例如,調(diào)用 Date api 獲取到日期可能只有一位:

          let date = new Date().getDate(); // 3

          常規(guī)做法:

          if (data.toString().length == 1) {
              date = `0${date}`
          }

          使用 String.prototype.slice

          // 不管幾位,都在前面拼接一個(gè) 0 ,然后截取最后兩位
          date = `0${date}`.slice(-2);

          使用 String.prototype.padStart

          // 當(dāng)字符串長(zhǎng)度小于第一個(gè)參數(shù)值,就在前面補(bǔ)第二個(gè)參數(shù)
          date = `${date}`.padStart(20);

          2) 千分位分隔符

          實(shí)現(xiàn)如下的需求:

          • 從后往前每三個(gè)數(shù)字前加一個(gè)逗號(hào)
          • 開(kāi)頭不能加逗號(hào)

          這樣看起來(lái)非常符合 (?=p) 的規(guī)律,p 可以表示每三個(gè)數(shù)字,要添加逗號(hào)所處的位置正好是 (?=p) 匹配出來(lái)的位置。

          第一步,先嘗試把最后一個(gè)逗號(hào)弄出來(lái):

          "300000000".replace(/(?=\d{3}$)/",")
          // '300000,000'

          第二步,把所有逗號(hào)都弄出來(lái):

          "300000000".replace(/(?=(\d{3})+$)/g",")
          // ',300,000,000'

          使用括號(hào)把一個(gè) p 模式變成一個(gè)整體

          第三步,去掉首位的逗號(hào):

          "300000000".replace(/(?!^)(?=(\d{3})+$)/g",")
          // '300,000,000'

          3) 借用數(shù)組拼接字符串

          很多同學(xué)都知道 模板字符串 可以很方便地進(jìn)行字符串拼接,但是需要拼接較多參數(shù)的時(shí)候,這樣就顯得比較麻煩:

          // HH -> 23
          // mm -> 58
          // ss -> 32
          const timeString = `${HH}:${mm}:${ss}`;
          // scheme -> https://
          // host -> 10.3.71.108
          // port -> :8080
          const URLString = `${scheme}${host}${port}`

          實(shí)際上,拼接字符串,除了使用模板字符串的方式,還可以使用數(shù)組:

          const timeString = [HH, mm, ss].join(":");
          const URLString = [scheme, host, port].join("");

          順便一提,本人之前維護(hù)過(guò)一個(gè) jQuery 項(xiàng)目,就使用這種方式拼接 html 模板:

          const dataSource = ["dby""dm""233"];
          const template = dataSource.map(name => `<div>${name}</div>`).join("");

          4) 判斷字符串前綴、后綴

          判斷字符串前綴、后綴不要一言不合就使用正則表達(dá)式:

          const url = "https://bili98.cn";
          const isHTTPS = /^https:\/\//.test(url); // true

          const fileName = "main.py";
          const isPythonCode = /\.py$/.test(fileName); // true

          推薦使用 String.prototype.startsWithString.prototype.endsWith,語(yǔ)義性更好:

          const url = "https://bili98.cn";
          const isHTTPS = url.startsWith("https://"// true

          const fileName = "main.py";
          const isPythonCode = fileName.endsWith(".py"); // true

          參考

          我的代碼簡(jiǎn)潔之道[8]

          你會(huì)用ES6,那倒是用啊![9]

          有個(gè)開(kāi)發(fā)者總結(jié)這 15 優(yōu)雅的 JavaScript 個(gè)技巧[10]

          Node 社群



          我組建了一個(gè)氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對(duì)Node.js學(xué)習(xí)感興趣的話(后續(xù)有計(jì)劃也可以),我們可以一起進(jìn)行Node.js相關(guān)的交流、學(xué)習(xí)、共建。下方加 考拉 好友回復(fù)「Node」即可。



          如果你覺(jué)得這篇內(nèi)容對(duì)你有幫助,我想請(qǐng)你幫我2個(gè)小忙:

          1. 點(diǎn)個(gè)「在看」,讓更多人也能看到這篇文章
          2. 訂閱官方博客 www.inode.club 讓我們一起成長(zhǎng)

          點(diǎn)贊和在看就是最大的支持

          瀏覽 24
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产毛片欧美毛片高潮 | 三级片在线视频观看 | 亚州多毛少妇 | 成人性交无码 | 99热2|