溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

HTML/CSS/JS編碼規(guī)范有哪些

發(fā)布時間:2021-11-06 15:42:36 來源:億速云 閱讀:88 作者:iii 欄目:web開發(fā)

這篇文章主要講解了“HTML/CSS/JS編碼規(guī)范有哪些”,文中的講解內(nèi)容簡單清晰,易于學(xué)習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習“HTML/CSS/JS編碼規(guī)范有哪些”吧!

一、HTML編碼規(guī)范

1. img標簽要寫alt屬性

根據(jù)W3C標準,img標簽要寫alt屬性,如果沒有就寫一個空的。但是一般要寫一個有內(nèi)容的,根據(jù)圖片想要表達的意思,因為alt是在圖片無法加載時顯示的文字。如下不太好的寫法:

<img src="company-logo.svg" alt="ABC Company Logo">

更好的寫法:

<img src="chime-logo.svg" alt="ABC Company">

這里就不用告訴用戶它是一個Logo了,直接告訴它是ABC Compay就好了。再如:

<img src="user-head.jpg" alt="User Portrait">

可改成:

<img src="user-head.jpg" alt="Bolynga Team">

如果圖片顯示不出來,就直接顯示用戶的名字。

有些人偷懶就直接寫個空的alt那也可以,但是在一些重要的地方還是要寫一下,畢竟它還是有利于SEO.

2. 單標簽不要寫閉合標簽

為什么?因為寫了也沒用,還顯得你不懂html規(guī)范,我們不是寫XHTML。常見的單標簽有img、link、input、hr、br,如下不好的寫法:

<img src="test.jpg"></img><br/> <input type="email" value=""/>

應(yīng)改成:

<img src="test.jpg"><br> <input type="email" value="">

如果你用React寫jsx模板,它就要求每個標簽都要閉合,但是它始終不是原生html.

3. 自定義屬性要以data-開頭

自己添加的非標準的屬性要以data-開頭,否則 w3c validator 會認為是不規(guī)范的,如下不好的寫法:

<div count="5"></div>

應(yīng)改成:

<div data-count="5"></div>

4. td要在tr里面,li要在ul/ol里面

如下不好的寫法:

<div>     <li></li>     <li></li> </div>

更常見的是td沒有寫在tr里面:

<table>     <td></td>     <td></td> </table>

如果你寫得不規(guī)范,有些瀏覽器會幫你矯正,但是有些可能就沒有那么幸運。因為標準并沒有說如果寫得不規(guī)范應(yīng)該怎么處理,各家瀏覽器可能有自己的處理方式。

5. ul/ol的直接子元素只能是li

有時候可能會直接在ul里面寫一個div或者span,以為這樣沒關(guān)系:

<ol>     <span>123</span>     <li>a</li>     <li>b</li> </ol>

這樣寫也是不規(guī)范的,不能直接在ol里面寫span,ol是一個列表,它的子元素應(yīng)該都是display: list-item的,突然冒出來個span,你讓瀏覽器如何自處。所以寫得不規(guī)范就會導(dǎo)致在不同的瀏覽器會有不同的表現(xiàn)。

同樣,tr的直接子元素都應(yīng)該是td,你在td里面寫tr那就亂了。

6. section里面要有標題標簽

如果你用了section/aside/article/nav這種標簽的話,需要在里面寫一個h2/h3/h4之類的標題標簽,因為這四個標簽可以劃分章節(jié),它們都是獨立的章節(jié),需要有標題,如果UI里面根本就沒有標題呢?那你可以寫一個隱藏的標題標簽,如果出于SEO的目的,你不能直接display: none,而要用一些特殊的處理方式,如下套一個hidden-text的類:

<style>.hidden-text{position: absolute; left: -9999px; right: -9999px}</style> <section>     <h2>Listing Detail</h2> </section>

7. 使用section標簽增強SEO

使用section的好處是可以劃分章節(jié),如下代碼:

<body> <h2>Listing Detail</h2> <section>     <h2>House Infomation</h2>     <section>        <h2>LOCATION</h2>        <p></p>     </section>     <section>         <h2>BUILDING</h2>         <p></p>     </section> </section> <section>     <h2>Listing Picture</h2> </section> </body>

就會被outline成這樣的大綱:

Listing Detail

  1. House Infomation

    1. LOCATION

    2. BUILDING

  2. Listing Picture

可以使用 html5 outliner 進行實驗,可以看到,我們很任性地使用了多個h2標簽,這個在html4里面是不合法的。

8. 行內(nèi)元素里面不可使用塊級元素

例如下面的寫法是不合法的:

<a href="/listing?id=123">     <div></div> </a>

a標簽是一個行內(nèi)元素,行內(nèi)元素里面套了一個div的標簽,這樣可能會導(dǎo)致a標簽無法正常點擊。再或者是span里面套了div,這種情況下需要把inline元素顯式地設(shè)置display為block,如下代碼:

<a href="/listing?id=123" style="display: block">     <div></div> </a>

這樣就正常了。

9. 每個頁面要寫<!DOCType html>

設(shè)置頁面的渲染模式為標準模式,如果忘記寫了會怎么樣?忘記寫了會變成怪異模式,怪異模式下很多東西渲染會有所不同,怪異模式下input/textarea的默認盒模型會變成border-box,文檔高度會變成可視窗口的高度,獲取window的高度時就不是期望的文檔高度。還有一個區(qū)別,父容器行高在怪異模式下將不會影響子元素,如下代碼:

<div><img src="test.jpg" style="height:100px"></div>

在標準模式下div下方會留點空白,而在怪異模式下會。這個就提醒我們在寫郵件模板時需要在頂部加上<!DOCType html>,因為在本地開發(fā)郵件模板時是寫html片段,沒有這個的話就會變成怪異模式。

10. 要用table布局寫郵件模板

由于郵件客戶端多種多樣,你不知道用戶是使用什么看的郵件,有可能是用的網(wǎng)頁郵箱,也有可能用的gmail/outlook/網(wǎng)易郵箱大師等客戶端。這些客戶端多種多樣,對html/css的支持也不一,所以我們不能使用高級的布局和排版,例如flex/float/absolute定位,使用較初級的table布局能夠達到兼容性最好的效果,并且還有伸縮的效果。

另外郵件模板里面不能寫媒體查詢,不能寫script,不能寫外聯(lián)樣式,這些都會被郵件客戶端過濾掉,樣式都得用內(nèi)聯(lián)style,你可以先寫成外聯(lián),然后再用一些工具幫你生成內(nèi)聯(lián)html。

寫完后要實際測一下,可以用QQ郵箱發(fā)送,它支持發(fā)送html格式文本,發(fā)完后在不同的客戶端打開看一下,看有沒有問題,如手機的客戶端,電腦的客戶端,以及瀏覽器。

由于你不知道用戶是用手機打開還是電腦打開,所以你不能把郵件內(nèi)容的寬度寫死,但是完全100%也不好,在PC大屏幕上看起來可能會太大,所以一般可以這樣寫:

<table style="border-collapse:collapse;font-family: Helvetica Neue,Helvetica,Arial;font-size:14px;width:100%;height:100%">     <tr><td valign="top"><table style="border:1px solid #ececec;border-top:none; max-width:600px;border-collapse:collapse">     <tr><td>內(nèi)容1</td></tr>     <tr><td>內(nèi)容2</td></tr> </table></td></tr></table>

最外面的table寬度100%,里面的table有一個max-width:600px,相對于外面的table居中。這樣在PC上最大寬度就為600px,而在手機客戶端上寬度就為100%。

但是有些客戶端如比較老的outlook無法識別max-width的屬性,導(dǎo)致在PC上太寬。但是這個沒有辦法,因為我們不能直接把寬度寫死不然在手機上就要左右滑了,也不能寫script判斷ua之類的方法。所以無法兼容較老版本outlook.

11. html要保持簡潔,不要套太多層

需要套很多層的,一般有兩種情況,一種是切圖不太會,需要套很多層來維持排版,第二種是會切圖,但是把UI拆解得太細。像以下布局:

HTML/CSS/JS編碼規(guī)范有哪些

我會這么寫:

<ul>     <li>         <div>             <img>         </div>         <div></div>     </li> </ul>

因為它是一個列表,所以外面用ul/li作為容器,里面就兩個div,一個圖片的float: left,另外一個文字的容器,這樣就可以了。不用套很多層,但是有一些是必要的,你寫得太簡單的話,擴展性不好,例如它是一個列表那你就應(yīng)該使用ul/ol,如果你要清除浮動,那你可能需要套一個clearfix的容器。

如果有一塊是整體,它整體向右排版,那么這一塊也要套一個容器,有時候為了實現(xiàn)一些效果,可能也要多套一個容器,例如讓外面的容器float,而里面的容器display: table-cell。但是你套這些容器應(yīng)該都是有價值,如果你只是為了在功能上看起來整齊劃一,區(qū)分明顯好像沒太大的意義。

12. 特殊情況下才在html里面寫script和style

通常來說,在html里面直接寫script和style是一種不好的實踐,這樣把樣式、結(jié)構(gòu)和邏輯都摻雜在一起了。但是有時候為了避免閃屏的問題,可能會直接在相應(yīng)的html后面跟上調(diào)整的script,這種script看起來有點丑陋,但是很實用,是沒有辦法的辦法。

13. 樣式要寫在head標簽里

樣式不能寫在body里,寫在body里會導(dǎo)致渲染兩次,特別是寫得越靠后,可能會出現(xiàn)閃屏的情況,例如上面的已經(jīng)渲染好了,突然遇到一個style標簽,導(dǎo)致它要重新渲染,這樣就閃了一下,不管是從碼農(nóng)的追求還是用戶的體驗,在body里面寫style終究是一種下策。

同樣地script不要寫在head標簽里面,會阻礙頁面加載。

而CSS也推薦寫成style標簽直接嵌在頁面上,因為如果搞個外鏈,瀏覽器需要先做域名解析,然后再建立連接,接著才是下載,這一套下來可能已經(jīng)過了0.5s/1s,甚至2~3秒。而寫在頁面的CSS雖然無法緩存,但是本身它也不會很大,再加gzip壓縮,基本上在50k以內(nèi)。

14. html要加上lang的屬性

