日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JS书写优化

發布時間:2023/12/10 javascript 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JS书写优化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

網上有不少關于JS編寫優化建議,這里我根據自己的經驗提出一些比較有用的意見。

1、按強類型風格寫代碼


JS是弱類型的,但是寫代碼的時候不能太隨意,寫得太隨意也體現了編碼風格不好。下面分點說明:
(1)定義變量的時候要指明類型,告訴JS解釋器這個變量是什么數據類型的,而不要讓解釋器去猜,例如不好的寫法:


var?num,??

str,??

?obj;??


聲明了三個變量,但其實沒什么用,因為解釋器不知道它們是什么類型的,好的寫法應該是這樣的:


var?num?=?0,??

str?=?'',??

obj?=?null;??


定義變量的時候就給他一個默認值,這樣不僅方便了解釋器,也方便了閱讀代碼的人,他會在心里有數——知道這些變量可能會當作什么用。
(2)不要隨意地改變變量的類型,例如下面代碼:


var?num?=?5;??

num?=?"-"?+?num;??


第1行它是一個整型,第2行它變成了一個字符串。因為JS最終都會被解釋成匯編的語言,匯編語言變量的類型肯定是要確定的,你把一個整型的改成了字符串,那解釋器就得做一些額外的處理。


并且這種編碼風格是不提倡的,有一個變量第1行是一個整型,第10行變成了一個字符串,第20行又變成了一個object,這樣就讓閱讀代碼的人比較困惑,上面明明是一個整數,怎么突然又變成一個字符串了。好的寫法應該是再定義一個字符串的變量:


var?num?=?5;??

var?sign?=?"-"?+?num;??


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


function?getPrice(count){??

?if(count?<?0)?return?"";??

else?return?count?*?100;??

}??


getPrice這個函數有可能返回一個整數,也有可能返回一個空的字符串。這樣寫也不太好,雖然它是符合JS語法的,但這種編碼風格是不好的。


使用你這個函數的人會有點無所適從,不敢直接進行加減乘除,因為如果返回字符串進行運算的話值就是NaN了。


函數的返回類型應該是要確定的,如下面是返回整型:


function?getPrice(count){??

if(count?<?0)?return?-1;??

else?return?count?*?100;??

}??


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


2、減少作用域查找



(1)不要讓代碼暴露在全局作用域下
例如以下運行在全局作用域的代碼:


<script>??

var?map?=?document.querySelector("#my-map");??

map.style.height?=?"600px";??

</script>??


有時候你需要在頁面直接寫一個script,要注意在一個script標簽里面,代碼的上下文都是全局作用域的,由于全局作用域比較復雜,查找比較慢。


例如上面的map變量,第二行在使用的時候,需要在全局作用域查找一下這個變量,假設map是在一個循環里面使用,那可能就會有效率問題了。所以應該要把它搞成一個局部的作用域:


<script>??

!function(){??

var?map?=?document.querySelector("#my-map");??

?map.style.height?=?"600px";??

}()??

</script>??


上面用了一個function制造一個局部作用域,也可以用ES6的塊級作用域。由于map這個變量直接在當前的局部作用域命中了,所以就不用再往上一級的作用域(這里是全局作用域)查找了,而局部作用域的查找是很快的。


同時直接在全局作用域定義變量,會污染window對象。

(2)不要濫用閉包


閉包的作用在于可以讓子級作用域使用它父級作用域的變量,同時這些變量在不同的閉包是不可見的。


這樣就導致了在查找某個變量的時候,如果當前作用域找不到,就得往它的父級作用域查找,一級一級地往上直到找到了,或者到了全局作用域還沒找到。因此如果閉包嵌套得越深,那么變量查找的時間就越長。如下:


function?getResult(count){??

count++;??

function?process(){??

var?factor?=?2;??

return?count?*?factor?-?5;??

}??

?return?process();??

}??


上面的代碼定義了一個process函數,在這個函數里面count變量的查找時間要高于局部的factor變量。

其實這里不太適合用閉包,可以直接把count傳給process:


function?getResult(count){??

count++;??

?function?process(count){??

?var?factor?=?2;??

return?count?*?factor?-?5;??

}??

return?process(count);??

}??


這樣count的查找時間就和factor一樣,都是在當前作用域直接命中。這個就啟示我們如果某個全局變量需要頻繁地被使用的時候,可以用一個局部變量緩存一下,如下:


var?url?=?"";??

if(window.location.protocal?===?"https:"){??

url?=?"wss://xxx.com"?+?window.location.pathname?+?window.location.search;??

}??


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


var?url?=?"";??

var?location?=?window.location;??

if(location.protocal?===?"https:"){??

url?=?"wss://xxx.com"?+?location.pathname?+?location.search;??

}??


搞成了一個局變變量,這樣查找就會明顯快于全局的查找,代碼也可以寫少一點。


3、避免==的使用


這里你可能會有疑問了,有些人喜歡用==,有些人喜歡用===,大家的風格不一樣,你為什么要強制別人用===呢?習慣用==的人,不能僅僅是因為==比===少敲了一次鍵盤。為什么不提倡用==呢?
(1)如果你確定了變量的類型,那么就沒必要使用==了,如下:


if(typeof?num?!=?"undefined"){????

}???

var?num?=?parseInt(value);??

if(num?==?10){??

}??

上面的兩個例子都是確定類型的,一個是字符串,一個是整數。就沒必要使用==了,直接用===就可以了。

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


var?totalPage?=?"5";??

if(parseInt(totalPage)?===?1){??

}??

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


if(a?==?b){??

}??

如下JSLint的輸出:


Expected?‘===’?and?instead?saw?‘==’.????

