JS優化技巧,解決冗餘代碼

来源:https://www.cnblogs.com/xw-01/archive/2023/08/02/17600393.html
-Advertisement-
Play Games

### 1. 使用箭頭函數簡化函數定義 ```cobol // 傳統函數定義 function add(a, b) { return a + b; } // 箭頭函數簡化 const add = (a, b) => a + b; ``` ### 2. 使用解構賦值簡化變數聲明 ```cobol // ...


1. 使用箭頭函數簡化函數定義

// 傳統函數定義



function add(a, b) {



 return a + b;



 }



  



 // 箭頭函數簡化



 const add = (a, b) => a + b;

2. 使用解構賦值簡化變數聲明

// 傳統變數聲明



const firstName = person.firstName;



const lastName = person.lastName;



// 解構賦值簡化



const { firstName, lastName } = person;

3. 使用模板字面量進行字元串拼接

// 傳統字元串拼接



const greeting = 'Hello, ' + name + '!';



// 模板字面量簡化



const greeting = `Hello, ${name}!`;

4. 使用展開運算符進行數組和對象操作

// 合併數組



const combined = [...array1, ...array2];



// 複製對象



const clone = { ...original };

5. 使用數組的高階方法簡化迴圈和數據操作

// 遍曆數組並返回新數組



const doubled = numbers.map(num => num * 2);



// 過濾數組



const evens = numbers.filter(num => num % 2 === 0);

6. 使用條件運算符簡化條件判斷

// 傳統條件判斷



let message;



if (isSuccess) {



 message = 'Operation successful';



} else {



 message = 'Operation failed';



}



// 條件運算符簡化



const message = isSuccess ? 'Operation successful' : 'Operation failed';

7. 使用對象解構和預設參數簡化函數參數

// 傳統參數設置預設值



function greet(name) {



 const finalName = name || 'Guest';



 console.log(`Hello, ${finalName}!`);



 }



  



 // 對象解構和預設參數簡化



 function greet({ name = 'Guest' }) {



 console.log(`Hello, ${name}!`);



 }

8. 使用函數式編程概念如純函數和函數組合

// 純函數



function add(a, b) {



 return a + b;



 }



  



 // 函數組合



 const multiplyByTwo = value => value * 2;



 const addFive = value => value + 5;



 const result = addFive(multiplyByTwo(3));

9. 使用對象字面量簡化對象的創建和定義

// 傳統對象創建



const person = {



 firstName: 'John',



 lastName: 'Doe',



 age: 30,



 };



  



 // 對象字面量簡化



 const firstName = 'John';



 const lastName = 'Doe';



 const age = 30;



 const person = { firstName, lastName, age };

10. 使用適當的命名和註釋來提高代碼可讀性

// 不好的



const x = 10; // 設置x的值為10



function a(b) {



 return b * 2; // 返回b的兩倍



}



// 好的



const speed = 10; // 設置速度為10



