[JavaScriptWeird]No.1 觀念小叮嚀:語法解析器、執行環境、詞彙環境

前言

終於開始這個系列的第一篇,所以先來記錄一些比較基礎的名詞解釋,往後的課程中也會多次的提及這些詞彙,因此透過這篇記錄下來,避免自己金魚腦忘掉。

語法解析器 ( Syntax Parsers )

語法解析器可能會是一個「直譯器」或是「編譯器」,例如在 JavaScript 中我們寫的程式沒辦法直接告訴電腦該做什麼,那該怎麼辦?

需要透過一個「中間人」(在此指編譯器,也就是別人寫的程式)

概念像是這樣
克服 JS 奇怪部分 截圖

透過語法解析器,我們寫的程式碼會逐字地被解讀,如果程式碼正確,那麼語法解析器就會將其轉化為電腦看得懂的硬體指令,最後呈現出我們預想的結果。

像是如果程式碼內寫了 return;,當語法解析器看到「r」時,它預期會再看到一個「e」,語法解析器會逐字地進行。

如果語法解析器看到一些非預期的東西就會出現錯誤,但如果是正確的,就會繼續下去,並在遇到分號時結束。

語法解析器甚至可以在執行前改變我們的程式碼,像是幫忙補上分號,這也是為什麼 JavaScript 中,有時候我們忘記寫分號,程式仍然可以執行。

不過幫忙補上分號有時候並不是一件好事,有時這會讓程式難以除錯,所以我們應該避免語法解析器自動補上分號。

因為有時語法解析器做出不如我們預期的行為,像是我們輸入 return 按下「Enter」 鍵,會出現一個「Carriage Return」,這是個看不見的字元,但它確實存在,這時語法解析器會受「Carriage Return」影響,進而把有「Carriage Return」的地方替換成分號。也就是說,任何語法解析器預期會有分號的地方都會自動地補上。

舉例來說:

1
2
3
4
5
6
7
function getPerson(){  
return
{
name:'Tony'
}
}
console.log(getPerson()); // undefined

因為 return 後面有「Carriage Return」,如果 JavaScript 在關鍵字 return 後發現「Carriage Return」,就會自動補上分號,所以什麼都沒有回傳。

要讓這程式正確執行應該這麼做:

1
2
3
4
5
6
function getPerson(){  
return {
name:'Tony'
}
}
console.log(getPerson()); // {name: "Tony"}

刪除「Carriage Return」並且補上一個「空白」分隔,讓程式碼好看一點。再補上一個大括號,讓語法解析器知道要開始使用物件實體語法。

詞彙環境 (Lexical Environment)

詞彙環境指的是程式碼在整個程式中的「實際位置」,在 JavaScript 中詞彙環境非常重要,但不是每個程式語言都是這樣。

在 JavaScript 中我們可能寫了一個 函式 function

1
2
3
function hello() {  
var a = 'say hello';
}

這個函數內有個變數 a ,這個 a 詞彙上就是「在函式內」,但就像上面提到的,我們寫的程式碼需要被轉換成電腦看得懂的東西,也就是在轉換過程中,函式以及變數會被放到一個對應的記憶體位址,以及如何與其他的函式變數、程式互動。

那為什麼 JavaScript 中詞彙環境非常重要呢?

因為這可以幫助編譯器在轉換過程中做出某些決定。

執行環境 (Execution Context)

A wrapper to help mange the code that is running.

執行環境就有點像是一個管理者的角色,因為可能會有相當多的「詞彙環境」,但哪一個才是現在正執行的呢?

這就是執行環境所管理的東西。

執行環境包含了我們寫的程式碼、正在執行的程式碼,但不只包含這些,當目前程式碼正處於被編譯中時,編譯器除了執行我們的程式碼之外也能執行別的事情。

名稱 / 值 配對 & 物件

在 JavaScript 的世界中,物件是相當重要的,我們必須先了解 JavaScript 中物件的意義。

例如:名稱(name) / 值(value) 配對

一個「名稱 / 值」配對,代表「一個名稱會對應到一個值」

一段正在執行的程式碼,同樣的名稱只會有一個;一個名稱只能被一個值定義,而這個值可以是更多名稱/值的配對。

這樣說很模糊,舉例一個簡單的「名稱 / 值」配對:

1
var brother = 'Tony'

這樣我們就有了宣告(var)、變數名稱(brother)、值(Tony)

那比較複雜的「名稱 / 值」配對呢?會是什麼樣子?

記得剛才提到的物件嗎?在 JavaScript 中我們也可以同樣套用這個概念!

1
2
3
4
5
6
7
8
var farm = {  
farmName: 'nice Farm',
owner: 'Tony',
animals: {
dogs: 3,
cats: 1
}
}

例如 farm 的值是一個「名稱 / 值」 的組合,farm 仍然是個名稱,但值是用{}包覆住的「名稱 / 值」組合

繼續往下一層觀察, farmNameowner 也是「名稱 / 值」配對,注意到 animals 了嗎?它的值也是一個「名稱 / 值」 的組合。

JavaScript 中的物件,就是在說名稱 / 值配對的組合,而這個值本身可能是另一個物件

後記:

總算是把心得記錄完了,這篇主要記錄之後課程可能會多次提到的關鍵字,為了避免之後自己忘記這些關鍵字到底再說什麼,所以特別整理起來,這樣子之後回顧會比較容易。

0%