如下,如果是英文的網(wǎng)頁,應(yīng)該這么寫:

<html> <html>

第一種表示它是英文的網(wǎng)頁,第二種表示它是美國英語的網(wǎng)頁,加上這個的好處是有利于SEO和屏幕閱讀器使用者,他可以快速地知道這個網(wǎng)頁是什么語言的,如果是中文可以這么寫:

<html>

15. 要在head標簽靠前位置寫上charset的meta標簽

如下,一般charset的meta標簽要寫在head標簽后的第一個標簽:

<head>    <meta charset="utf-8"> </head>

一個原因是避免網(wǎng)頁顯示unicode符號時亂碼,寫在前面是因為w3c有規(guī)定,語言編碼要在html文檔的前1024個字節(jié)。如果不寫的話在老的瀏覽器會有utf-7攻擊的隱患,具體可以自行查閱資料,只是現(xiàn)在的瀏覽器基本都去掉了對utf-7編碼的支持了。

charset的標簽寫成html5的這種比較簡潔的寫法就行了,不需要寫成html4這種長長的:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

據(jù)我所查,就算是IE6也支持那種簡短的寫法,雖然它不是一個html5瀏覽器。

16. 特殊符號使用html實體

不要直接把Unicode的特殊符號直接拷到html文檔里面,要使用它對應(yīng)的實體Entity,常用的如下表所示:

| 符號 | 實體編碼 |
| ? | ? |
| ¥ | ¥ |
| ? | ? |
| > | > |
| < | < |
| & | & |

特別是像?這種符號,不要從UI里面直接拷一個unicode的字符過去,如果直接拷過去會比較丑,它取的是用的字體里面的符號。

17. img空src的問題

有時候可能你需要在寫一個空的img標簽,然后在JS里面動態(tài)地給它賦src,所以你可能會這么寫:

<img src="" alt>

但是這樣寫會有問題,如果你寫了一個空的src,會導(dǎo)致瀏覽器認為src就是當前頁面鏈接,然后會再一次請求當前頁面,就跟你寫一個a標簽的href為空類似。如果是background-image也會有類似的問題。這個時候怎么辦呢?如果你隨便寫一個不存在的url,瀏覽器會報404的錯誤。

我知道的有兩種解決方法,第一種是把src寫成about:blank,如下:

<img src="about:blank" alt>

這樣它會去加載一個空白頁面,這個沒有兼容問題,不會加載當前頁面,也不會報錯。

第二種辦法是寫一個1px的透明像素的base64,如下代碼所示:

<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">

第二種可能比較符合規(guī)范,但是第一種比較簡單,并且沒有兼容性問題。

18. 關(guān)于行內(nèi)元素空格和換行的影響

有時候換行可能會引入空格,如下代碼:

<form>     <label>Email: </label>     <input type="email"> </form>

在label和input中間會有一個空格,這樣可能會導(dǎo)致設(shè)置lable的width和input 的width兩者的和等于form的時候會導(dǎo)致input換行了,有時候你檢查半天沒查出原因,最后可能發(fā)現(xiàn),原來是多了一個空格,而這個空格是換行引起的。這個時候你可能會有一個問題,為什么<form>和<label>之間以及<input>和</form>之間的換行為什么沒引入空格?這是因為塊級元素開始的空白文本將會被忽略,如下Chrome源碼的說明:

// Whitespace at the start of a block just goes away. Don't even

// make a layout object for this text.

并且,塊級元素后面的空白文本結(jié)點將不會參與渲染,也就是說像這種:

<div></div> <div></div>

兩個div之間有textNode的文本節(jié)點,但是不會參與渲染。

要注意的是注釋標簽也是正常的頁面標簽,也會給它創(chuàng)建一個相應(yīng)的節(jié)點,只是它不參與渲染。

19. 類的命名使用小寫字母加中劃線連接

如下使用-連接,不要使用駝峰式:

<div></div>

20. 不推薦使用自定義標簽

是否可以使用自定義標簽,像angular那樣都是用的自定義標簽,如下代碼:

<my-cotnainer></my-container>

一般不推薦使用自定義標簽,angular也有開關(guān)可以控制是否要使用自定義標簽。雖然使用自定義標簽也是合法的,只要你給他display: block,它就像一個div一樣了,但是不管是從SEO還是規(guī)范化的角度,自定義標簽還是有點另類,雖然可能你會覺得它的語義化更好。

21. 重復(fù)雜id和重復(fù)屬性

我們知道,如果在頁面寫了兩個一模一樣的id,那么查DOM的時候只會取第一個,同理重復(fù)的屬性也會只取第一個,如下:

<input type="text" name="books">

第二個class將會被忽略,className重復(fù)了又會怎么樣?重復(fù)的也是無效的,這里主要是注意如果你直接操作原生className要注意避免className重復(fù),如下代碼:

var input = form.books; input.className += " valid";

如果重復(fù)執(zhí)行的話,className將會有重復(fù)的valid類。

22. 不推薦使用屬性設(shè)置樣式

例如,如果你要設(shè)置一個圖片的寬高,可能這么寫:

<img src="test.jpg" alt width="400" height="300">

這個在ios的safari上面是不支持的,可以自行實驗。

或者table也有一些可以設(shè)置:

<table border="1"></table>

但是這種能夠用CSS設(shè)置的就用CSS,但是有一個例外就是canvas的寬高需要寫在html上,如下代碼:

<canvas width="800" height="600"></canvas>

如果你用CSS設(shè)置的話它會變成拉伸,變得比較模糊。

23. 使用適合的標簽

標簽使用上不要太單調(diào):

(1)如果內(nèi)容是表格就使用table,table有自適應(yīng)的優(yōu)點;如果是一個列表就使用ol/ul標簽,擴展性比較好

(2)如果是輸入框就使用input,而不是寫一個p標簽,然后設(shè)置contenteditable=true,因為這個在IOS Safari上光標定位容易出現(xiàn)問題。如果需要做特殊效果除外

(3)如果是粗體就使用b/strong,而不是自己設(shè)置font-weight

(4)如果是表單就使用form標簽,注意form里面不能套form

(5)如果是跳鏈就使用a標簽,而不是自己寫onclick跳轉(zhuǎn)。a標簽里面不能套a標簽

(6)使用html5語義化標簽,如導(dǎo)航使用nav,側(cè)邊欄使用aside,頂部和尾部使用header/footer,頁面比較獨立的部分可以使用article,如用戶的評論。

(7)如果是按鈕就應(yīng)該寫一個button或者<input type=”button”>,而不是寫一個a標簽設(shè)置樣式,因為使用button可以設(shè)置disabled,然后使用CSS的:disabled,還有:active等偽類使用,例如在:active的時候設(shè)置按鈕被按下去的感覺

(8)如果是標題就應(yīng)該使用標題標簽h2/h3/h4,而不是自己寫一個<p class=”title”></p>,相反如果內(nèi)容不是標題就不要使用標題標簽了

(9)在手機上使用select標簽,會有原生的下拉控件,手機上原生select的下拉效果體驗往往比較好,不管是IOS還是android,而使用<input type=”tel”>在手機上會彈一個電話號碼的鍵盤,<input type=”number”> <input type=”email”>都會彈相應(yīng)的鍵盤

(10)如果是分隔線就使用hr標簽,而不是自己寫一個border-bottom的樣式,使用hr容易進行檢查

(11)如果是換行文本就應(yīng)該使用p標簽,而不是寫br,因為p標簽可以用margin設(shè)置行間距,但是如果是長文本的話使用div,因為p標簽里面不能有p標簽,特別是當數(shù)據(jù)是后端給的,可能會帶有p標簽,所以這時容器不能使用p標簽。

24. 不要在https的鏈接里寫http的圖片

只要https的網(wǎng)頁請求了一張http的圖片,就會導(dǎo)致瀏覽器地址欄左邊的小鎖沒有了,一般不要寫死,寫成根據(jù)當前域名的協(xié)議去加載,用//開頭:

<img src=”//static.chimeroi.com/hello-world.jpg”>

二、CSS編碼規(guī)范

1. 文件名規(guī)范

文件名建議用小寫字母加中橫線的方式。為什么呢?因為這樣可讀性比較強,看起來比較清爽,像鏈接也是用這樣的方式,例如stackoverflow的url:

https://stackoverflow.com/questions/25704650/disable-blue-highlight-when-touch-press-object-with-cursorpointer

或者是github的地址:

https://github.com/wangjeaf/ckstyle-node

那為什么變量名不用小寫字母加小劃線的方式,如:family_tree,而是推薦用駝峰式的familyTree?C語言就喜歡用這種方式命名變量,但是由于因為下劃線比較難敲(shift + -),所以一般用駝峰式命名變量的居多。

引入CSS文件的link可以不用帶type="text/css",如下代碼:

<link rel="stylesheet" href="test.css">

因為link里面最重要的是rel這個屬性,可以不要type,但是不能沒有rel。

JS也是同樣道理,可以不用type,如下代碼:

<script src="test.js"></script>

沒有兼容性問題。

2. 屬性書寫順序

屬性的書寫順序?qū)τ跒g覽器來說沒有區(qū)別,除了優(yōu)先級覆蓋之外。但是如果順序保持一致的話,掃一眼可以很快地知道這個選擇器有什么類型的屬性影響了它,所以一般要把比較重要的屬性放前面。比較建議的順序是這樣的:

HTML/CSS/JS編碼規(guī)范有哪些

你可能會覺得我平時差不多就是這么寫的,那么說明你有一個比較好的素養(yǎng)。并且我覺得規(guī)則不是死,有時候可以靈活,就像你可能會用transform寫居中,然后把left/top/transform挨在一起寫了,我覺得這也是無可厚非的,因為這樣可以讓人一眼看出你要干嘛。

3. 不要使用樣式特點命名

有些人可能喜歡用樣式的特點命名,例如:

.red-font{     color: red; } .p1{     font-size: 18px; } .p2{     font-size: 16px; }