function double(value) {



 return value * 2; // 返回輸入值的兩倍

11. 優雅的寫條件判斷代碼

簡單的條件判斷邏輯用if else 或者 三元運算符, 一眼看過去還能知道說的啥,但是大量的if else和疊加在一起的三元運算符就是接盤俠的噩夢~~~

給大家上一個三元運算符疊加的案例,我是真實在項目中遇到過,cpu直接乾爆~~~

<view>{{status===1?'成功': status===2 ? '失敗' : status===3 ? '進行中' : '未開始' }}</view>

大概是這樣的,具體的項目代碼不好放在這裡,小伙伴們意會就行。

複雜邏輯推薦使用對象Map寫法,符合人腦的邏輯,可讀性高,看著舒服~~~

1,普通的if else

let txt = '';



if (falg) {



 txt = "成功"



} else {



 txt = "失敗"



}

2,三元運算符

let txt = flag ? "成功" : "失敗";

3,多個if else

// param {status} status 活動狀態:1:成功 2:失敗 3:進行中 4:未開始



let txt = '';



if (status == 1) {



 txt = "成功";



} else if (status == 2) {



 txt = "失敗";



} else if (status == 3) {



 txt = "進行中";



} else {



 txt = "未開始";



}

4,switch case

let txt = '';



switch (status) {



 case 1:



 txt = "成功";



 break;



 case 2:



 txt = "成功";



 break;



 case 3:



 txt = "進行中";



 break;



 default:



 txt = "未開始";



}

5,對象寫法

const statusMap = {



 1: "成功",



 2: "失敗",



 3: "進行中",



 4: "未開始"



}



//調用直接 statusMapp[status]

5,Map寫法

const actions = new Map([



 [1, "成功"],



 [2, "失敗"],



 [3, "進行中"],



 [4, "未開始"]



])



// 調用直接 actions.get(status)

12. 封裝條件語句

同上,if里的條件越多越不利於接盤俠的維護,不利於人腦的理解,一眼看過去又是一堆邏輯。多個邏輯應該化零為整

大腦:'別來碰我,讓我靜靜'



// 不好的



if (fsm.state === 'fetching' && isEmpty(listNode)) {



 // ...



}



// 好的



shouldShowSpinner(fsm, listNode){



 return fsm.state === 'fetching' && isEmpty(listNode)



}



if(shouldShowSpinner(fsm, listNode)){



 //...doSomething



}

13. 函數應該只做一件事

函數式寫法推崇柯里化, 一個函數一個功能,可拆分可組裝。

// 不好的



function createFile(name, temp) {



 if (temp) {



   fs.create(`./temp/${name}`);



 } else {



   fs.create(name);



 }



}



// 好的



function createFile(name) {



 fs.create(name);



}



function createTempFile(name) {



 createFile(`./temp/${name}`)



}

再來一個慄子

函數要做的事情如下:

  • 遍歷clients數組
  • 遍歷過程中,通過lookup函數得到一個新的對象clientRecord
  • 判斷clientRecord對象中isActive函數返回的是不是true,
    • isActive函數返回true,執行email函數並把當前成員帶過去
// 不好的



function emailClients(clients) {



 clients.forEach((client) => {



   const clientRecord = database.lookup(client);



   if (clientRecord.isActive()) {



     email(client);



   }



 });



}



// 好的



function emailClients(clients) {



 clients



   .filter(isClientRecord)



   .forEach(email)



}



function isClientRecord(client) {



 const clientRecord = database.lookup(client);



 return clientRecord.isActive()



}

上面不好的慄子一眼看過去是不是感覺一堆代碼在那,一時半會甚至不想去看了。

好的慄子,是不是邏輯很清晰,易讀。

  • 巧用filter函數,把filter的回調單開一個函數進行條件處理,返回符合條件的數據
  • 符合條件的數據再巧用forEach,執行email函數

14. Object.assign給預設對象賦預設值

// 不好的



const menuConfig = {



 title: null,



 body: 'Bar',



 buttonText: null,



 cancellable: true



};



function createMenu(config) {



 config.title = config.title || 'Foo';



 config.body = config.body || 'Bar';



 config.buttonText = config.buttonText || 'Baz';



 config.cancellable = config.cancellable === undefined ?



 config.cancellable : true;



}



createMenu(menuConfig);



// 好的



const menuConfig = {



 title: 'Order',



 buttonText: 'Send',



 cancellable: true



};



function createMenu(config) {



 Object.assign({



   title: 'Foo',



   body: 'Bar',



   buttonText: 'Baz',



   cancellable: true 



 }, config)



}



createMenu(menuConfig);

15. 函數參數兩個以下最好

說一千道一萬,就是為了優雅,就是為了可讀性好。

// 不好的



function createMenu(title, body, buttonText, cancellable) {



 // ...



}



// 好的



const menuConfig = {



 title: 'Foo',



 body: 'Bar',



 buttonText: 'Baz',



 cancellable: true



};



function createMenu(config){



 // ...



}



createMenu(menuConfig)

16. 使用解釋性的變數

省流,用了擴展運算符,為了可讀性(saveCityZipCode(city, zipCode)可讀性很好,知道參數是幹嘛的)

// 不好的



const address = 'One Infinite Loop, Cupertino 95014';



const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;



saveCityZipCode(address.match(cityZipCodeRegex)[1], address.match(cityZipCodeRegex)[2]);



// 好的



const address = 'One Infinite Loop, Cupertino 95014';



const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;



cosnt [, city, zipCode] = address.match(cityZipCodeRegex) || [];



saveCityZipCode(city, zipCode)

想對類中的屬性進行更多自定義取/增/改的操作時,使用set/get

第一次見這個寫法,不知道是啥意思的小伙伴,把他當成vue2中的defineProperty

Object.defineProperty(data1,'age',{



 set:function(newAge){



   console.log(this.name+'現在'+newAge+'歲')



 },



 get:function(){



   return 18;



 }



})

是一個意思,賦值的時候set會被觸發,取值的時候get會被觸發。

巧用自帶屬性,提升性能。

class BankAccount {



 constructor(balance = 1000) {



   this._balance = balance;



 }



 // It doesn't have to be prefixed with `get` or `set` to be a



 //getter/setter



 set balance(amount) {



   console.log('set')



   if (verifyIfAmountCanBeSetted(amount)) {



     this._balance = amount;



   }



 }



 get balance() {



   console.log('get')



   return this._balance;



 }



 verifyIfAmountCanBeSetted(val) {



   // ...



 }



}



const bankAccount = new BankAccount();



// Buy shoes...



bankAccount.balance -= 100;



// Get balance



let balance = bankAccount.balance;

17. 讓對象擁有私有成員-通過閉包來實現

閉包天生就是做私有化的

// 不好的



const Employee = function(name) {



 this.name = name;



};



Employee.prototype.getName = function getName() {



 return this.name;



};



const employee = new Employee('John Doe');



console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe



delete employee.name;



console.log(`Employee name: ${employee.getName()}`); // Employee name: undefined



// 好的



const Employee = function(name){



 this.getName = function(){



   return name



 }



}



const employee = new Employee('John Doe');



console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe



delete employee.name;



console.log(`Employee name: ${employee.getName()}`); // Employee name: undefined

第一個示例

優點:

  • 通過原型鏈共用方法,節省了記憶體空間。所有實例對象共用同一個 getName 方法,而不是每個實例對象都創建一個獨立的方法。

缺點:

  • 在構造函數中無法直接定義私有屬性或方法,所有屬性和方法都會被暴露在原型鏈上

第二個示例

優點:

  • 可以在構造函數內部定義私有屬性和方法,不會暴露在對象的原型鏈上,提供了更好的封裝性。

缺點:

  • 每次創建實例對象時,都會創建一個獨立的方法,每個實例對象都有自己的 getName 方法,占用更多的記憶體空間。

18. 使用方法鏈

鏈式寫法也是代碼優雅之道的重頭戲。

ps:發明這個的程式員肯定是後端出身的,這種寫法在PHP的CI框架中見過。

// 不好的



class Car {



 constructor() {



   this.make = 'Honda';



   this.model = 'Accord';



   this.color = 'white';



 }



 setMake(make) {



   this.make = make;



 }



 save() {



   console.log(this.make, this.model, this.color);



 }



}



const car = new Car();



car.setMake('Ford');



car.save();



// 好的



class Car {



 constructor() {



   this.make = 'Honda';



   this.model = 'Accord';



   this.color = 'white';



 }



 setMake(make) {



   this.make = make;



   // NOTE: return this是為了用鏈式寫法



   return this;



 }



 save() {



   console.log(this.make, this.model, this.color);



   // NOTE:return this是為了用鏈式寫法



   return this;



 }



}



const car = new Car()



 .setMake('Ford')



 .save();

看完上面的這麼多慄子,小伙伴的思路是不是清晰了很多,在你們的項目里練練手吧。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 開發者的技術能力良莠不齊,DBA對資料庫知識的局限性導致爛SQL無處不在,而且隨著資料庫的不斷變更或演進,一些好的SQL也可能逐步變成需要優化的爛SQL, 我們要時刻不斷地找尋它們的蹤跡。 ...
  • ### 分享技術,用心生活 >背景:系統中有一個統計頁面載入特別慢,前端設置的40s超時時間都載入不出來數據,因為是個統計頁面,基本上一猜就知道是mysql的語句有問題,遺留了很久沒有解決,正好趁不忙的時候,下定決心一定把它給搞定! ## 1. 分析原因 (mysql5.7) 執行一下問題sql,可 ...
  • MySQL8_SQL語法 SQL 全稱 Structured Query Language,結構化查詢語言。操作關係型資料庫的編程語言,定義了一套操作關係型資料庫統一標準 。 一、SQL通用語法 在學習具體的SQL語句之前,先來瞭解一下SQL語言的同於語法。 1). SQL語句可以單行或多行書寫,以 ...
  • 複製,即在不同的節點上保存相同的副本,提供數據冗餘。如果一些節點不可用,剩餘的節點仍然可以提供數據服務,這些節點可能部署在不同的地理位置,以此來改善系統性能 ...
  • ### 前言 說到MySQL的MTS,相信很多同學都不陌生,從5.6開始基於schema的並行回放,到5.7的LOGICAL_CLOCK支持基於事務的並行回放,這些內容都有文章講解,在本篇文章不再贅述。今天要講的是,你知道如何查看並行回放是否存在性能瓶頸嗎,是由於主庫事務行為導致無法並行回放,還是由 ...
  • 本文分享自華為雲社區《如何為物聯網設備註入“華為雲+鴻蒙DNA”?看華為雲IoT怎麼答【華為雲IoT +鴻蒙】》,作者: 華為IoT雲服務。 根據市場咨詢機構預測,2025年全球物聯網設備將達到252億個。但各種智能設備大多都有一套自己的系統,而且互相“孤立”,無法交流。鴻蒙的到來,就是要用同一套語 ...
  • 由於Android APP/IOS APP平臺和開發語言的差異,對開髮端和用戶端來說,在系統相容適配、外接藍牙的安裝更新,以及不同平臺之間的移植都有不同程度的制約。 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 介紹 canvas:使用腳本 (通常為 JavaScript) 來繪製圖形的 HTML 元素。 本人遍歷了以下兩份文檔,學習完就相當於有了筆和紙,至於最後能畫出什麼,則需要在 canvas 應用方面進一步學習。 MDN 的 Canvas ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...