javascript
JSLint检测Javascript语法规范
前端javascript代碼編寫(xiě)中,有一個(gè)不錯(cuò)的工具叫JSLint,可以檢查代碼規(guī)范化,壓縮JS,CSS等,但是他的語(yǔ)法規(guī)范檢查個(gè)人覺(jué)得太“苛刻”了,會(huì)提示各種各樣的問(wèn)題修改建議,有時(shí)候提示的信息我們看的莫名其妙,這里,先轉(zhuǎn)載一下攜程UED的一個(gè)技術(shù)文章(原文鏈接ued.ctrip.com/blog/?p=273…),看看JSLint的錯(cuò)誤提示都是什么意思:
一直以為檢查JS語(yǔ)法錯(cuò)誤非jslint不可,不過(guò)使用起來(lái)總是覺(jué)得太重量級(jí)了一點(diǎn)點(diǎn)。
后來(lái)無(wú)意中發(fā)現(xiàn)了一個(gè)叫jshint的東東。
首先介紹一下,jshint和jslint的差別在哪里。
摘自官網(wǎng)的一段內(nèi)容
JSHint is a fork of Douglas Crockford’s JSLint that is designed to be more flexible than the original. Our goal is to make a tool that helps you to find errors in your JavaScript code and to enforce your favorite coding style.
We realize that people use different styles and conventions, and we want our tool to adjust to them. JSHint will never enforce one particular convention.
大概的意思就是,JSHint比起JSLint而言,會(huì)更加輕量級(jí)一些。它能夠找出代碼中的語(yǔ)法錯(cuò)誤,并且建議更好的一種編碼風(fēng)格。當(dāng)然,它也不是強(qiáng)制性的非要你根據(jù)它規(guī)定的編碼風(fēng)格來(lái)做。因?yàn)樗峁┝艘幌盗械呐渲?#xff0c;你可以隨時(shí)關(guān)掉某些你覺(jué)得不必要的錯(cuò)誤提示。這個(gè)我后面會(huì)介紹到。
那么如何使用jsHint檢查錯(cuò)誤呢?用起來(lái)非常簡(jiǎn)單哦~
var result = JSHINT(source, options);復(fù)制代碼先解釋一下參數(shù)和返回值:
第一個(gè)參數(shù)source : 必選項(xiàng)。表示需要檢查的代碼,js或者json,可以傳一個(gè)字符串或者一個(gè)數(shù)組。如果傳字符串,需要用’\r’或者’\n’來(lái)分隔一行一行的代碼;如果傳數(shù)組,則每一個(gè)數(shù)組元素表示一行的代碼。
第二個(gè)參數(shù)option : 可選項(xiàng)。表示代碼檢查的配置項(xiàng)。大部分的都是bool類型的,也有一部分,例如predef,可以是一個(gè)array,含有全局變量或者全局方法;或者是一個(gè)object,key是全局變量或者方法,value是一個(gè)bool值,表示是否被定義過(guò)。
返回值:如果代碼沒(méi)有問(wèn)題,JSHINT會(huì)返回一個(gè)true;否則返回false。
詳細(xì)的說(shuō)明
1. 關(guān)于第一個(gè)參數(shù)
由于只能傳入一個(gè)字符串或者數(shù)組。但是如果需要根據(jù)一個(gè)js的鏈接來(lái)檢查此文件呢?
我嘗試使用ajax方法獲取js的內(nèi)容(雖然是可以跨域的),但是如果頁(yè)面是gb2312的取回來(lái)就會(huì)亂碼,那么用jshint頁(yè)面檢查的話,讀到中文部分就會(huì)報(bào)錯(cuò)”unsafe charater”。嘗試使用二進(jìn)制的responseBody進(jìn)行轉(zhuǎn)碼,但是沒(méi)有找到是適合的js轉(zhuǎn)碼方法。
后來(lái),我寫(xiě)了一個(gè)php的中轉(zhuǎn)頁(yè)面,用file_get_contents的方法讀取文件,使用mb_detect_encoding檢測(cè)頁(yè)面編碼
<?phpmb_detect_order("GB2312,GBK,UTF-8,ASCII");$url = $_REQUEST["url"];$str = file_get_contents($url); if(!isset($url) || !$str){echo "";}else{$getcontent = iconv(mb_detect_encoding($str), "utf-8", $str);echo $getcontent;} ?>復(fù)制代碼
當(dāng)然,也有同學(xué)提到可以將js文件獲取下來(lái),存到本地。讀取的時(shí)候判斷編碼來(lái)讀取,也是一種方法。不過(guò)我沒(méi)有嘗試過(guò)。
2. 關(guān)于第二個(gè)參數(shù)
我覺(jué)得這個(gè)才是JSHINT的精髓,因?yàn)槊恳粋€(gè)配置項(xiàng)都可以定義你要check的深度和廣度。
下面就把這一系列的配置項(xiàng)列出來(lái)(偶自己翻譯的)。以下的這些是官網(wǎng)上面的option。
| prop | description |
| asi | 是否使用自動(dòng)插入分號(hào) |
| bitwise | 如果是true,則禁止使用位運(yùn)算符 |
| boss | 如果是true,則允許在if/for/while的條件中使用=做賦值操作 |
| curly | 如果是true,則要求在if/while的模塊時(shí)使用TAB結(jié)構(gòu) |
| debug | 如果是true,則允許使用debugger的語(yǔ)句 |
| eqeqeq | 如果是true,則要求在所有的比較時(shí)使用===和!== |
| eqnull | 如果是true,則允許使用== null |
| evil | 如果是true,則允許使用eval方法 |
| forin | 如果是true,則不允許for in在沒(méi)有hasOwnProperty時(shí)使用 |
| immed | 如果是true,則要求“立即調(diào)用”(immediate invocations)必須使用括號(hào)包起來(lái) |
| laxbreak | 如果是true,則不檢查換行,那么自動(dòng)插入分號(hào)的選項(xiàng)必須開(kāi)啟。 |
| maxerr | 默認(rèn)是50。 表示多少錯(cuò)誤時(shí),jshint停止分析代碼 |
| newcap | 如果是true,則構(gòu)造函數(shù)必須大寫(xiě) |
| noarg | 如果是true,則不允許使用arguments.caller和arguments.callee |
| noempty | 如果是true,則不允許使用空函數(shù) |
| nonew | 如果是true,則不允許不做賦值的構(gòu)造函數(shù),例如new UIWindow(); |
| nomen | 如果是true,則不允許在名稱首部和尾部加下劃線 |
| onevar | 如果是true,則在一個(gè)函數(shù)中只能出現(xiàn)一次var |
| passfail | 如果是true,則在遇到第一個(gè)錯(cuò)誤的時(shí)候就終止 |
| plusplus | 如果是true,則不允許使用++或者- -的操作 |
| regexp | 如果是true,則正則中不允許使用.或者[^…] |
| undef | 如果是ture,則所有的局部變量必須先聲明之后才能使用 |
| sub | 如果是true,則允許使用各種寫(xiě)法獲取屬性(一般使用.來(lái)獲取一個(gè)對(duì)象的屬性值) |
| strict | 如果是true,則需要使用strict的用法, 詳見(jiàn)ejohn.org/blog/ecmasc… |
| white | 如果是true,則需要嚴(yán)格使用空格用法。 |
當(dāng)然,千萬(wàn)別以為JSHINT就只有這些配置項(xiàng),在我使用的過(guò)程中,發(fā)現(xiàn)很多配置項(xiàng)就需要去讀它的源代碼才能發(fā)現(xiàn)。
比如,當(dāng)我發(fā)現(xiàn)他會(huì)報(bào)錯(cuò)我的某個(gè)自定義函數(shù)$animate沒(méi)有定義的時(shí)候,我嘗試用/*global $animate*/來(lái)聲明,但是沒(méi)有效果。
于是我跟蹤代碼,發(fā)現(xiàn)了如下的代碼
當(dāng)時(shí)我在這個(gè)后面加了一段代碼,準(zhǔn)備擴(kuò)展一個(gè)predef的項(xiàng)。
后來(lái)才發(fā)現(xiàn),原來(lái)JSHINT本身就有一個(gè)predef的配置,就像上面說(shuō)的一個(gè)數(shù)組或一個(gè)object即可。
當(dāng)然,細(xì)心的同學(xué)一定發(fā)現(xiàn)了,里面也可以聲明代碼運(yùn)行的環(huán)境。例如jquery/dojo等。
- Browser (browser)
- Development: console, alert, etc. (devel)
- jQuery (jquery)
- CouchDB (couch)
- ES5 (es5)
- Node.js (node)
- Rhino (rhino)
- Prototype.js (prototypejs)
- MooTools (mootools)
又比如JSHINT檢查的時(shí)候,針對(duì)某些字符會(huì)報(bào)”unsafe character”的錯(cuò)誤,但是如果有些字符恰巧就是我們需要的怎么辦呢?
跟蹤代碼,發(fā)現(xiàn)檢查unsafe的正則如下:
我們可以自定義一下cx
3. 返回值
當(dāng)返回false的時(shí)候,我們?nèi)绾沃来a哪里出問(wèn)題了呢?
有以下幾個(gè)方法:
1. JSHINT.errors
JSHINT.errors是一個(gè)object,有以下值:
{line: 錯(cuò)誤的行數(shù),charater: 錯(cuò)誤的字符數(shù),reason: 問(wèn)題詳細(xì)描述信息,evidence: 出錯(cuò)的代碼,raw: 原本的描述信息,a: the first detail,b: the second detail,c: the third detail,d: the fourth detail }復(fù)制代碼
2. JSHINT.report(limited)
參數(shù)limited如果為true,則表示report僅僅輸出錯(cuò)誤(errors)
返回一個(gè)類似report的最終結(jié)果。可以被放置在html中。
3. JSHINT.data()
返回一個(gè)object格式的數(shù)據(jù)結(jié)果, 有以下值:
{ errors:[ { line: 錯(cuò)誤的行數(shù)[number], charater: 錯(cuò)誤的字符數(shù)[number], reason: 問(wèn)題詳細(xì)描述信息[string], evidence: 出錯(cuò)的代碼[string] } ], functions: [ name: 函數(shù)名稱[STRING], line: 錯(cuò)誤的行數(shù)[NUMBER], last: NUMBER, param: [ 參數(shù)[STRING] ], closure: [ 閉包[STRING] ], var: [ STRING ], exception: [ STRING ], outer: [ STRING ], unused: [ STRING ], global: [ STRING ], label: [ STRING ] ], globals: [ STRING ], member: { STRING: NUMBER }, unuseds: [ { name: STRING, line: NUMBER } ], implieds: [ { name: STRING, line: NUMBER } ], urls: [ STRING ], json: 是否是json的數(shù)據(jù)[BOOLEAN]復(fù)制代碼
使用下來(lái),jshint對(duì)代碼的檢查非常不錯(cuò)的。
但是覺(jué)得jshint有些地方可以改進(jìn),例如所有的報(bào)錯(cuò)信息都是分散在四面八方。這里一句warning(“xx”),那里一句warning(“yy”)。不像wikipedia有一個(gè)統(tǒng)一管理message的地方,而且有語(yǔ)言版本的選擇。
無(wú)奈之下,我只能增加了一下message的翻譯,并且小改了一下warning的函數(shù)
warning函數(shù)增加了一個(gè)m = globalMsg[m] || m;
function warning(m, t, a, b, c, d) { var ch, l, w; t = t || nexttoken; if (t.id === ‘(end)’) { // `~ t = token; } l = t.line || 0; ch = t.from || 0; m = globalMsg[m] || m; w = { id: ‘(error)’, raw: m, evidence: lines[l - 1] || ”, line: l, character: ch, a: a, b: b, c: c, d: d }; w.reason = m.supplant(w); JSHINT.errors.push(w); if (option.passfail) { quit(‘Stopping. ‘, l, ch); } warnings += 1; if (warnings >= option.maxerr) { quit(“Too many errors.”, l, ch); } return w; }復(fù)制代碼
如果你需要一個(gè)輕量級(jí)的語(yǔ)法檢查工具,那么jshint還是一個(gè)蠻得心應(yīng)手的工具。如果能夠更深入的讀一下JSHINT的代碼,收獲應(yīng)該不小。
針對(duì)自己項(xiàng)目中遇到的一些提示,做一些舉例說(shuō)明:
1 [W099]:Mixed spaces and tabs
這個(gè)錯(cuò)誤是最常見(jiàn)的,意思是在同一行中,空格和Tab縮進(jìn)混合使用了,修改很簡(jiǎn)單,一般是刪除Tab縮進(jìn),全部改為空格。為了方便,我們可以把編輯器的Tab縮進(jìn)設(shè)置成2個(gè)或4個(gè)空格,來(lái)代替原有的縮進(jìn)。
2 [W030]:Expected an assignment or function call and instead saw an expression
這個(gè)錯(cuò)誤提示的很詭異,我是用如下代碼提示的這個(gè)錯(cuò)誤 index-1 <0 ? index = 0:index = index - 1; 這是一個(gè)逗號(hào)表達(dá)式,但是JSLInt認(rèn)為這里不應(yīng)該用表達(dá)式,而必須是一個(gè)函數(shù),所以,如果非常在乎這個(gè)錯(cuò)誤,就改為if else 語(yǔ)句吧
3 [W041]:Use '===' to compare with ...
這個(gè)錯(cuò)誤是說(shuō),我們要是用全等來(lái)代替等于,如果表達(dá)式兩邊的數(shù)據(jù)類型是一致的話,建議使用全等來(lái)判斷
4 [W033]:Missing semicolon
缺少分號(hào);這個(gè)一般都是自己忘記寫(xiě)了吧,但是有一個(gè)需要注意的是,對(duì)于只有一句的結(jié)構(gòu),后面也需要寫(xiě)分號(hào)。例如:if(index<0) {index=tcount-1} 這句代碼,正確寫(xiě)法是if(index<0) {index=tcount-1;},我是經(jīng)常忘記這里寫(xiě)分號(hào),汗...
其他還有一些錯(cuò)誤提示就對(duì)照一下改吧,要培養(yǎng)自己良好的代碼風(fēng)格和書(shū)寫(xiě)習(xí)慣。
總結(jié)
以上是生活随笔為你收集整理的JSLint检测Javascript语法规范的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Dynamics CRM 2015 站点
- 下一篇: Spring WebFlux 响应式编程