然后你在它的html里面就會看到套了大量的p1/p2/bold-font/right-wrap之類的類名,這種是不可取的,假設(shè)你搞了個red-font,下次UI要改顏色,那你寫的這個類名就沒用了,或者是在響應(yīng)式里面在右邊的排版在小屏的時候就會跑到下面去,那你取個right就沒用了。有些人先把UI整體瞄了一下,發(fā)現(xiàn)UI大概用了3種字號18px/16px/14px,于是寫3個類p1/p2/p3,不同的字號就套不同的類。這乍一看,好像寫得挺通用,但是當你看他的html時,你就瘋掉了,這些p1/p2/p3的類加起寫了有二三十個,密密麻麻的。我覺得如果要這樣寫的話還不如借助標題標簽如下:

.house-info h3{     font-size: 18px; } .house-info h4{     font-size: 16px; }

因為把它的字號加大了,很可能是一個標題,所以為什么不直接用標題標簽,不能僅僅擔心因為標題標簽會有默認樣式。

類的命名應(yīng)當使用它所表示的邏輯意義,如signup-success-toast、request-demo、agent-portrait、 company-logo等等。

如果有些樣式你覺得真的特別通用,那可以把它當作一個類,如clearfix,或者有些動畫效果,有幾個地方都要用到,我覺得這種較為復(fù)雜并且通用的可以單獨作為一個類。但是還是趨向于使用意義命名。

4. 不要使用hack

有些人在寫CSS的時候使用一些hack的方法注釋,如下:

