因為正在深入了解 JavaScript這個語言,因為已經下定決心要先熟練這個語言了,應該要好好瞭解並熟悉一些更深入的概念和用法才是,並且把自己的筆記放在這,希望也能有些用處。

關鍵字 – 語法解析器、執行環境、詞彙環境

語法解析器(Syntax Parser)

將JavaScript逐字地解析並轉換成電腦懂的東西(編譯器或直譯器就是語法解析器),因為如此,開發編譯器程式的開發者可以在翻譯的過程中做一些額外的事情。

執行環境(執行上下文)(Execution Context)

一個幫助管理正在執行之程式的包裹,由工程師寫好的一個環境,來驗證和執行你的程式碼。

詞彙環境(Lexical Environment)

代表程式碼在程式中實際的所在位置。

關鍵字 – 名稱/值配對與物件(Name/Value pairs and Objects)

名稱/值配對

例如:Address = '100 Main St.'Address是名稱,'100 Main St.'則是值。

物件

物件則是則是「名稱/值配對」的組合,也就是說,一個名稱,很可能只是一個更多名稱的列表
例如:

Address:
    {
        Street: 'Main',
        Number: 100,
        Apartment: {
            Floor: 3,
            Number: 301
        }
    }

Street是一個名稱、'Main'則是他的值,Apartment也是一個名稱,但他的值是另外一個名稱/值的配對,如果是從其他語言過來的話,可能會認為物件還有更深入的解釋,但在JavaScript,就是這樣而已。

全域環境與全域物件

「基礎的執行環境」(Base Execution Context)是你的全域執行環境,全域的意思是我們在程式的任何地方都可以取用他,這個全域執行環境創造兩個東西,一個是「Global Object」,另一個是特殊的「this」變數。

假設我們在「瀏覽器」執行一個空的JavaScript檔,然後在Console輸入this,會發現環境自動幫我們建立了一個window物件,而this也指向這個window物件,但如果我們是在Node.js執行,則會得到不一樣的全域物件。

當我們在程式碼輸入var a = 'Hello World!',且不是在function內,也就是全域時,這些變數或函數會自動和全域物件連結,我們要是在console輸入a會出現"Hello World!",輸入window.a也會出現"Hello World!",所以:如果你的變數和物件實際上並不在函數裡,他們就是全域物件

執行環境:創造與提升(Hoisting)

我們在更深入了解,JavaScript在創造執行環境時做了什麼,以下範例:

var a = 'Hello World!';
function b() {
    console.log('I am b!');
}

b(); // "I am b!"
console.log(a); // "Hello World!"

這個對於大家來說應該沒有問題,但是如果我們顛倒一下順序呢?

b(); // "I am b!"
console.log(a); // undefined

var a = 'Hello World!';
function b() {
    console.log('I am b!');
}

如果是從其他語言來的,應該下意識會認為根本不會執行,而且會有error,但在JavaScript,這是會被執行的,而且結果會和上面一樣,這就是所謂的提升(Hoisting)。

如果我們把var a = 'Hello World!';刪掉的話,則會得到沒有定義a變數的error,為什麼會這樣呢?這跟JavaScript創造執行環境的步驟有關係。

創造執行環境的第一個步驟:創造步驟,會先創造一個全域物件、一個特殊的this變數以及Outer Environment,最後,語法解析器會把我們的程式碼看過一遍,知道我們在哪裡創造變數和函數,並把所有的變數和函數在記憶體預留位置,最後的這個步驟就是「提升」(Hoisting),此時,函數內的程式碼已經先被執行了,但是變數只是先預留位置,還不知道值是什麼,所以會先被給予undefined,這也是為什麼會得到console.log(a); // undefined的結果,而函數因為已經被事先設定好了,所以會正確得到"I am b!",雖然如此,在定義變數時,最好還是按照順序來,才不會得到一些和預期不一樣的結果。