因為正在深入了解 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!"
,雖然如此,在定義變數時,最好還是按照順序來,才不會得到一些和預期不一樣的結果。
發佈留言