成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

簡(jiǎn)單幾步讓你的 JS 寫得更漂亮

開(kāi)發(fā) 前端
網(wǎng)上有不少關(guān)于 JS 編寫優(yōu)化建議,這里我根據(jù)自己的經(jīng)驗(yàn)提出一些比較有用的意見(jiàn)。

 網(wǎng)上有不少關(guān)于 JS 編寫優(yōu)化建議,這里我根據(jù)自己的經(jīng)驗(yàn)提出一些比較有用的意見(jiàn)。

[[325014]]

1. 按強(qiáng)類型風(fēng)格寫代碼

JS 是弱類型的,但是寫代碼的時(shí)候不能太隨意,寫得太隨意也體現(xiàn)了編碼風(fēng)格不好。下面分點(diǎn)說(shuō)明:

(1)定義變量的時(shí)候要指明類型,告訴 JS 解釋器這個(gè)變量是什么數(shù)據(jù)類型的,而不要讓解釋器去猜,例如不好的寫法:

 

  1. var num, 
  2.     str, 
  3.     obj; 

聲明了三個(gè)變量,但其實(shí)沒(méi)什么用,因?yàn)榻忉屍鞑恢浪鼈兪鞘裁搭愋偷模玫膶懛☉?yīng)該是這樣的:

 

  1. var num = 0, 
  2.     str = ''
  3.     obj = null

定義變量的時(shí)候就給他一個(gè)默認(rèn)值,這樣不僅方便了解釋器,也方便了閱讀代碼的人,他會(huì)在心里有數(shù)——知道這些變量可能會(huì)當(dāng)作什么用。

(2)不要隨意地改變變量的類型,例如下面代碼:

 

  1. var num = 5; 
  2. num = "-" + num; 

第 1 行它是一個(gè)整型,第 2 行它變成了一個(gè)字符串。因?yàn)?JS 最終都會(huì)被解釋成匯編的語(yǔ)言,匯編語(yǔ)言變量的類型肯定是要確定的,你把一個(gè)整型的改成了字符串,那解釋器就得做一些額外的處理。并且這種編碼風(fēng)格是不提倡的,有一個(gè)變量第 1 行是一個(gè)整型,第 10 行變成了一個(gè)字符串,第 20 行又變成了一個(gè) object,這樣就讓閱讀代碼的人比較困惑,上面明明是一個(gè)整數(shù),怎么突然又變成一個(gè)字符串了。好的寫法應(yīng)該是再定義一個(gè)字符串的變量:

 

  1. var num = 5; 
  2. var sign = "-" + num; 

(3)函數(shù)的返回類型應(yīng)該是要確定的,例如下面不確定的寫法:

 

  1. function getPrice(count){ 
  2.     if(count < 0) return ""
  3.     else return count * 100; 

getPrice 這個(gè)函數(shù)有可能返回一個(gè)整數(shù),也有可能返回一個(gè)空的字符串。這樣寫也不太好,雖然它是符合 JS 語(yǔ)法的,但這種編碼風(fēng)格是不好的。使用你這個(gè)函數(shù)的人會(huì)有點(diǎn)無(wú)所適從,不敢直接進(jìn)行加減乘除,因?yàn)槿绻祷刈址M(jìn)行運(yùn)算的話值就是 NaN 了。函數(shù)的返回類型應(yīng)該是要確定的,如下面是返回整型:

 

  1. function getPrice(count){ 
  2.     if(count < 0) return -1; 
  3.     else return count * 100; 

然后告訴使用者,如果返回-1 就表示不合法。如果類型確定,解釋器也不用去做一些額外的工作,可以加快運(yùn)行速度。

2. 減少作用域查找

(1)不要讓代碼暴露在全局作用域下

例如以下運(yùn)行在全局作用域的代碼:

  1. <script> 
  2.     var map = document.querySelector("#my-map"); 
  3.     map.style.height = "600px"
  4. </script> 

 

有時(shí)候你需要在頁(yè)面直接寫一個(gè) script,要注意在一個(gè) script 標(biāo)簽里面,代碼的上下文都是全局作用域的,由于全局作用域比較復(fù)雜,查找比較慢。例如上面的 map 變量,第二行在使用的時(shí)候,需要在全局作用域查找一下這個(gè)變量,假設(shè) map 是在一個(gè)循環(huán)里面使用,那可能就會(huì)有效率問(wèn)題了。所以應(yīng)該要把它搞成一個(gè)局部的作用域:

  1. <script> 
  2. !function(){ 
  3.     var map = document.querySelector("#my-map"); 
  4.     map.style.height = "600px"
  5. }() 
  6. </script> 

上面用了一個(gè) function 制造一個(gè)局部作用域,也可以用 ES6 的塊級(jí)作用域。由于 map 這個(gè)變量直接在當(dāng)前的局部作用域命中了,所以就不用再往上一級(jí)的作用域(這里是全局作用域)查找了,而局部作用域的查找是很快的。同時(shí)直接在全局作用域定義變量,會(huì)污染 window 對(duì)象。

(2)不要濫用閉包

閉包的作用在于可以讓子級(jí)作用域使用它父級(jí)作用域的變量,同時(shí)這些變量在不同的閉包是不可見(jiàn)的。這樣就導(dǎo)致了在查找某個(gè)變量的時(shí)候,如果當(dāng)前作用域找不到,就得往它的父級(jí)作用域查找,一級(jí)一級(jí)地往上直到找到了,或者到了全局作用域還沒(méi)找到。因此如果閉包嵌套得越深,那么變量查找的時(shí)間就越長(zhǎng)。如下:

 

  1. function getResult(count){ 
  2.     count++; 
  3.     function process(){ 
  4.         var factor = 2; 
  5.         return count * factor - 5; 
  6.     } 
  7.     return process(); 

上面的代碼定義了一個(gè) process 函數(shù),在這個(gè)函數(shù)里面 count 變量的查找時(shí)間要高于局部的 factor 變量。其實(shí)這里不太適合用閉包,可以直接把 count 傳給 process:

 

  1. function getResult(count){ 
  2.     count++; 
  3.     function process(count){ 
  4.         var factor = 2; 
  5.         return count * factor - 5; 
  6.     } 
  7.     return process(count); 

這樣 count 的查找時(shí)間就和 factor 一樣,都是在當(dāng)前作用域直接命中。這個(gè)就啟示我們?nèi)绻硞€(gè)全局變量需要頻繁地被使用的時(shí)候,可以用一個(gè)局部變量緩存一下,如下:

 

  1. var url = ""
  2. if(window.location.protocal === "https:"){ 
  3.     url = "wss://xxx.com" + window.location.pathname + window.location.search; 

頻繁地使用了 window.location 對(duì)象,所以可以先把它緩存一下:

 

  1. var url = ""
  2. var location = window.location; 
  3. if(location.protocal === "https:"){ 
  4.     url = "wss://xxx.com" + location.pathname + location.search; 

搞成了一個(gè)局變變量,這樣查找就會(huì)明顯快于全局的查找,代碼也可以寫少一點(diǎn)。

 3.避免==的使用

這里你可能會(huì)有疑問(wèn)了,有些人喜歡用==,有些人喜歡用===,大家的風(fēng)格不一樣,你為什么要強(qiáng)制別人用===呢?習(xí)慣用==的人,不能僅僅是因?yàn)?=比===少敲了一次鍵盤。為什么不提倡用==呢?

(1)如果你確定了變量的類型,那么就沒(méi)必要使用==了,如下:

 

  1. if(typeof num != "undefined"){ 
  2.  
  3. var num = parseInt(value); 
  4. if(num == 10){ 
  5.  

上面的兩個(gè)例子都是確定類型的,一個(gè)是字符串,一個(gè)是整數(shù)。就沒(méi)必要使用==了,直接用===就可以了。

(2)如果類型不確定,那么應(yīng)該手動(dòng)做一下類型轉(zhuǎn)換,而不是讓別人或者以后的你去猜這里面有類型轉(zhuǎn)換,如下:

 

  1. var totalPage = "5"
  2. if(parseInt(totalPage) === 1){ 
  3.  

(3)使用==在 JSLint 檢查的時(shí)候是不通過(guò)的:

 

  1. if(a == b){ 
  2.  

如下 JSLint 的輸出:

 

  1. Expected ‘===’ and instead saw ‘==’. 
  2. if(a == b){ 

 

(4)并且使用==可能會(huì)出現(xiàn)一些奇怪的現(xiàn)象,這些奇怪的現(xiàn)象可能會(huì)給代碼埋入隱患:

 

  1. null == undefined          //true 
  2. '' == '0'                  //false 
  3. 0  == ''                   //true 
  4. 0  == '0'                  //true 
  5.  ' == 0            //true 
  6. new String("abc") == "abc" //true 
  7. new Boolean(true) == true  //true 
  8. true == 1                  //true 

上面的比較在用===的時(shí)候都是 false,這樣才是比較合理的。例如第一點(diǎn) null 居然會(huì)等于 undefined,就特別地奇怪,因?yàn)?null 和 undefined 是兩個(gè)毫無(wú)關(guān)系的值,null 應(yīng)該是作為初始化空值使用,而 undefined 是用于檢驗(yàn)?zāi)硞€(gè)變量是否未定義。這和第 1 點(diǎn)介紹強(qiáng)類型的思想是相通的。

4. 合并表達(dá)式

如果用 1 句代碼就可以實(shí)現(xiàn) 5 句代碼的功能,那往往 1 句代碼的執(zhí)行效率會(huì)比較高,并且可讀性可能會(huì)更好

(1)用三目運(yùn)算符取代簡(jiǎn)單的 if-else

如上面的 getPrice 函數(shù):

 

  1. function getPrice(count){ 
  2.     if(count < 0) return -1; 
  3.     else return count * 100; 

可以改成:

 

  1. function getPrice(count){ 
  2.     return count < 0 ? return -1 : count * 100; 

這個(gè)比寫一個(gè) if-else 看起來(lái)清爽多了。當(dāng)然,如果你寫了 if-else,壓縮工具也會(huì)幫你把它改三目運(yùn)算符的形式:

 

  1. function getPrice(e){return 0>e?-1:100*e} 

(2)連等

連等是利用賦值運(yùn)算表達(dá)式會(huì)返回所賦的值,并且執(zhí)行順序是從右到左的,如下:

 

  1. overtime = favhouse = listingDetail = {...} 

有時(shí)候你會(huì)看到有人這樣寫:

 

  1. var age = 0; 
  2. if((age = +form.age.value) >= 18){ 
  3.     console.log("你是成年人"); 
  4. else { 
  5.     consoe.log("小朋友,你還有" + (18 - age) + "就成年了"); 

也是利用了賦值表達(dá)式會(huì)返回一個(gè)值,在 if 里面賦值的同時(shí)用它的返回值做判斷,然后 else 里面就已經(jīng)有值了。上面的+號(hào)把字符串轉(zhuǎn)成了整數(shù)。

(3)自增

利用自增也可以簡(jiǎn)化代碼。如下,每發(fā)出一條消息,localMsgId 就自增 1:

 

  1. chatService.sendMessage(localMsgId++, msgContent); 

5. 減少魔數(shù)

例如,在某個(gè)文件的第 800 行,冒出來(lái)了一句:

 

  1. dialogHandler.showQuestionNaire("seller""sell", 5, true); 

就會(huì)讓人很困惑了,上面的四個(gè)常量分別代表什么呢,如果我不去查一個(gè)那個(gè)函數(shù)的變量說(shuō)明就不能夠很快地意會(huì)到這些常量分別有什么用。這些意義不明的常量就叫“魔數(shù)”。所以最好還是給這些常量取一個(gè)名字,特別是在一些比較關(guān)鍵的地方。例如上面的代碼可改成:

 

  1. var naireType = "seller"
  2.     dialogType = "sell"
  3.     questionsCount = 5, 
  4.     reloadWindow = true
  5.  
  6. naireHandler.showNaire(naireType, dialogType, questionsCount, reloadWindow); 

這樣意義就很明顯了。

6. 使用 ES6 簡(jiǎn)化代碼

ES6 已經(jīng)發(fā)展很多年了,兼容性也已經(jīng)很好了。恰當(dāng)?shù)厥褂?,可以讓代碼更加地簡(jiǎn)潔優(yōu)雅。

(1)使用箭頭函數(shù)取代小函數(shù)

有很多使用小函數(shù)的場(chǎng)景,如果寫個(gè) function,代碼起碼得寫 3 行,但是用箭頭函數(shù)一行就搞定了,例如實(shí)現(xiàn)數(shù)組從大到小排序:

 

  1. var nums = [4, 8, 1, 9, 0]; 
  2. nums.sort(function(a, b){ 
  3.     return b - a; 
  4. }); 
  5. //輸出[9, 8, 4, 1, 0] 

如果用箭頭函數(shù),排序只要一行就搞定了:

 

  1. var nums = [4, 8, 1, 9, 0];``nums.sort(a, b => b - a); 

代碼看起來(lái)簡(jiǎn)潔多了,還有 setTimeout 里面經(jīng)常會(huì)遇到只要執(zhí)行一行代碼就好了,寫個(gè) function 總感覺(jué)有點(diǎn)麻煩,用字符串的方式又不太好,所以這種情況用箭頭函數(shù)也很方便:

 

  1. setTimeout(() => console.log("hi"), 3000) 

箭頭函數(shù)在 C++/Java 等其它語(yǔ)言里面叫做 Lambda 表達(dá)式,Ruby 比較早就有這種語(yǔ)法形式了,后來(lái) C++/Java 也實(shí)現(xiàn)了這種語(yǔ)法。當(dāng)然箭頭函數(shù)或者 Lambda 表達(dá)式不僅適用于這種一行的,多行代碼也可以,不過(guò)在一行的時(shí)候它的優(yōu)點(diǎn)才比較明顯。

(2)使用 ES6 的 class

雖然 ES6 的 class 和使用 function 的 prototype 本質(zhì)上是一樣的,都是用的原型。但是用 class 可以減少代碼量,同時(shí)讓代碼看起來(lái)更加地高大上,使用 function 要寫這么多:

 

  1. function Person(name, age){ 
  2.     this.name = name
  3.     this.age = age; 
  4.  
  5. Person.prototype.addAge = function(){ 
  6.     this.age++; 
  7. }; 
  8.  
  9. Person.prototype.setName = function(name){ 
  10.     this.name = name
  11. }; 

使用 class 代碼看加地簡(jiǎn)潔易懂:

 

  1. class Person{ 
  2.     constructor(name, age){ 
  3.         this.name = name
  4.         this.age = age; 
  5.     } 
  6.     addAge(){ 
  7.         this.age++; 
  8.     } 
  9.     setName(name){ 
  10.         this.name = name
  11.     } 

并且 class 還可以很方便地實(shí)現(xiàn)繼承、靜態(tài)的成員函數(shù),就不需要自己再去通過(guò)一些技巧去實(shí)現(xiàn)了。

(3)字符串拼接

以前要用+號(hào)拼接:

 

  1. var tpl = 
  2.     '<div>' + 
  3.     '    <span>1</span>' + 
  4.     '</div>'

 

 

現(xiàn)在只要用兩個(gè)反引號(hào)“`”就可以了:

 

  1. var tpl = 
  2. `   <div> 
  3.         <span>1</span> 
  4.     </div> 
  5. `; 

 

 

另外反引號(hào)還支持占位替換,原本你需要:

 

  1. var page = 5, 
  2.     type = encodeURIComponet("#js"); 
  3. var url = "/list?page=" + page + "&type=" + type; 

現(xiàn)在只需要:

 

  1. var url = `/list?page=${page}&type=${type}`; 

就不用使用+號(hào)把字符串拆散了。

(4)塊級(jí)作用域變量

塊級(jí)作用域變量也是 ES6 的一個(gè)特色,下面的代碼是一個(gè)任務(wù)隊(duì)列的模型抽象:

 

  1. var tasks = []; 
  2. for(var i = 0; i < 4; i++){ 
  3.     tasks.push(function(){ 
  4.         console.log("i is " + i); 
  5.     }); 
  6. for(var j = 0; j < tasks.length; j++){ 
  7.     tasks[j](); 

但是上面代碼的執(zhí)行輸出是 4,4,4,4,并且不是想要輸出:0,1,2,3,所以每個(gè) task 就不能取到它的 index 了,這是因?yàn)殚]包都是用的同一個(gè) i 變量,i 已經(jīng)變成 4 了,所以執(zhí)行閉包的時(shí)候就都是 4 了。那怎么辦呢?可以這樣解決:

 

  1. var tasks = []; 
  2. for(var i = 0; i < 4; i++){ 
  3.     !function(k){ 
  4.         tasks.push(function(){ 
  5.             console.log("i is " + k); 
  6.         }); 
  7.     }(i); 
  8. for(var j = 0; j < tasks.length; j++){ 
  9.     tasks[j](); 

把 i 賦值給了 k,由于 k 它是一個(gè) function 的一個(gè)參數(shù),每次執(zhí)行函數(shù)的時(shí)候,肯定會(huì)實(shí)例化新的 k,所以每次的 k 都是不同的變量,這樣就輸出就正常了。但是代碼看起來(lái)有點(diǎn)別扭,如果用 ES6,只要把 var 改成 let 就可以了:

 

  1. var tasks = []; 
  2. for(let i = 0; i <= 4; i++){ 
  3.     tasks.push(function(){ 
  4.         console.log("i is " + i); 
  5.     }); 
  6. for(var j = 0; j < tasks.length; j++){ 
  7.     tasks[j](); 

只改動(dòng)了 3 個(gè)字符就達(dá)到了目的。因?yàn)?for 循環(huán)里面有個(gè)大括號(hào),大括號(hào)就是一個(gè)獨(dú)立的作用域,let 定義的變量在獨(dú)立的作用域里面它的值也是獨(dú)立的。當(dāng)然即使沒(méi)寫大括號(hào) for 循環(huán)執(zhí)行也是獨(dú)立的。除了以上幾點(diǎn),ES6 還有其它一些比較好用的功能,如 Object 的 assign,Promise 等,也是可以幫助寫出簡(jiǎn)潔高效的代碼。以上列了我自己在實(shí)際寫代碼過(guò)程中遇到的一些問(wèn)題和一些個(gè)人認(rèn)為比較重要的方面,其它的還有變量命名、縮進(jìn)、注釋等,這里就不提及了。寫代碼的風(fēng)格也體現(xiàn)了編程的素養(yǎng),有些人的代碼看起來(lái)非常地干凈利落,而有些人的代碼看起來(lái)讓人比較痛苦。這種編程素質(zhì)的提升需要有意識(shí)地去做一些改進(jìn),有些人雖然代碼寫得很爛,但是他自己并不覺(jué)得有什么問(wèn)題。這就需要多去學(xué)下別人的代碼,甚至學(xué)一下其它語(yǔ)言的書寫,兩者一比較就能發(fā)現(xiàn)差異,或者看下這方面的書,像什么代碼大全之類的。

責(zé)任編輯:華軒 來(lái)源: 前端工匠
相關(guān)推薦

2019-09-17 14:31:52

JSJavaScript前端

2016-01-13 11:39:52

CSS邊框網(wǎng)站

2020-07-15 08:37:11

JavaScript開(kāi)發(fā)技術(shù)

2019-04-04 14:05:20

consolejs前端

2010-04-02 09:26:53

CentOS系統(tǒng)

2020-06-01 07:41:52

Gmail郵箱郵件安全電子郵件

2022-10-31 07:09:15

拷貝代碼項(xiàng)目

2024-11-21 15:56:37

2015-08-17 14:28:48

UbuntuNvidia Linu驅(qū)動(dòng)

2015-08-20 09:19:46

ios9uistackview

2009-11-24 10:10:06

D-link無(wú)線路由器

2015-07-20 15:24:44

Linux工具截圖

2018-07-16 00:09:30

數(shù)據(jù)科學(xué)大數(shù)據(jù)機(jī)器學(xué)習(xí)

2023-11-28 10:17:37

2012-06-20 13:36:42

Surface平板

2009-11-17 08:46:04

Windows 7基站建立

2018-03-15 09:20:00

前端JSconsole

2009-02-24 08:21:22

Windows 7桌面亮麗

2019-07-10 10:20:36

前端用戶體驗(yàn)javascript

2022-08-29 18:34:46

Pythonsubprocess系統(tǒng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 欧美一区二区三区高清视频 | 国内久久精品 | 久久久影院 | 日本网站免费在线观看 | 亚洲第一成人影院 | 欧美日韩中文字幕在线 | 国产精品久久久久免费 | av电影一区二区 | 欧美久久久 | 国产视频在线一区二区 | 99热这里 | 亚洲色图婷婷 | 国产美女网站 | 99九色 | 天天爽综合网 | 日韩精品一区二区三区高清免费 | 欧美中文字幕在线观看 | 老司机深夜福利网站 | 麻豆国产一区二区三区四区 | 日本淫视频 | 99热最新网址| 99精品欧美一区二区三区 | 99精品网站 | 欧美一区二 | 色婷婷久久综合 | 7799精品视频天天看 | 国产精品日日摸夜夜添夜夜av | 毛片大全 | 日韩一区二区三区视频在线播放 | 免费黄色av| 久久综合久久综合久久综合 | av一级毛片| 综合久久av| jav成人av免费播放 | 天堂视频免费 | 欧美一区二区 | 综合久久99 | 日韩精品成人免费观看视频 | 成人免费一区二区三区牛牛 | 欧美日本一区二区 | 欧美三级网站 |