前端入門7-JavaScript語法之相關術語
宣告
本系列文章內容全部梳理自以下幾個來源:
- 《JavaScript權威指南》
- MDN web docs
- Github:smyhvae/web
- Github:goddyZhao/Translation/JavaScript
作為一個前端小白,入門跟著這幾個來源學習,感謝作者的分享,在其基礎上,通過自己的理解,梳理出的知識點,或許有遺漏,或許有些理解是錯誤的,如有發現,歡迎指點下。
PS:梳理的內容以《JavaScript權威指南》這本書中的內容為主,因此接下去跟 JavaScript 語法相關的系列文章基本只介紹 ES5 標準規範的內容、ES6 等這系列梳理完再單獨來講講。
正文-相關術語
對於從 Java 或 C++ 轉過來的開發人員來說 JavaScript 會有點讓人困惑,因為它全部都是動態的,都是執行時,而且不存在類機制。所有的都是例項物件。所以,學習一些 JavaScript 的語言特性時,最好不要試圖從 Java 中尋找相關概念硬套過來,類比可以。
接下去一系列關於 JavaScript 語法的文章中,將會出現很多在 Java 裡出現或者沒出現過的專業術語,所以第一篇就先來羅列一下,每個術語先給一定的解釋。
有的理解不了沒關係,等這系列文章看完,再回過頭來看這一張基本也都能理解了。先羅列出來,至少有個印象,不至於到時看到一臉懵逼。
直接量
可以直接使用的資料值,即在程式中直接出現的資料值,如:
"hello world"
123
{name:dasu}
[]
...
等等這些直接出現可直接使用的資料值稱為直接量,不同資料型別有不同的叫法,常見的有:數字直接量、字串直接量、正則表示式直接量、物件直接量、陣列直接量等。
字面量
跟直接量沒什麼區別,都是同一個單詞 literals 的不同翻譯而已,所以直接量也就是字面量,字面量就是直接量,不同書可能用的不同翻譯而已。
原始值
原始型別的值稱為原始值,原始值是不可變的。在 JavaScript 中,有兩種資料型別:原始型別和物件型別。
原始型別包括:數字(Number)、字串(String)、布林(Boolean)、null、undefined。
表示式&語句
表示式可以理解成方程式,用於計算某個結果值或某種行為的程式碼可稱為表示式,通常它們並不會改變程式狀態,也不會影響程式後續執行流程,如算術表示式: x+1。
語句表示一個完整的行為,可以是多個表示式與關鍵字、運算子等的組合。
函式&方法
function 關鍵字宣告的稱為函式,但將函式置於物件內時,此時稱它為物件的方法。
簡單的理解,從不同的角度看待,如果是從函式本身,那麼它就是個函式,如果是從物件角度看待,那麼稱某個函式是物件的方法,本質上沒什麼區別。但當呼叫時會有所區別。
另外,函式本質上也是一個物件。
建構函式
JavaScript 沒有類似於 Java 的 class 機制,一個函式,當和 new 關鍵字一起使用時,此時稱這個函式為建構函式。
也就是所有的函式都可以作為建構函式,當它和 new 關鍵字一起使用時,此時它的行為有區別於普通的函式呼叫。
全域性物件
在前端裡,當 js 的宿主是瀏覽器時,全域性物件是 window。全域性物件有幾點特性:
- js 檔案中不在函式內宣告的所有變數和函式都是作為全域性物件的屬性存在。
- 全域性物件的屬性使用時,可以直接通過屬性名訪問,不必新增字首,也就是不必像 window.name 這麼使用。
- js 檔案中,函式外出現的 this 都指向全域性物件 window。
全域性屬性
全域性物件的屬性就稱全域性屬性,但這裡的全域性屬性,更多的是在表示這種場景下為全域性物件建立的屬性:
<script type="text/javascript">
weixin = dasuAndroidTv;
</script>
當我們在函式外部直接對一個不存在的變數賦值操作時,此時等價於執行 this.weixin = dasuAndroidTv
,而 this 指向全域性物件,所以會自動為全域性物件新增一個屬性,屬性名為 weixin。
所以,有時候,全域性屬性是特指這種場景下為全域性物件建立的屬性。之所以會用全域性屬性來稱呼這種場景,是為了跟下面的全域性變數和全域性函式區分開。
全域性變數
<script type="text/javascript">
var weixin = dasuAndroidTv;
</script>
像這種不在函式內宣告的變數,稱為全域性變數。雖然,它們最終也都是作為全域性物件 window 的屬性而存在,但由於這種方式為 window 建立的屬性和上述介紹的不加 var 關鍵字為全域性物件新增屬性的方式有本質上的區別。
所以,為了和上述介紹的全域性屬性概念區別開來,通常稱這種通過 var 為全域性物件建立的屬性為全域性變數。
既然全域性物件的屬性在任何地方都可以不加字首的直接訪問使用,所以全域性變數在任何地方都可以被使用。
對於上述介紹的那種直接對不存在的屬性進行賦值操作行為而建立的全域性屬性,是可通過 delete 動態刪除的;
而通過 var 或 function 這種宣告全域性變數的方式為全域性物件建立的屬性,是不可通過 delete 刪除的。
全域性函式
<script type="text/javascript">
function add() {}
</script>
像這種不在函式內宣告的函式,稱為全域性函式。它跟全域性變數的特性、用意一模一樣,區別只在於一個是變數、一個是函式而言。
包裝物件
原始型別所對應的物件型別,類似於 Java 中的包裝類。
因為原始型別不是物件,不可操作方法和屬性,但可將其轉換為對應的物件型別,此時稱為包裝物件,即可像操作物件一樣操作這些轉成包裝物件的原始型別資料。
包裝物件有:Number, Boolean, String
原型
由於在 JavaScript 中,除了原始型別,其餘的皆為物件,所以它的繼承雙方只能都是物件,也就是說,物件也是繼承自物件的,那麼作為父類角色,作為被繼承的那個物件,此時稱它為原型。
所以,才說 JavaScript 是基於原型的繼承語言。
原型就是類似於 Java 中父類的概念。
原型鏈
既然涉及繼承,那麼自然就有繼承結構,這個結構在 JavaScript 中就稱為原型鏈。
比如物件 a 繼承自物件 b,物件 b 繼承自物件 c,那麼 a 的原型鏈就表示為:a -> b -> c(省略掉內建的繼承關係)。
原型鏈用於當操作物件某個屬性時,尋找該屬性的來源。
作用域
作用域指的是變數和函式的作用域,下面統稱變數,在 JavaScript 中,變數分兩種:全域性變數和區域性變數。
全域性變數指的是在函式外定義的變數,作用域是全域性,在任何地方都可以使用,即使跨 js 檔案中也可以使用,因為它們實際上是作為全域性物件的屬性存在,在前端裡就是作為 window 的屬性,而多個 <script> 中的不同 js 檔案,都是共用同一個全域性物件 window,自然就可以跨檔案使用它的屬性。
區域性變數指函式內部定義的變數,或者函式形參,作用域為函式內。需要區別於 Java 中的區域性變數,Java 裡的區域性變數的作用域為塊級作用域:只能在區域性變數宣告的程式碼塊且宣告位置之後使用;但在 JavaScript 中,變數都有宣告提前的特性,區域性變數在函式內不管哪裡都可以訪問,即使宣告的位置在末尾,或內嵌的程式碼塊中。
作用域鏈
在 JavaScript 中,允許在函式內部繼續定義函式,所以函式可以存在很深的巢狀層次,這裡的巢狀層次不是指呼叫的巢狀,而是指函式宣告的巢狀,A 函式在 B 函式中定義,作為 B 函式的區域性變數存在這種。
而內部函式是可以訪問外部函式內的變數的,也可以訪問全域性的變數,那麼當內部函式使用了某個外部變數,就會藉助作用域鏈,沿著作用域鏈中尋找這個外部變數究竟是外部函式內的變數,還是全域性變數。
從原理上解釋,每個函式呼叫時,都會建立一個函式執行上下文,執行上下文中儲存著當前上下文中的所有變數,作用域鏈,就是將具有巢狀層次的函式的上下文中的變數串接起來的存在。
還是要反覆強調,上面的巢狀層次指的不是函式呼叫時的巢狀層次,而是函式定義時的巢狀層次。可以將這裡有巢狀層次關係的函式理解成 Java 中的內部類。
閉包
MDN 中的文章對其的解釋為:閉包是函式和宣告該函式的詞法環境的組合,這個環境包含了這個閉包建立時所能訪問的所有區域性變數。
某篇文章中看到過這麼一種解釋:閉包是程式碼塊和建立該程式碼塊的上下文中資料的結合。
閉包的概念不怎麼好理解,有的文章裡會說,函式就是閉包,有的說內嵌的函式是閉包,這裡先不做評價,先嚐試著從上面兩種解釋中去理解一下,看能否理解,後續會專門寫一篇來講講。
大家好,我是 dasu,歡迎關注我的公眾號(dasuAndroidTv),公眾號中有我的聯絡方式,歡迎有事沒事來嘮嗑一下,如果你覺得本篇內容有幫助到你,可以轉載但記得要關注,要標明原文哦,謝謝支援~