值
有時我很想知道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)
var a a(1+2)
var a a;(1+2)