if(a?==?b){??


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


?null?==?undefined??????????//true??

''?==?'0'??????????????????//false??

0??==?''???????????????????//true??

0??==?'0'??????????????????//true??

'?
?'
?==?0????????????//true??

new?String("abc")?==?"abc"?//true??

new?Boolean(true)?==?true??//true??

true?==?1??????????????????//true??


上面的比較在用===的時候都是false,這樣才是比較合理的。例如第一點null居然會等于undefined,就特別地奇怪,因為null和undefined是兩個毫無關系的值,null應該是作為初始化空值使用,而undefined是用于檢驗某個變量是否未定義。
這和第1點介紹強類型的思想是相通的。


4、合并表達式


如果用1句代碼就可以實現5句代碼的功能,那往往1句代碼的執行效率會比較高,并且可讀性可能會更好
(1)用三目運算符取代簡單的if-else
如上面的getPrice函數:


?function?getPrice(count){??

?if(count?<?0)?return?-1;??

else?return?count?*?100;??

}??


可以改成:

function?getPrice(count){??

return?count?<?0???return?-1?:?count?*?100;??

}??


這個比寫一個if-else看起來清爽多了。當然,如果你寫了if-else,壓縮工具也會幫你把它改三目運算符的形式:


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


(2)連等
連等是利用賦值運算表達式會返回所賦的值,并且執行順序是從右到左的,如下:


overtime?=?favhouse?=?listingDetail?=?{...}??


有時候你會看到有人這樣寫:


var?age?=?0;??

if((age?=?+form.age.value)?>=?18){??

?console.log("你是成年人");??

}?else?{??

?consoe.log("小朋友,你還有"?+?(18?-?age)?+?"就成年了");??

}??

也是利用了賦值表達式會返回一個值,在if里面賦值的同時用它的返回值做判斷,然后else里面就已經有值了。上面的+號把字符串轉成了整數。

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


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

5、減少函數


例如,在某個文件的第800行,冒出來了一句:


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


就會讓人很困惑了,上面的四個常量分別代表什么呢,如果我不去查一個那個函數的變量說明就不能夠很快地意會到這些常量分別有什么用。這些意義不明的常量就叫“魔數”。

所以最好還是給這些常量取一個名字,特別是在一些比較關鍵的地方。例如上面的代碼可改成:


?var?naireType?=?"seller",??

dialogType?=?"sell",??

questionsCount?=?5,??

reloadWindow?=?true;??

naireHandler.showNaire(naireType,?dialogType,?questionsCount,?reloadWindow);??

這樣意義就很明顯了。

6、使用ES6簡化代碼


ES6已經發展很多年了,兼容性也已經很好了。恰當地使用,可以讓代碼更加地簡潔優雅。
(1)使用箭頭函數取代小函數
有很多使用小函數的場景,如果寫個function,代碼起碼得寫3行,但是用箭頭函數一行就搞定了,例如實現數組從大到小排序:


var?nums?=?[4,?8,?1,?9,?0];??

nums.sort(function(a,?b){??

return?b?-?a;??

});??

//輸出[9,?8,?4,?1,?0]??


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


var?nums?=?[4,?8,?1,?9,?0];??

nums.sort(a,?b?=>?b?-?a);??


代碼看起來簡潔多了,還有setTimeout里面經常會遇到只要執行一行代碼就好了,寫個function總感覺有點麻煩,用字符串的方式又不太好,所以這種情況用箭頭函數也很方便:


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


箭頭函數在C++/Java等其它語言里面叫做Lambda表達式,Ruby比較早就有這種語法形式了,后來C++/Java也實現了這種語法。

當然箭頭函數或者Lambda表達式不僅適用于這種一行的,多行代碼也可以,不過在一行的時候它的優點才比較明顯。

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


function?Person(name,?age){??

this.name?=?name;??

this.age?=?age;??

}??

Person.prototype.addAge?=?function(){??

?this.age++;??

};????

Person.prototype.setName?=?function(name){??

this.name?=?name;??

};??


使用class代碼看加地簡潔易懂:


class?Person{??

constructor(name,?age){??

this.name?=?name;??

?this.age?=?age;??

? ?}??

addAge(){??

?this.age++;??

????}??

setName(name){??

this.name?=?name;??

? }??

}??


并且class還可以很方便地實現繼承、靜態的成員函數,就不需要自己再去通過一些技巧去實現了。

(3)字符串拼接
以前要用+號拼接:


?var?tpl?=???

'<div>'?+???

'????<span>1</span>'?+??

??'</div>';??

現在只要用兩個反引號“`”就可以了:


var?tpl?=???

<div>??

<span>1</span>??

?</div>??

`;??

另外反引號還支持占位替換,原本你需要:


var?page?=?5,??

type?=?encodeURIComponet("#js");??

var?url?=?"/list?page="?+?page?+?"&type="?+?type;??


現在只需要:


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


就不用使用+號把字符串拆散了。

(4)塊級作用域變量
塊級作用域變量也是ES6的一個特色,下面的代碼是一個任務隊列的模型抽象:


?var?tasks?=?[];??

for(var?i?=?0;?i?<?4;?i++){??

tasks.push(function(){??

console.log("i?is?"?+?i);??

?});??

}??

for(var?j?=?0;?j?<?tasks.length;?j++){??

?tasks[j]();??

}??

但是上面代碼的執行輸出是4,4,4,4,并且不是想要輸出:0,1,2,3,所以每個task就不能取到它的index了,這是因為閉包都是用的同一個i變量,i已經變成4了,所以執行閉包的時候就都是4了。那怎么辦呢?可以這樣解決:


var?tasks?=?[];??

for(var?i?=?0;?i?<?4;?i++){??

?!function(k){??

? tasks.push(function(){??

?console.log("i?is?"?+?k);??

? ? ? });??

????}(i);??

}??

for(var?j?=?0;?j?<?tasks.length;?j++){??

????tasks[j]();??

}??


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


var?tasks?=?[];??

for(let?i?=?0;?i?<=?4;?i++){??

????tasks.push(function(){??

????????console.log("i?is?"?+?i);??

????});??

}??

for(var?j?=?0;?j?<?tasks.length;?j++){??

????tasks[j]();??

}??


只改動了3個字符就達到了目的。因為for循環里面有個大括號,大括號就是一個獨立的作用域,let定義的變量在獨立的作用域里面它的值也是獨立的。當然即使沒寫大括號for循環執行也是獨立的。

除了以上幾點,ES6還有其它一些比較好用的功能,如Object的assign,Promise等,也是可以幫助寫出簡潔高效的代碼。

以上列了我自己在實際寫代碼過程中遇到的一些問題和一些個人認為比較重要的方面,其它的還有變量命名、縮進、注釋等,這里就不提及了。寫代碼的風格也體現了編程的素養,有些人的代碼看起來非常地干凈利落,而有些人的代碼看起來讓人比較痛苦。


這種編程素質的提升需要有意識地去做一些改進,有些人雖然代碼寫得很爛,但是他自己并不覺得有什么問題。


這就需要多去學下別人的代碼,甚至學一下其它語言的書寫,兩者一比較就能發現差異,或者看下這方面的書,像什么代碼大全之類的。


總結

以上是生活随笔為你收集整理的JS书写优化的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 漂亮少妇高潮午夜精品 | 午夜在线一区二区三区 | 亚洲午夜av在线 | 大j8黑人w巨大888a片 | 国产视频一区在线播放 | 偷拍中国夫妇高潮视频 | 国产日韩欧美不卡 | 国产亚洲成av人片在线观看桃 | 天堂网www在线 | 午夜视频网站在线观看 | av一级免费 | 日本人妻熟妇久久久久久 | 成人午夜淫片免费观看 | 一本大道一区二区 | 91喷水 | 美女毛片在线观看 | 夜色一区 | 日本欧美一区二区三区不卡视频 | 四虎成人在线观看 | 黑人巨大猛交丰满少妇 | 国产黄色大片在线观看 | 国产丰满麻豆 | 免费黄视频在线观看 | 99热这里精品 | 欧美第一精品 | 国产乱视频 | 日本久久一级片 | 在线天堂一区 | 日韩综合第一页 | 尤物在线视频 | 日韩亚洲欧美精品 | 性色av蜜臀av | 网站在线免费观看 | 日本一区二区三区中文字幕 | 最新毛片网 | 99热首页| 亚洲天堂小说 | 久久久免费高清视频 | 橹图极品美女无圣光 | 国产在线一级片 | 中国av在线 | 亚洲第一在线 | 久久网一区 | 久久大尺度 | 日韩成人av网址 | www.美色吧.com | 免费成年人视频 | 青青视频在线免费观看 | 以女性视角写的高h爽文 | 波多野吉衣毛片 | 人与动物毛片 | 四虎永久网站 | 最近日韩中文字幕中文 | 国产精品福利一区二区三区 | 欧美私人影院 | 国产视频你懂得 | 潘金莲一级淫片aaaaa | 欧美与黑人午夜性猛交久久久 | 呦呦av | 欧美国产精品一区二区 | 美女超碰在线 | 欧美久久激情 | 成人综合一区 | 精品国产一区二区三区久久狼黑人 | 亚洲a毛片 | 中文字幕高清在线 | 日韩亚洲在线 | 国产精品国产三级国产传播 | 天堂社区av| 伊人久久久 | 91国产精品一区 | 久久99精品久久久久子伦 | 高清成人免费视频 | 人妻精品无码一区二区 | 亚洲精品国产成人 | 男女被到爽流尿 | 欧美成人午夜影院 | 俄罗斯毛片基地 | 鲁鲁狠狠狠7777一区二区 | 极品久久久 | 亚洲日批视频 | 亚洲精品视频在线免费 | 手机看片欧美日韩 | 被各种性器调教到哭vk | 狠狠干2017 | 最新色网站| 日韩精品视频中文字幕 | 视频一区二区三 | 黄色片视频免费在线观看 | 日韩av一区在线观看 | 日本特黄特黄刺激大片 | 两个人做羞羞的视频 | 91网站在线播放 | 美女乱淫 | 欧美顶级少妇做爰hd | 性欧美free | 日日夜夜精品视频免费 | 亚洲欧美日韩国产一区二区三区 | 天天操国产 |