.agent-name{     float: left;     _margin: 10px;     //padding: 20px; }

這種方法的原理是由于//或者_開頭的CSS屬性瀏覽器不認識,于是就被忽略,分號是屬性終止符,從//到分號的內(nèi)容都被瀏覽器忽略,但是這種注釋是不提倡的,要么把.css文件改成.less或者.scss文件,這樣就可以愉快地用//注釋了。

還有一些專門針對特定瀏覽器的hack,如*開頭的屬性是對IE6的hack。不管怎么樣都不要使用hack。

5. 選擇器的性能

選擇器一般不要寫超過3個,有些人寫sass或者less喜歡套很多層,如下:

.listings-list{     ul{         li{             .bed-bath{                 p{                      color: #505050;                 }             }         }     } }

一個容器就套一層,一層一層地套下來,最底層套了七八層,這么長的選擇器的性能比較差,因為Chrome里面是用遞歸從最后一個選擇器一直匹配到第一個,選擇器越多,匹配的時間就越長,所以時間會比較長,并且代碼的可讀性也比較差,為看到最里面的p標簽的樣式是哪個的我得一層層地往上看,看是哪里的p。代碼里面縮進了7、8層看起來也比較累。

一般只要寫兩三個比較重要的選擇器就好了,不用每個容器都寫進去,重要的目標元素套上class或者id。

最后一個選擇器的標簽的應(yīng)該少用,因為如果你寫個.container div{}的話,那么頁面上所有的div第一次都匹配中,因為它是從右往左匹配的,這樣的寫的好處是html不用套很多的類,但是擴展性不好,所以不要輕易這樣用,如果要用需要仔細考慮,如果合適才使用,最起碼不能濫用。

6. 避免選擇器誤選

有時候會出現(xiàn)自己的樣式受到其他人樣式的影響,或者自己的樣式不小心影響了別人,有可能是因為類的命名和別人一樣,還有可能是選擇器寫的范圍太廣,例如有人在他自己的頁面寫了:

* {     box-sizing: border-box; }

結(jié)果導(dǎo)致在他個頁面的公用彈框樣式掛了。一方面不要寫*全局匹配選擇器,不管從性能還是影響范圍來說都太大了,例如在一個有3個子選擇器的選擇器:

.house-info .key-detail .location{}復(fù)制代碼

在三個容器里面,*都是適用的,并且有些屬性是會繼承的,像font-size,會導(dǎo)致這三個容器都有font-size,然后一層層地覆蓋。

還有一種情況是濫用了:first-child、:nth-of-type這種選擇器,使用這種選擇器的后果是擴展性不好,只要html改了,就會導(dǎo)致樣式不管用了,或者影響到了其它無關(guān)元素。但是并不是說這種選擇器就不能用,只要用得好還是挺方便的,例如說在所有的li里面要讓最后一個li的margin-left小一點,那么可以這么寫:

.listing-list li:last-child{     margin-left: 10px; }

這可能比你直接套一個類強。但是不管怎么樣,不能濫用,合適的時候才使用,而不是僅僅為了少寫類名。

7. 減少覆蓋

覆蓋是一種常用的策略,也是一種不太優(yōu)雅的方式,如下代碼,為了讓每個house中間的20px的間距,但是第一個house不要有間距:

.house{     margin-top: 20px; } .house:first-child{     margin-top: 0; }

其實可以改成這樣:

.house + .house{     margin-top: 20px; }

只有前面有.house的.house才能命中這個選擇器,由于第一個.house前面沒有,所以命不中,這樣看起來代碼就簡潔多了。

還有這種情況,如下代碼所示:

.request-demo input{     border: 1px solid #282828; } .request-demo input[type=submit]{     border: none; }

其實可以借助一個:not選擇器:

.request-demo input:not([type=sbumit]){     border: 1px solid #282828; }

這樣看起來代碼也優(yōu)雅了很多。

有一種覆蓋是值得的,那就是響應(yīng)式里面小屏的樣式覆蓋大屏,如下:

.container{     width: 1080px;     margin: 0 auto; } @media (min-width: 1024px){     .container{         width: auto;         margin: 0 40px;     } }

大屏的樣式也可以寫成:

@media (min-width: 1025px){      .container{          width: 1080px;          margin: 0 auto;     } }

我一開始是就是這么寫的,為了遵循減少覆蓋原則,但是后來發(fā)現(xiàn)這種實踐不好,代碼容易亂,寫成覆蓋的好處在于可以在瀏覽器明顯地看到,小屏的樣式是覆蓋了哪個大屏的樣式,這個在大屏的時候又是怎么樣的。

8. 使用CSS3的選擇器完成一些高級的功能

上面提到:not可以讓代碼簡潔,還有其它一些很好用的。例如說只有兩個的時候一個占比50%,而有3個的時候一個占比33%,這個用CSS就可以實現(xiàn),如下:

.listing-list li{     width: 33%; } .listing-list li:first-child:nth-last-child(2), .listing-list li:first-child:nth-last-child(2) ~ li{      width: 50%; }

當li是第一個元素并且是倒數(shù)第二個元素的時候以及和它相鄰的li被第二組選擇器命中,它的寬度是50%,也就是只有兩個li的時候才能滿足這個條件。

另外還可以借用:hover/:focus/:invalid/:disabled等偽類選擇器完成一些簡單的交互。

9. 少用!important

important用來覆蓋屬性,特別是在CSS里面用來覆蓋style里的屬性,但是important還是少用為妙。有時候你為了偷懶直接寫個!important,以為這個的優(yōu)先級是最高的了,往往螳螂捕蟬,黃雀在后,很可能過不了多久又要再寫一個優(yōu)先級更高的覆蓋掉,這樣就略顯尷尬了。所以能少用還是少用。如果要覆蓋還是先通過增加添加選擇器權(quán)重的方式。

10. 多寫注釋

"程序猿最煩兩件事,第一件事是別人要他給自己的代碼寫文檔,第二件呢?是別人的程序沒有留下文檔"。注釋也是同樣道理,當看到很多綠色的注釋代碼神經(jīng)會比較放松,而當看到揉成一團還沒有注釋的代碼是比較壓抑的。CSS的注釋可包括:

(1)文件頂部的注釋
/*  * @description整個列表頁樣式入口文件  * @author yincheng.li  */
(2)模塊的注釋
/*詳情頁貸款計算器*/復(fù)制代碼
(3)簡單注釋
/*為了去除輸入框和表單點擊時的灰色背景*/ input,  form{     -webkit-tap-highlight-color:  rgba(255, 255, 255, 0); }
(4)TODO的注釋

有時候你看源碼的時候你會看到一些TODO的注釋:

/* TODO(littledan): Computed properties don't work yet in nosnap.    Rephrase when they do. */復(fù)制代碼

表示這些代碼還有待完善,或者有些缺陷需要以后修復(fù)。而這種TODO的注釋一般編輯器會把TODO高亮。

注意不要寫一些錯誤的誤導(dǎo)的注釋或者比較廢話的注釋,這種還不如不寫,如下:

/* 標題的字號要大一點 */ .listings h3{     font-size: 20px; }

11. 排版規(guī)范

不管是JS/CSS,縮進都調(diào)成4個空格,如果你用的sublime,在軟件的右下角有一個Tab Size,選擇Tab Size 4,然后再把最上面的Indent Using Spaces勾上,這樣,當你打一個tab鍵縮進的時候就會自動轉(zhuǎn)換成4個空格。如果你使用vim,新增或者編輯~/.vimrc文件新增一行:

:set tabstop=4

也會自動把縮進改成4個空格,其它編輯器自行查找設(shè)置方法。因為\t在不同的編輯器上顯示長度不一樣,而改成空格可以在不同人的電腦上格式保持一致。

多個選擇器共用一個樣式集,每個選擇器要各占一行,如下:

.landing-pop, .samll-pop-outer, .signup-success{        display: none; }

每個屬性名字冒號后面要帶個空格,~、>、+選擇器的前后也要帶一個空格:

.listings > li{     float: left; }

12. 屬性值規(guī)范

(1)如果值是0,通常都不用帶單位

例如:

.list{     border: 1px solid 0px;     margin: 0px; }

應(yīng)改成:

.list{     border: 1px solid 0;     margin: 0; }

但是有個特例,就是和時間有關(guān)的時間單位都要帶上秒s,如下兩個都是不合法的:

transition-duration: 0; transition: transform 0 linear;
(2)色值用十六進制,少用rgb

如下:

color: rgb(80, 80, 80);

應(yīng)改成:

color: #505050;

因為使用rgb是一個函數(shù),它還要計算一下轉(zhuǎn)換。如果是帶有透明度的再用rgba.

如果色值的六個數(shù)字一樣,那么寫3個就好:

color: #ccc;
(3)注意border none和0的區(qū)別

如下兩個意思一樣:

border: 0; border-width: 0;

而下面這兩個一樣:

border: none; border-style: none;

所以用0和none都可以去掉邊框。

你可能會說打包工具其實最后會幫我處理,但自己要保持一個良好的書寫習慣還是很重要的。

13. font-family的設(shè)置

注意使用系統(tǒng)字體的對應(yīng)的font-family名稱,如SFUIText Font這個字體,在Safari是-apple-system,而在Chrome是BlinkMacSystemFont,所以font-family可以這么寫:

font-family{     font-family: -apple-system, BlinkMacSystemFont, sans-serif; }

再如微軟雅黑,很多中文網(wǎng)站都用這個字體,要寫成:

font-family{     font-family: Microsoft YaHei; }

另外font-family不能在代碼任意設(shè)置,如果使用了自定義字體。如下代碼:

.title{     font-family: Lato Bold; }

因為如果你在代碼里面寫了好多個font-family,到時候要整體替換網(wǎng)頁的字體就很麻煩了,正確的做法應(yīng)該是這樣的:

h2, strong, b{     font-family: Lato Bold;     font-weight: normal; }

如果需要加粗就用標題標簽,或者b/strong標簽,并且要把font-weight調(diào)回來,因為那個字體本身就有加粗效果了,如果font-weight再是粗體的話瀏覽器會用自己的算法繼續(xù)加粗。如果是細體怎么辦,一方面一般細體用得比較少,另一方面沒有細體的標簽,可以通過套類的方式。

14. 不要設(shè)置太大的z-index

有些人喜歡設(shè)置z-index很大:

z-index: 99999;

以為他是老大了,不會有人再比他高了,但是螳螂捕蟬,黃雀在后,很快得再寫一個:

z-index: 999999;

通常自己頁面的業(yè)務(wù)邏輯的z-index應(yīng)該保持在個位數(shù)就好了。

15. 合并屬性

一般的說法是說為了提高性能,屬性要合并,但其實Chrome每個屬性都是單獨的,就算你合在一起,它也會幫你拆出來,如把margin拆成left/right/top/bottom,但是我們還是推薦寫成合的,因為它可以讓代碼看起來更簡潔,代碼量更少,如下代碼:

.container{     margin-top: 20px;     margin-left: 10px;     margin-right: 10px; }

可以寫成:

.container{     margin: 20px 10px 0; }

但是合在一起寫了,要注意別覆蓋了其它的設(shè)置,如上面把margin-bottom設(shè)置成了0.

再如:

.banner{     background-image: url(/test.jpg);     background-position: 0 0;     background-repeat: no-repeat; }

可以改成:

.banner{     background: url(test.jpg) 0 0 no-repeat; }

16. 注意float/absolute/fixed定位會強制設(shè)置成block

如下代碼:

a.btn {     float: left;     display: block;     width: 100px;     height: 30px; }

第二行的display: block其實是沒用的,因為如果你浮動了,目標元素就會具有塊級盒模型的特性,即使你display: table-cell或者inline也不管用。如果你是display: flex,那么float將會被忽略。

同樣地,absolute定位和fixed定位也有同樣的效果,會把行內(nèi)元素變成塊級的。

17. 清除浮動

清除浮動有多種方法,一般用clearfix大=法,雖然這個方法有缺陷,但是它比較簡單且能夠適用絕大多數(shù)的場景,一個兼容IE8及以上的clearfix的寫法:

.clearfix:after{     content: "";     display: table;     clear: both; }

就不要在末尾添加一個多余元素的方法清除浮動了,雖然也可行,但是比較low.

18. 引號的使用

(1)font-family

一般來說font-family不需要添加引號,即使字體名稱帶有空格也沒關(guān)系,但是有一種情況是一定要加上引號的,就是字體名稱剛好是關(guān)鍵詞,如下字體都需要加關(guān)鍵詞:

font-family: "inherit", "serif", "sans-serif", "monospace", "fantasy", and "cursive"
(2)background的url
background-url: url("//cdn.test.me/test.jpg");

你不加也可以,但是有一種一定要加,那就是url里面帶有特殊字符沒有轉(zhuǎn)義,如下:

background-url: url(//cdn.test.me/hello world.jpg)

上面瀏覽器會去加載//cdn.test.me/hello,然后報404。這種情況通常是圖片是用戶上傳的,圖片的名字帶有空格,后端給的url沒有對特殊字符做處理,就會有問題,所以當url是可變的時候,最好還是帶上引號:

background-url: url('//cdn.test.me/hello world.jpg');

這樣瀏覽器就能正常加載圖片了。這種情況最好的還是從源頭上避免,但我們也可以做個兼容。

(3)單引號還是雙引號

這兩個都是合法的,只是統(tǒng)一一下比較好,不能一下子單引號,一下子雙引號的,比較普遍的推薦是html使用雙引號,css使用單引號。

19. CSS動畫規(guī)范

(1)不要使用all屬性做動畫

使用transition做動畫的時候不要使用all所有屬性,在有一些瀏覽器上面可能會有一些問題,如下:

transition: all 2s linear;

在Safari上面可能會有一些奇怪的抖動,正確的做法是要用哪個屬性做動畫就寫哪個,如果有多個就用隔開,如下代碼所示:

transition: transform 2s linear,              opacity 2s linear;
(2)使用transform替代position做動畫

如果能用transform做動畫的,就不會使用left/top/margin等,因為transform不會造成重繪,性能要比position那些高很多,特別是在移動端的時候效果比較明顯。基本上位移的動畫都能用transform完成,不需要使用CSS2的屬性,如一個框從右到左彈出。

(3)偏向于使用CSS動畫替代JS動畫

例如把一個框,從下到上彈出,可以用jQuery的slideUp函數(shù),或者自己寫setInterval函數(shù)處理,但是這些沒有比用CSS來得好。使用CSS,初始狀態(tài)可以把框translate移動屏幕外,然后點擊的時候加上一個類,這個類的transform值為0,然后再用transition做動畫就好了。

20. 不要斷詞

英文的單詞或者數(shù)字如果當前行排不下會自動切到下一行,這樣就導(dǎo)致每行長短不一,有時候可能不太美觀,但是不能使用word-break: break-all把一個單詞拆成兩行,還有一種是使用:

hyphens: auto;

它會把單詞拆成用-連接的形式,看起來好像挺合理,但是由于它斷詞斷得不夠徹底,有些單詞斷不了,長短不一的現(xiàn)象看起來也比較明顯,有些單詞還被拆成了兩行,所以還不如不加。

因此,不要使用斷詞。

21. 不要設(shè)置圖標字體font-family

這個和上面提到的font-family設(shè)置是一樣的,不要在代碼里面手動設(shè)置font-family,如下:

.icon-up:before{     content: "\e950";     font-family: "icon-font"; }

正確的做法是給.icon-up的元素再套一個.icon的類,font-family等對圖標字體的相關(guān)設(shè)置都統(tǒng)一在這個類里面:

.icon{     font-family: "icon-font";     /* Better Font Rendering =========== */     -webkit-font-smoothing: antialiased;     -moz-osx-font-smoothing: grayscale; }

因為我們可能會添加其它一些設(shè)置,有個.icon的類統(tǒng)一處理比較好。就不要手動一個個去設(shè)置font-family了。

22. 設(shè)置常見樣式reset

由于每個瀏覽器都有自己的UA樣式,并且這些樣式還不太統(tǒng)一,所以需要做樣式reset,常見的reset有以下:

/* IE瀏覽器對輸入控件有自己的font-family,需要統(tǒng)一 */ input, textarea, button{     font-family: inherit; } /* Chrome瀏覽器會在輸入控制聚集的時候添加一個藍色的outline*/ input:focus, textarea:focus, select:focus{     outline: none; } /* 去掉textarea的可拉大小功能*/ textarea{     resize: none; } /* IOS Safari在橫屏的時候會放大字體,第二個屬性讓滑動更流暢 */ html{     -webkit-text-size-adjust: 100%;     -webkit-overflow-scrolling : touch; } /* 統(tǒng)一標簽的margin值和p標簽的line-height*/ body, p, h2, h3, ul, ol, figure, li{     padding: 0;     margin: 0; } h2, h3, p{     line-height: 150%; } /* 去掉select的默認樣式 */ select{     -webkit-appearance: none; } /* 如果有輸入內(nèi)容IE會給輸入框右邊加一個大大的X */ input::-ms-clear{     display: none;     width: 0;     height: 0; } /* 去掉number輸入框右邊點擊上下的小三角 */ input::-webkit-inner-spin-button{     -webkit-appearance: none; } input::-webki-outer-spin-button{     -webki-appearance: none; }

23. 圖片壓縮

不管是UI直接給的圖片還是自己從UI圖里切出來的圖片,都需要把圖片壓縮一下,建議使用 tinypng ,它可以在保持圖片質(zhì)量減少較低的情況下,把圖片壓得很厲害,比直接在PS里面設(shè)置壓縮質(zhì)量要強。如果是色彩比較豐富的圖片要使用jpg格式,不能使用png格式,png會大得多,如果是logo那種矢量圖片,直接使用svg格式即可。一般來說要把圖片控制在300k以內(nèi),特別是banner頭圖,圖片的大小也要控制住。

24. 正確使用background和img

顯示一張圖片有兩種方式,可以通過設(shè)置CSS的background-image,或者是使用img標簽,究竟什么時候用哪種呢?

如果是頭圖等直接展示的圖片還是要img標簽,如果是做為背景圖就使用background,因為使用img可以寫個alt屬性增強SEO,而背景圖那種本身不需要SEO。雖然background有一個一個background-position: center center很好,但是頭圖那種還是使用img吧,自己去居中吧,不然做不了SEO。

25. 響應(yīng)式的規(guī)范

響應(yīng)式開發(fā)最不好不要雜合使用rem,文字字號要么全部使用rem,要么不要用,也不要使用transform: scale去縮小,因為被縮小的字號看起來會有點奇怪,別人都是14px,而你變成了13.231px,小了一點。響應(yīng)式的原則一般是保持中間或者兩邊間距不變,然后縮小主體內(nèi)容的寬度。

26. 適當使用:before/:after

:before和:after可以用來畫頁面的一些視覺上的輔助性元素,如三角形、短的分隔線、短豎線等,可以減少頁面上沒有用的標簽。但是頁面上正常的文本等元素還是不要用before/after畫了。

27. 少用absolute定位

首先absolute定位的元素渲染性能會比較高,因為它獨立出來了,計算量會少,用得好還是可以的。但是如果你頁面的主要布局是使用absolute的那肯定是不可取的,因為absolute定位的可擴展性很差,你把每個元素的位置都定死了就變不了了,可以多用float,雖然float的性能相對較差,但是不管是實用性還是兼容性都是挺好的。

28. 少用inline-block布局

有些人喜歡用inline-block,特別是剛開始學(xué)切圖的人,因為block會換行,而inline-block不會換行還具有盒模型,因此inline-block用得很順手,而float比較復(fù)雜,還要處理清除浮動之類的問題。如下布局:

HTML/CSS/JS編碼規(guī)范有哪些

應(yīng)該寫li,然后讓li float,如果你讓li display:inline-block也可以達到目的。但是inline-block用得多了可能會有一些奇怪的問題,你通常要在一個inline-block的元素里面套block的元素,inline-block是行內(nèi)元素,而block是塊級元素,這兩者終究有點差別。這種應(yīng)該用float/flex會更自然,如果你float用順手了你會發(fā)現(xiàn)比inline-block好多了,并且更加專業(yè)。如果你沒怎么用過flex ,那你可以嘗試換一下使用flex,如果你沒怎么用過float,可以嘗試用一下。只有你的切圖方式多樣化了,你切起圖來才能比較靈活。

29. 圖片的居中和寬高設(shè)定

一般來說,UI給的圖片展示寬高是固定的,但是實際的圖片長寬是不固定,大部分圖片是長是比寬大,小部分圖片是寬比長大。所以需要居中裁剪展示,如下圖所示:

HTML/CSS/JS編碼規(guī)范有哪些

中間黑色的框是展示區(qū)域,圖片的短邊和窗器的邊一樣大,另一邊按圖片的原始比例拉伸,然后居中顯示。這個得借助JS,因為圖片未加載好之前,不知道是長邊比較大還是寬比較大。如下代碼:

<div>     <img src="test.jpg" alt onload="resizeImg(this, '400px', '300px'"> </div>

借助一個resizeImg函數(shù),在onload函數(shù)里面做處理。然后居中用CSS:

.img-container{     position: relative;     width: 400px;     height: 300px; } .img-container img{     position: absolute;     left: -9999px;     right: -9999px;     top: -9999px;     bottom: -9999px;     margin: auto; }

上面代碼用了一個margin: auto做居中。

30. 移動端提高可點區(qū)域范圍

移動端的的一些圖標如X,可能會設(shè)計得比較小,所以點起來會不太好點,因此要提高可點區(qū)域范圍,可通過增加padding,如下代碼:

.icon-close{     position: abosulte;     right: 0;     top: 0;     padding: 20px; }

這樣區(qū)域就增加了一圈,點起來就容易多了。

31. 不要設(shè)置input的line-height

如果設(shè)置input的line-height,如下代碼,你可能要做垂直居中:

.request-demo input{     height: 40px;     line-height: 40px; }

設(shè)置了line-height為一個很高的值,這樣會導(dǎo)致Safari瀏覽器的輸入光標|變得巨大,所以如果你要居中的話,使用padding吧。

32. 移動端彈框要禁止body滑動

因為IOS Safari切換輸入框的時候會頁面會彈閃得很厲害,因為你在切的時候它會先把鍵盤收起來,然后再彈出來,這個時間很短,給人感覺頁面彈閃了一下,但如果把body禁止滑動了就不會有這個問題,這有兩個解決辦法,第一種是把body fixed住,第二種設(shè)置body overflow: hidden,相對來說第二種比較簡單一點。IOS10完全不會閃,IOS9以下還是會閃。

33. 對于漸變的處理

有時候UI里面會有一些漸變的效果,無法復(fù)制CSS出來,這個時候可以用一個在線的工具,生成漸變的CSS: www.cssmatic.com/gradient-ge… ,但是這個需要自己手動調(diào)一個和UI一模一樣的效果,或者可以直接給UI調(diào)一個它理想的效果,它會生成兼容性很強的CSS:

background: #fff; background: -moz-linear-gradient(left, #fff 0%, #d2d2d2 43%, #d1d1d1 58%, #fefefe 100%); background: -webkit-gradient(left top, right top, color-stop(0%, #fff), color-stop(43%, #d2d2d2), color-stop(58%, #d1d1d1), color-stop(100%, #fefefe)); background: -webkit-linear-gradient(left, #fff 0%, #d2d2d2 43%, #d1d1d1 58%, #fefefe 100%); background: -o-linear-gradient(left, #fff 0%, #d2d2d2 43%, #d1d1d1 58%, #fefefe 100%); background: -ms-linear-gradient(left, #fff 0%, #d2d2d2 43%, #d1d1d1 58%, #fefefe 100%); background: linear-gradient(to right, #fff 0%, #d2d2d2 43%, #d1d1d1 58%, #fefefe 100%); filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fff', endColorstr='#fefefe', GradientType=1 );

34. 行內(nèi)元素可以直接設(shè)置margin-left/margin-right

如下有些人為了把span撐開,設(shè)置span display: inline-block:

span.phone-numer{     display: inline-block;     margin-left: 10px; }

其實行內(nèi)元素可直接margin的左右,能夠把它撐開,不需要設(shè)置inline-block:

span.phone-numer{     margin-left: 10px; }

另外需要注意的是img/input/textarea/button默認就是inline-block,也不用再設(shè)置。

三、JS編碼規(guī)范

1. 變量命名

《代碼大全》這本書里面有一章是專門講變量命名的,這里結(jié)合這本書的建議做說明??偟貋碚f,變量名要準確完整地描述該變量所表述的事物,具體來說:

(1)變量名不應(yīng)以短巧為榮

如以下好的變量名和不好的變量名:

| 不好的變量名 | 好的變量名 |
| inp | input, priceInput |
| day1, day2, param1 | today, tomorrow |
| id | userId, orderId |
| obj | orderData, houseInfos |
| tId | removeMsgTimerId |
| handler | submitHandler, searchHandler |

左邊的變量名都不太清楚,代碼的擴展性不好,一旦代碼需要加功能的話,就容易出現(xiàn)obj1、obj2、obj3這種很抽象的命名方式。所以一開始就要把變量的名字起得真實有意義,不要搞一些很短很通用的名字。

當然變量名取得太長也不好,如maximumNumberOfTeamMembers.

(2)變量名不要使用計算機術(shù)語

變量名應(yīng)直指問題領(lǐng)域,來源于現(xiàn)實世界,而不是計算機世界,例如取了texareaData之類的名字,應(yīng)該取一個和業(yè)務(wù)相關(guān)的名字,如leaveMsg.

(3)變量名的對仗要明確

如up/down、begin/end、opened/closed、visible/invisible、scource/target,對仗明確可以讓人很清楚地知道兩個變量的意義和用途。

(4)警惕臨時變量

有些喜歡取temp和obj之類的變量,如果這種臨時變量在兩行代碼內(nèi)就用完了,接下來的代碼就不會再用了,還是可以接受的,如交換數(shù)組的兩個元素。但是有些人取了個temp,接下來十幾行代碼都用到了這個temp,這個就讓人很困惑了。所以應(yīng)該盡量少用temp類的變量,如下代碼:

var temp = 10; var leftPosition = currentPosition + temp,     topPosition = currentPosition - temp;

應(yīng)改成:

var adjustSpace = 10; var leftPosition = currentPosition + adjustSpace,      topPosition = currentPosition - adjustSpace;
(5)bool變量

《代碼大全》這本書建議布爾變量不用以is/do之類的開頭,如:

var isMobile = true,     isError = true,     doUpdate = false;

可改成:

var mobile = true,     error = true,     updated = false;

還有其它一些常用的名稱如done/found/successs/ok/available/complete等,結(jié)合具體的語境:

var ajaxDone = true,     fileFound = false,     resourceUpdated = true;

另外變量名不要使用否定的名詞,如notOk,notReady,因為否定的詞取反的時候就會比較奇怪,如if(!notOk). 要使用肯定的布爾變量名。如果是參數(shù)的話可結(jié)合ES6的默認形參值。

(6****)變量名使用正確的語法

不要使用中文拼音,如shijianchuo應(yīng)改成timestamp,如果是復(fù)數(shù)的話加s,或者加上List,如orderList、menuItems,而過去式的加上ed,如updated/found等,如果正在進行的加上ing,如calling.

2. 聲明變量時要賦值

如下聲明三個變量:

var registerForm,      question,      calculateResult;

以上絕對是合法JS語法,但是這三個變量的用途會讓人比較困惑,特別是中間第二個question,問題是什么。但是當你把上面的變量賦一個初始值的時候:

var registerForm = null,      question = "",      calculateResult = 0;

就讓人豁然開朗了,原來question是一個問題的字符串,而result是一個數(shù)字,form是一個對象。這也有利于JS解釋器提前做一些優(yōu)化處理,不用等到使用的時候才知道這些變量是什么類型的。

3. 函數(shù)的返回值類型要確定

如下代碼:

function calculatePrice(seatCount){     if (seatCount <= 0) {         return "";     } else {         return seatCount * 79;     } }

這個代碼可能返回整型,也有可能返回字符串,就會讓人比較困惑,同時從代碼性能來說也是不高的,雖然它是合法的JS語法,一個函數(shù)的返回類型要統(tǒng)一。你可能會說我用上面的函數(shù)做為輸入框顯示的值,如果是負數(shù)或者0,那么輸入框就不要顯示任何東西,所以才會返回空的字符串。即使是這樣的原因也不建議這樣寫,從長遠來看這樣寫是不利的,你應(yīng)該用其它的方法組織你的代碼。要養(yǎng)成強類型的代碼風格,這樣不容易出bug,擴展也容易。另外如果一個變量你把它當成數(shù)字使用,下面就不要再把它當成字符串使用了,因為這樣也容易讓人困惑。微軟的Typescript就是一種強類型的書寫語法,很多大型項目會使用typescript寫JS,有興趣的可以繼續(xù)了解怎么寫typescript.

4. 不要給變量賦值undefined

undefined表示一個變量未定義,你定義了一個變量又說它未定義本身就很奇怪。這可能會造成的問題是使用上的歧義,因為我們經(jīng)常使用undefined來判斷變量有沒有定義:

if (typeof window.HTMLVideoElement === "undefined")復(fù)制代碼

如果要賦值應(yīng)該要賦空值,如對象賦值為null,數(shù)字賦值為0,字符串賦值為空字符,那你可能會說0也是一個正常的數(shù)字,如果賦值為0會導(dǎo)致我誤認為它是一個正常的數(shù)據(jù),那怎么辦呢?如果你的數(shù)字都是非負數(shù),那么可以把初始值置為-1,實在不行就置成NaN.

函數(shù)的返回值也不要顯式地return undefined.

5. 排版規(guī)范

一個比較流行的空格和縮進排版如下代碼所示:

//逗號后面帶個空格,) {中間帶個空格 function getSeatDiscount(seatCount, currentPrice) {     //雙目運算符左右兩邊都帶個空格     var originPrice = editOrder.getSeatsPrice(seatCount);     return Math.round((originPrice - currentPrice) / originPrice * 100); }

一行太長要換行,如V8的源碼里面一行最長是70個字符,超過就換行:

function ArrayUnshift(arg1) {  // length == 1 //if判斷里面進行了換行,并且if (中間帶個空格   if (len > 0 && UseSparseVariant(array, len, IS_ARRAY(array), len) &&       !%object_is_sealed(array)) {     SparseMove(array, 0, 0, len, num_arguments);   } else {     SimpleMove(array, 0, 0, len, num_arguments);   } }

一行代碼太長了就換行是一種好的習慣,太長讓人看起來比較費勁?;旧弦恍胁灰^100個字符,超過就要換行,不管是注釋還是代碼。

6. 使用===代替==

==會帶上類型轉(zhuǎn)換,這和上面一樣的,我們要用強類型的風格寫代碼,所以不要使用==,如果有類型轉(zhuǎn)換自己做類型轉(zhuǎn)換,不要讓別人去猜這里面有類型轉(zhuǎn)換,使用==會有一些比較奇怪的結(jié)果:

null == undefined          //true '' == '0'                  //false 0  == ''                   //true 0  == '0'                  //true ' \t\r\n ' == 0            //true new String("abc") == "abc" //true new Boolean(true) == true  //true true == 1                  //true

7. 減少魔數(shù)

對一些比較重要的常量起一個名字,例如下面的代碼:

const ONE_DATE = 3600 * 24 * 1000; var tomorrow = today + ONE_DATE;

再如下面不好的寫法:

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

上面四個常量會讓人看起來比較困惑,如果可以的話給它們起個名字,如果覺得麻煩那就加上注釋。

8. 不要讓代碼暴露在全局作用域下運行

一個原因是在全局作用域下,變量的查找時間會更長,第二個原因是污染全局作用域,有時候會造成一些意想不到的結(jié)果,如下:

var name = "hi boy"; console.log(window.name);

定義了一個變量,但是剛好不巧window.name是本來有這個屬性,這個屬性通常用來跨域傳遞數(shù)據(jù)。如果你設(shè)置了name這個變量,就把全局的window.name給覆蓋了。

9. let/var/const的使用

ES6新增了let/const定義變量,使用let有一些好處,如:

(1)避免變量重復(fù)定義
let me = "go"; // Uncaught SyntaxError: Identifier 'me' has already been declared let me = "go";

使用babel loader打包的時候它會做靜態(tài)檢查:

Module build failed: Duplicate declaration "me"

(2)for循環(huán)的變量作用域是獨立的
for(let i = 0; i <= 4; i++) {     tasks.push(function(){         console.log("i is " + i);     }); }

使用let使得i在for循環(huán)里面每次運行的作用域都是獨立的。并且for里定義的變量在for循環(huán)外是不可見的。

babel在轉(zhuǎn)換的時候,會在for循環(huán)里面套一個function,然后把i當作函數(shù)的參數(shù):

var _loop = function _loop(_i) {     tasks.push(function () {         console.log("i is " + _i);     });  }; for (var _i = 0; _i <= 4; _i++) {     _loop(_i); }

由于let可以避免變量重復(fù)定義,就沖著這一點,就使得它很有意義。所以推薦多用****let****定義變量。所以本規(guī)范下面的變量將使用let代替var.

而const適合于給常量起個名字,如上面提到的:

const ONE_DAY = 3600 * 24 * 1000; const adjustSpace = 10;

或者是定義其它一些不需要修改的變量,防止不小心被其它代碼修改了。

10. 簡潔代碼

(1)使用三目運算代替簡單的if-else

可以寫一行就不要寫三行,如下:

let seatDiscount = 100; if(seat < 5) {     seatDiscount = 90; } else if(seat < 10) {     seatDiscount = 80; } else {     seatDiscount = 70; }

可以改成三目運算符:

let seatDiscount = seat < 5 ? 90 :                             seat < 10 ? 80 : 70;

代碼從8行減少到了2行。

(2)使用箭頭函數(shù)取代簡單的函數(shù)

例如以下代碼:

setTimeout(function(){     window.location.reload(true); }, 2000);

可改成:

setTimeout(() => window.location.reload(true), 2000);復(fù)制代碼

代碼從3行變成了1行。

11. 注意避免執(zhí)行過長時間的JS代碼

對于一般的頁面的數(shù)據(jù)量來說,加減乘除等計算不足以造成性能瓶頸。容易造成瓶頸的是DOM操作,特別是大批量的DOM操作,只要一次有幾百上千的級別就容易造成頁面卡頓。特別是不要在一個for循環(huán)里不斷地修改DOM,如下代碼:

for(var i = 0; i < 1000; i++) {     ul.appendChild(li); }

這種可以先把li拼好了,再一次性append到ul里面,如下代碼:

var fragment = document.createDocumentFragment(); for(var i = 0; i < 1000; i++) {     fragment.appendChild(li); } ul.appendChild(fragment);

如果你用jq的話應(yīng)該先把模板渲染好,然后再一次性append到dom里面,而不是不斷地append到dom里面?,F(xiàn)在的瀏覽器一般也比較智能,它會做一些優(yōu)化,但是我們不能老是指望瀏覽器會優(yōu)化。

但是還是要注意數(shù)據(jù)量特別大的情況,你可能要使用setTimeout的方式分段處理數(shù)據(jù),甚至使用多線程。使用setTimeout可以這樣:

function sliceWorks(data, finishedCallback) {     if(!data.length) {         finishedCallback();     } else {         const PIECES = 100;         process(data.splice(0, PIECES));         setTimeout(() => sliceWorks(data, finishedCallback), 100);     } }

我們使用一個遞歸,把數(shù)據(jù)分段處理,每段100個,當數(shù)據(jù)處理完再調(diào)完成回調(diào)函數(shù)。

12. 多寫注釋

這個和CSS規(guī)范類似:

(1)文件頂部的注釋,包括描述、作者、更新
/*  * @file listing-detail.js  * @description 房源詳情頁的JS主文件,處理輪播、房貸計算器、約看房等邏輯  * @author yincheng.li  * @update (yincheng.li 2017/8/19)  */
(2)函數(shù)的注釋
/*  * 和搜索界面展示有關(guān)的處理邏輯  * @namespace  */ var searchWinHandler = {     /*      * 初始化驅(qū)動函數(shù)      *       * @param {bool} realTimeSearch 是否需要進行實時搜索      * @param {HTMLFormElement} form 搜索表單DOM元素      *      */     init(realTimeSearch, HTMLFormElement){     }     /*      * 搜索條件展示點擊X按鈕的處理函數(shù)      *      * @param {object} jquery的點擊事件event      * @trigger 會觸發(fā)search按鈕的點擊事件,以觸發(fā)搜索      * @returns 無返回      *      * TODO 這里臨時使用了一個全局變量的flag,這種實現(xiàn)方式不太好      * 雖然比較方便      */                   closeFilterSpan(event){     } };

上面的@auhor @return都是注釋標簽,其它常用的注釋標簽還有:

/* @class 表示一個類 @constructor 構(gòu)造函數(shù) @deprecated 被棄用 @global 全局的變量 @namespace 具有命名空間作用的object,如$.fn.remove,$.fn.append,$和fn就是一個namespace,而fn是$的子命名空間 @this 這里的this指向哪里 @throws 在這個函數(shù)里面可能會拋出什么異常 @version 當前版本 */
(3)變量定義和代碼的注釋

對一些比較重要的變量加注釋,標明它是什么用途,以及對一些核心代碼邏輯加上注釋,或者比較復(fù)雜的業(yè)務(wù)邏輯,寫了5個case,每個case分別代表什么;為了改某個bug而加入的代碼,說明下為了解決什么問題;還有某些易混的判斷,為什么if判斷條件寫了四個,為什么代碼到這個if判斷不通過就直接return了;一些常量的注釋,為什么會突然冒出來100這個數(shù)字;改動了別人的代碼,為什么要改動;等等。如:

 var requestData = {         listingId: listingData.listingId,         page: 1,         //把200改成5,點擊More的時候是重新刷新頁面的,也沒有其他地方用到,         //沒必要請求那么多,嚴重影響性能         pageSize: 5//200     };

總之多寫注釋還是好的,只要不是廢話:

//定義了一個number的變量 let number = 5;

或者是和邏輯不符合的錯誤注釋。

還有一種排版的注釋,右括號的對應(yīng)關(guān)系:

            } //function ajax         } //switch(b)     } //if(a) }  //searchHandler

主要是為了方便在后面加代碼,例如我要在switch(b)后面加代碼,當我看到這個注釋我就很清楚地知道需要在哪里按回車。不過一般不推薦嵌套很深的代碼,或者寫得很長,一個函數(shù)幾百行。

13. 代碼不要嵌套太深

有些人的代碼經(jīng)常會套個七八層,以jq代碼為例,如下:

var orderHandler = {     bindEvent: function(){         $(".update-order").on("click", function(){             if(orderStatus === "active"){                 ajax({                     url: "/update-order",                     success: function(data){                         for(let i = 0; i < data.orders.length; i++){                             dom.append();                         }                     }                 });             } else {                 ajax({                     url: "/create-order",                     success: function(data){                     }                 });             }         });     } };

上面的代碼最深的一層縮進了八層,你可能會覺得這樣邏輯挺清晰的啊,但是這種寫法同時也有點面條式。以上代碼如果讓我寫,我會這么組織:

var orderHandler = {     sendUpdateOrderReq: function(requestUrl, successCallback){         ajax({             url: requestUrl,             success: successCallback;         });     },     updateOrder: function(event){         let requestUrl = orderStatus === "active" ? "/update-order"                                  : "create-order";         //更新訂單回調(diào)函數(shù)         let activeUpdateCallback = function(data){              for(var i = 0; i < data.orders.length; i++){                 console.log(data.orders[i].id);             }                };         //創(chuàng)建訂單回調(diào)函數(shù)         let inactiveUpdateCallback = function(data){         };               let successCallback = {             active: activeUpdateCallback,             inactive: inactiveUpdateCallback         };         //發(fā)請求處理訂單         searchHandler.sendUpdateOrderReq(requestUrl,                                                      successCallback[orderStatus]);     },           bindEvent: function(){         $(".update-order").on("click", searchHandler.updateOrder);     }                                                };

首先把綁定的匿名函數(shù)改成有名的函數(shù),這樣有個好處,當你想要off掉的時候隨時可off掉,然后可以減少一層縮進,接著把根據(jù)orderStatus不同的回調(diào)先用變量判斷好,而不是同時積壓到后面再一起處理。再把發(fā)送請求的函數(shù)再單獨抽出來做為一個函數(shù),這樣可以減少兩層縮進。上面最深的縮進為4層,減少了一半。并且你會發(fā)現(xiàn)這樣寫代碼邏輯會更加清晰,我在bindEvent里面掃一眼就可以知道哪些DOM綁了哪些事件,然后我對如對哪個DOM的事件感興趣再跳到相應(yīng)的回調(diào)函數(shù)去看,而不用拉了一兩頁才在bindEvent里面找到目標DOM。并且把updateOrder單獨做為一個獨立的函數(shù),其它地方如果需要也可以使用,例如可能還有一個組合功能的操作可能會用到。另外把ajax再做一層抽象主要是這個東西實在是太常用,讓人一眼就知道要干嘛,把它分離到另外一個地方可以讓具體的業(yè)務(wù)代碼更加簡單,例如上面發(fā)請求,我把回調(diào)函數(shù)準備好之后,只要執(zhí)行一行代碼就好了。

你縮進太多層,一行就被空格占掉了三、四十個字符,感觀上就不是很好,還會出現(xiàn)上面提到的,最后面要寫好多個右括號收尾的情況,并且一個函數(shù)動不動就兩、三百行。

14. jQuery編碼規(guī)范

如果你使用了jQuery。

(1)使用closest代替parent

盡量不要使用parent去獲取DOM元素,如下代碼:

var $activeRows = $this.parent().parent().children(".active");復(fù)制代碼

這樣的代碼擴展性不好,一旦DOM結(jié)構(gòu)發(fā)生改變,這里的邏輯分分鐘會掛,如某天你可能會套了個div用來清除浮動,但是沒想到導(dǎo)致有個按鈕點不了了就坑爹了。

應(yīng)該用closest,如:

var $activeRows = $this.closest(".order-list").find(".active");復(fù)制代碼

直接定位和目標元素的最近共同祖先節(jié)點,然后find一下目標元素就好了,這樣就不會出現(xiàn)上面的問題,只要容器的類沒有變。如果你需要處理非自己的相鄰元素,可以這么搞:

$this.closest("li").siblings("li.active").removeClass("active"); $this.addClass("active");

有時候你可以先把所有的li都置成某個類,然后再把自己改回去也是可取的,因為瀏覽器會進行優(yōu)化,不會一見到DOM操作就立刻執(zhí)行,會先排成一個隊列,然后再一起處理,所以實際的DOM操作對自己先加一個類然后再去掉的正負相抵操作很可能是不會執(zhí)行的。

(2)選擇器的性能問題

如下代碼:

$(".page ul").addClass("shown"); $(".page .page-number").text(number); $(".page .page-next").removeClass("active"); 復(fù)制代碼

上面的代碼做了三個全局查找,其實可以優(yōu)化一下:

var $page = $(".page"); $page.find("ul").addClass("shown"); $page.find(".page-number").text(number); $page.find(".page-next").removeClass("active");

先做一個全局查找,后續(xù)的查DOM都縮小到HTML/CSS/JS編碼規(guī)范有哪些page的節(jié)點只有幾十個,在幾個里面找就比在document幾百幾千個節(jié)點里面查找要快多了。jQuery的查DOM也是用的querySelectorAll,這個函數(shù)除了用在document之外,可用在其它DOM結(jié)點。

(3)on事件之前需要的時候才off

有些人喜歡在綁事件之前先off掉,這樣感覺可以確保萬無一失,但是如果你綁的事件是匿名的,你很可能會把其它JS文件綁的一起off掉了,并且這樣不容易暴露問題,有時候你的問題可能是重復(fù)綁定事件,如點一次按鈕就綁一次就導(dǎo)致了綁多次,所以根本原因在這里。你應(yīng)該要確保事件只被綁一次,而不是確保每次寫之前都先off掉。如果你的事件容易出現(xiàn)綁多次的情況說明你的代碼組織有問題,這個在開發(fā)的時候應(yīng)該是能夠暴露出來的。

(4)對DOM節(jié)點較少的不要使用委托

例如說一個表單只有幾個input元素,然后你給input加了個委托到form上面,甚至有時候是body上面,由于事件冒泡導(dǎo)致在form上或者在頁面上的所有操作都會冒泡到form/body上,即使操作的不是目標元素,這樣jQuery就會收到在body上的事件,然后再判斷處理所有的操作的目標元素是不是你指定的那個,如果是再觸發(fā)你綁的回調(diào)函數(shù)。特別是像mousemove觸發(fā)得頻繁的事件都需要執(zhí)行。所以如果元素比較少或者不需要動態(tài)增刪的那種就不要使用冒泡了,直接綁在對應(yīng)的多個元素就好了。

(5)有時候使用原生更簡單

例如獲取表單的input的和它的value:

let email = form.email.value.trim();

如果form里面有一個input[name=email]的輸入框,就可以這么用。

再如,改變一個button的狀態(tài),下面兩個其實差不多,但是如果獲取不到dom元素的話第一個會掛:

$("#update-order")[0].disabled = true; $("#update-order").prop("disabled", true);

設(shè)置一個元素的display為block:

div.style.display = "block";復(fù)制代碼

但是絕大多數(shù)的情況下還是要使用jq的API以確保兼容性,如下獲取scrollTop:

//在Firefox永遠返回0 let _scrollTop = document.body.scrollTop(); //正確方法 let scrollTop = $(window).scrollTop();

因為在firefox里面需要使用:

document.documentElement.scrollTop

而這個在Chrome永遠返回0。再如window.innerWidth在某些低版本的安卓手機會有問題。所以當你不確定兼容性的時候,就不要使用原生API,不然你得經(jīng)過小心驗證后再使用。你可以不用,但不是說不要去了解原生API,多去了解原生DOM操作還是挺有幫助的。

15. 對于常用的屬性進行緩存

如下代碼,頻繁地使用了window.location這個屬性:

let webLink = window.location.protocol + window.location.hostname; if(openType === "needtoTouch"){     webLink += "/admin/lead/list/page" +               window.location.search.replace(/openType=needToTouch(&?)/, "") +               window.location.hash; }

可以先把它緩存一下,加快變量作用域查找:

let location = window.location; let webLink = location.protocol + location.hostname; if(openType === "needtoTouch"){     webLink += "/admin/lead/list/page" +                 location.search.replace(/openType=needToTouch(&?)/, "") +                        location.hash; }

當把location變成一個局部變量之后,它的查找時間將明顯快于全局變量。你可能會說就算再快這點時間對于用戶來說還是沒有區(qū)別的吧,但是這是做為一名程序員的追求,以及可以讓代碼更簡潔。

16. 盡量不要在JS里面寫CSS

如下代碼,如果是非選中狀態(tài)就把顏色置灰:

$menuItem.css("color", "#ccc");復(fù)制代碼

反之顏色恢復(fù)正常:

$menuItem.css("color", "#000");

這樣的代碼有問題,如果以后顏色改了,那么你需要改兩個地方,一個是CSS里設(shè)置,另一個是JS里面設(shè)置,而JS寫的樣式特別容易被忽略,查起來也不好定位。好的做法應(yīng)該是通過添加刪除類的方法:

//變成選中態(tài) $menuItem.addClass("selected"); //變成非選中態(tài) $menuItem.removeClass("selected");

然后再通過CSS給selected的類添加樣式。如果是button之類的控件可以結(jié)合:disabled、:checked、:valid等偽類,連類都不用添加

但是有一種是一定要用JS控制的,就是需要先計算然后動態(tài)地改變position或者transform的值,如果用CSS3的transition實現(xiàn)不了.

17. 在必要的地方添加非空判斷

添加非空判斷可以提高代碼的穩(wěn)健性,如下代碼:

//彈框時顯示other monthly charge showOtherMonthlyCharge: function(otherCharges, $dialog){     if(!otherCharges || !otherCharges.length){         return;     }    }

如果傳的為空就不用處理,有時候你可能要拋個異常,告訴調(diào)用者。對一些比較重要的地方可能還要添加類型檢驗。后端傳的數(shù)據(jù)要確保會有那個屬性,如果不確定也要添加非空判斷。如果調(diào)了第三方的API,添加出錯處理也很重要,因為你不能確保第三方API一定能正常工作,在一些你覺得可能會掛的地方做處理,如請求可能會超時,或者返回了undefined的異常結(jié)果,這種多使用一般能夠發(fā)現(xiàn)。

18. 不要用for in循環(huán)數(shù)組

如下代碼:

let a = [9, 3, 5]; for(let i in a){   console.log(a[i]) }

正常情況下將會輸出數(shù)組的元素,但是很不幸的是,如果有人給數(shù)組原型添加了一個函數(shù):

Array.prototype.add = function(){};

循環(huán)里的i將會有4個值:0, 1, 2, "add",這樣就導(dǎo)致你的遍歷出現(xiàn)問題,所以數(shù)組遍歷應(yīng)該使用length屬性或者數(shù)組的forEach/map方法。

19. 分號規(guī)范

JS里面的表達式是可以不用分號結(jié)尾,例如Zepto的源碼幾乎沒看到一個分號,但是我們還是提倡要每個句子后面都要加上分號,這樣不容易出錯。

20. 使用location跳轉(zhuǎn)需要先轉(zhuǎn)義

對于那些根據(jù)用戶輸入內(nèi)容做跳轉(zhuǎn),需要先把用戶內(nèi)容做轉(zhuǎn)義,如下有問題的代碼:

let searchContent = form.search.value.trim(); window.location.href = `/search?key=${searchContent}`;

如果用戶輸入了一個#號如門牌號,將會導(dǎo)致#后面的內(nèi)容當作錨點了,或者用戶可能會輸入一個空格。所以如果不確定內(nèi)容的東西需要先encode一下,如下代碼:

let searchContent = encodeURIComponent(form.search.value.trim()); window.location.href = `/search?key=${searchContent}`;

這樣跳轉(zhuǎn)就沒有問題了。

21. 點擊跳轉(zhuǎn)盡量不要使用onclick跳轉(zhuǎn)

點擊一個容器的時候做跳轉(zhuǎn),有些人喜歡這么寫:

<div onclick="window.locatioin.href='/listing/detail?id={{listingId}}'">     <img>     <div></div> </div>

其實這樣寫不好,不利于SEO,如果是一個跳轉(zhuǎn)應(yīng)該用a標簽,如下:

<a href="window.locatioin.href='/listing/detail?id={{listingId}}'">     <img>     <div></div> </a>

同時把a標簽變成塊級。就算你不用做SEO,也應(yīng)當盡量使用這種方式,因為用這種方式比較自然,還可以控制是否要新開頁,如果在移動端也不用考慮click事件是否有延遲的問題。

22. 不要直接使用localStorage

由于Safari的隱身模式下本地存儲會被禁用,如果你嘗試往localStorage寫數(shù)據(jù)的話,會報超出使用限制的錯誤:

QuotaExceededError (DOM Exception 22): The quota has been exceeded.

而Chrome的隱身窗口不會禁用。而使用Safari的用戶可能會開隱身窗口,特別是手機上的。這樣就導(dǎo)致代碼拋異常了,所以為了兼容Safari,不能直接使用localStorage,要做個兼容:

Data.hasLocalStorage = true; try{     window.localStorage.trySetData = 1; }catch(e){     Data.hasLocalStorage = false; } setLocalData: function(key, value){      if(Data.hasLocalStorage){         window.localStorage[key] = value;     }     else{            util.setCookie("_LOCAL_DATA_" + key, value, 1000);     } }, getLocalData: function(key){     if(Data.hasLocalStorage){         return window.localStorage[key];     }     else{         return util.getCookie("_LOCAL_DATA_" + key);     } }

上面代碼做了個兼容,如果不支持localStorage就使用cookie。要注意cookie一個域名最多只能有4kB,50個key,而本地存儲限制為5Mb.

23. 使用簡便的轉(zhuǎn)換

(1)把字符串轉(zhuǎn)整型可以使用+號
let maxPrice = +form.maxPrice.value;復(fù)制代碼

+號相當于Number:

let maxPrice = Number(form.maxPrice.value);復(fù)制代碼

parseInt和Number有一個很大的區(qū)別是parseInt(“10px”)結(jié)果為10,而Number(“10px”)是NaN,parseInt會更加自然,其它編程語言也有類似的轉(zhuǎn)換。但是Number還是能適用很多的場景。

(2)把小數(shù)去掉尾數(shù)轉(zhuǎn)成整型,可以使用 >> 0

如果計算某個數(shù)字在第幾排:

let _row = Math.floor(index / columns); let row = parseInt(index / columns);

都可改成:

let row = index / columns >> 0;

這個用位運算的效率會明顯高于上面兩個。

(3)轉(zhuǎn)成boolean值用!!

如下代碼:

let mobile = !!ua.match(/iPhone|iPad|Android|iPod|Windows Phone/)

24. 注意返回false的變量

有幾個值在if判斷里面都返回false:0、false、””、undefined、null、NaN都是false,所以判斷一個數(shù)組有沒有元素可以這么寫:

if (array.length) {}

而不用寫成:

if (array.length !== 0) {}

判斷一個字符串是不是空可以寫成:

if (str) {}

但是判斷一個變量有沒有定義還是要寫成:

if (typeof foo !== “undefined”) {}

因為如果直接if變量的話,上面的幾個可能取值都將認為是沒定義。

25. 使用Object.assgin簡化數(shù)據(jù)賦值

如下代碼,在發(fā)請求之前,經(jīng)常需要獲取表單的值,然后去修改和添加老數(shù)據(jù)提交:

var orderData = {     id: 123,     price: 500 } orderData.price = 600; orderData.discount = 15; orderData.manageFee = 100;

其實有一種更優(yōu)雅的方式那就是使用Object.assign:

var setOrderData = {     price: 600,     discount: 15,     manageFee: 100 } Object.assgin(orderData, setOrderData);

使用這個的好處是可以弄一個setOrderData的Object,寫成大括號的形式,而不用一個個去賦值,寫起來和看起來都比較累。最后再assign一下賦值給原先的Object就可以了。

26. 調(diào)試完去掉無關(guān)的console

調(diào)試完就把console.log之類的打印信息去掉,別想著等一下做完了再刪,等一下就忘了。另外,不要使用alert調(diào)試,console/debugger上線了都沒事,一般用戶也不會開一個控制臺,但是alert上線了就完蛋了,特別是有些人喜歡用alert(“fuck”)之類的看下代碼有沒有運行到這里,這種調(diào)試技巧還是比較初級,要是真上線了可能得卷鋪蓋走人了。這也可以通過代碼檢查工具做靜態(tài)檢查。

27. 注意this的指向

如下代碼:

let searchHandler = {     search() {         console.log(this);         this.ajax();     },     ajax() {     } }; $searchBtn.on("click", searchHandler.search);

當觸發(fā)searchBtn的點擊事件時,search函數(shù)里的this已經(jīng)指向 searchBtn了,因為它是click的回調(diào)函數(shù):

searchHandler.search.call(btn, event);復(fù)制代碼

所以函數(shù)運行環(huán)境就變成了btn了,因此這種單例的Object最好不要使用this,應(yīng)直接使用當前命名空間的變量名:

let searchHandler = {     search() {         console.log(this);         searchHandler.ajax();     },     ajax() {     } }; $searchBtn.on("click", searchHandler.search);

這樣就沒問題了。

28. 使用正則表達式做字符串處理

正則表達式可以很方便地處理字符串,通常只要一行代碼就搞定了。例如去掉全局的某一個字符,如去掉電話號碼的-連接符:

phoneNumer = phoneNumber.replace(/\-/g, “”);

或者反過來,把電話號碼改成3-3-4的形式:

phoneNumber = phoneNumber.replace(/^(\d{3})(\d{3})(\d{4})$/, “$1-$2-$3”);復(fù)制代碼

熟練掌握正則表達式是每個前端的基本技能。

29. 保持復(fù)用模塊的觀念

當你一個函數(shù)要寫得很長的時候,例如兩、三百行,這個時候你考慮把這個大函數(shù)給拆了,拆成幾個小函數(shù),然后讓主函數(shù)的邏輯變得清晰簡潔,而每個小函數(shù)的功能單一獨立,使用者只需要管輸入輸出,而不需要關(guān)心內(nèi)部是怎么運行的。如下在地圖里面處理用戶點擊的處理函數(shù):

handleMouseClick(latLng, ajax = true) {     var path = this.path;     // 這里調(diào)了一個closeToFirstPoint的函數(shù)判斷點擊位置是否接近第一個點     if(path.length >= 2 && ajax && this.closeToFirstPoint(latLng)){         // 如果是的話調(diào)closePath關(guān)閉路徑         this.closePath(ajax);         return;     }     path.push({lat: latLng.lat(), lng: latLng.lng()});     // 調(diào)畫點的函數(shù)     this.drawPoint(latLng);     // 調(diào)畫線的函數(shù)     this.drawSolidLine();     // 調(diào)畫多邊形背景的函數(shù)     this.drawPolygonMask();     this.lastMoveLine && this.lastMoveLine.setMap(null);     this.$drawTip.hide(); }

上面拆成了很多個小函數(shù),如畫點的drawPoint函數(shù),使用這個函數(shù)只需要關(guān)心給它一個當前點的經(jīng)緯度就可以了,它就幫你畫一個點。

在函數(shù)之上又可以繼續(xù)抽象,如把這個畫圖功能的模塊寫成一個DrawTool的類,這個類負責整個畫圖的功能,使用者只需要實例化一個對象,然后調(diào)一下init,傳一些參數(shù)就好了。

先抽成不同的函數(shù),每個函數(shù)負責一小塊,相似的函數(shù)聚集在一起形成一個模塊,幾個模塊的相互調(diào)用又形成一個插件。

30. 注意label事件會觸發(fā)兩次

如果label里面有input,監(jiān)聽label的事件會觸發(fā)兩次,如下代碼:

<form id="choose-fruit">     <label>         <input type="radio" name="fruit" value="apple">         <span>apple</span>     </label>     <label>         <input type="radio" name="fruit" value="pear">         <span>pear</span>     </label>  <form> <script> {     let $form = $("#choose-fruit");     $form.find("label").on("click", function(event){         console.log(event.target);     }); } </script>

當點到span的時候,click事件會觸發(fā)兩次,如果label里面沒有input的話,就只會觸發(fā)一次。這是為什么呢?因為在label容器內(nèi),點到span文字的時候會下發(fā)一次click事件給input,input事件又會冒泡到label,因此label會觸發(fā)兩次。因此如果你直接監(jiān)聽label事件要注意注意觸發(fā)兩次的情況。

感謝各位的閱讀,以上就是“HTML/CSS/JS編碼規(guī)范有哪些”的內(nèi)容了,經(jīng)過本文的學(xué)習后,相信大家對HTML/CSS/JS編碼規(guī)范有哪些這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI