js中語句末尾可以不加分號,
很多時候在做練習或寫幾個頁面時,我都是不會加的。雖然知道加了會好一點。但就是覺得很敲一句就要多按一次分號鍵(;)來加分號,而不加也不怎么樣,然后就不想加了。
也聽說在對js壓縮於,會自動給語句加分號。
只是呢,從沒認真考慮過如果分號會給js帶來錯誤?什么情況下會導致錯誤?
——看了《走進javascript——不起眼的基礎,值和分號》http://www.cnblogs.com/pssp/p/5215417.html 一文,我決定都給我的js語句加上分號。
難道是不加分號對js的影響很大?不,是我不加分號連什么情況下會導致錯誤都不知道,還偷什么懶?這不是在造坑?
先總結一下,像很多插件的js的首句前面都會有個;分號,是用來避免當如果合並如下js文件如以下情況時,解釋器可能會出錯。
//代碼塊A var a = 10; var b = 5; var c = a + b //代碼塊B ('x' + 'y').toString()
在 ('x' + 'y').toString() 前面加上分號就好了。
//代碼塊A var a = 10; var b = 5; var c = a + b //代碼塊B ;('x' + 'y').toString()
所以,分號是一件多么重要的事情。
另外,我想自己寫的一些js文件放到一些工具里去注釋或壓縮,就不能好好的運行了呢?分號?特殊語句?
如果我好好的寫分號,可能就不會糾結是分號問題還是遇到特殊的語句問題了。
值
有時我很想知道javascript解析引擎是如何區分一個變量的值,比如下面這段代碼。
var x = 'javascript'; //javascript
x = "hello"; // hello
x = 555; //555
x = null; //null
x = a; //a is not defined
x = true; //true
對於數字是直接賦值的,因為它沒有多樣性,數字就是數字。但是對於值是英文的情況就很難區分了,因為在編程語言中,英文既可能是字符串,也可能是引用的另外一個變量。因此如何區分變量和字符串就顯得格外重要,編程語言常常將字符串用引號括起來,從而達到區分變量和字符串的作用。有些語言比如java,它們還區分單引號和雙引號,單引號括起來的是一個字符,而雙引號括起來的才是字符串。但javascript並不區分字符和字符串,而是把它們都當作字符串,因此在javascript中單引號和雙引號並沒有什么區別。
雖然通過引號可以用來區分變量和字符串,但值往往也可能是一個關鍵字,比如上面那段代碼我將x賦值為null,那么這些編程語言又是如何區分變量和關鍵字的呢?
null = 123;
console.log(null); //Uncaught ReferenceError: Invalid left-hand side in assignment
undefined = 456;
console.log(undefined); //undefined
以上我給null和undefined分別賦給了另外一個值,其結果,給null賦值報錯了,給undefined賦值雖然沒有報錯,但也沒有成功。也許對於null和undefined來說,它們就是值。而變量則是尋找值。我們說javascript是如何區分變量和關鍵字,最終或許就變成了javascript是如何區分變量和值的。
分號
在一些JS插件中,經常會看到類似下面這樣的一行代碼
;(function(){ ......... })();
在代碼的最前面有一個分號,那么這個分號是干什么用的呢?
我們知道一個分號代表了一段代碼的結束,但問題是javascript允許你不寫分號,這樣就出現了一個問題,代碼的結束與否不是你來決定的而是由程序來決定的,而程序也不是萬能的,往往它只是走的某個規則,而如果你寫的這段代碼和它的規則不符,最終的結果就有些不如人意了。
以下是javascript對省略分號的解析規則
var a
=
1 + 2
console.log(a) //3
javascript解析器會將以上代碼解析成
var a = 1 + 2;
console.log(a); //3
如果javascript不給2后面添加分號將會無法解析下去,也可以這么說,如果遇到無法解析下去則javascript解析器會嘗試給其添加一個分號,如果還是解析不了則報錯。又比如下面這一段代碼
var a = 10;
var b = 5;
var c = a + b
(a + b).toString()
// b is not a function
它說b不是一個函數,也就是說以上這段代碼很有可能解析成了下面這段代碼
var a = 10;
var b = 5;
var c = a + b(a + b).toString();
它把()當成了函數調用。也可以理解為javascript解析器會盡可能多的去匹配,但也有幾個例外,它們是retrun、break、continue,當javascript解析器解析到這幾個關鍵字時,它不會把換行后的內容當成是自身的,而是直接在換行之前添加分號,不妨看看下面這段代碼
function test(){
return
123;
}
console.log(test()); //undefined
它並沒有返回123,也就是說它直接在retrun后面加了分號。
再回過頭來看看,那些插件開發者為什么要在代碼第一行添加一個分號?
既然是插件,自然是給別人用的對吧,可關鍵問題是你也不清楚使用這個插件的人它的代碼是如何編寫的,這好像挺謬論的,它的代碼和我們有什么關系呢。
如果說使用者的代碼會影響我們的代碼,那么它又是如何影響的呢?比如我們正在編寫類似下面這樣的一段代碼
<script src="test.js"></script> <script src="zmz.js"></script>
第一個腳本是使用者自己寫的,第二個腳本是引入的某個插件,那么瀏覽器又是如何解析這兩個腳本的呢?不妨我們來測試一下
test.js
var a
a
zmz.js
(1+2)
如果你運行起來會發現並沒有報錯,也就是說javascript解析器並不會因為前面這個文件沒有加分號而和后一個文件中的代碼一起解析。
問題倒不在這,而是有可能你剛剛看了一本關於HTTP的書,哇靠,原來把文件合並可以減少請求數,於是乎這兩個腳本融為一體了。搖身一變成了下面這樣
var a
a(1+2)
你說這能不出錯嗎,如果我們在插件的一開始就加上分號,這種事情就不可能出現。
var a
a;(1+2)
因此不要把分號單單認為只是用來結束某段代碼,它還可以用來隔離某段代碼和別人划清界限。