接下去一系列關於 JavaScript 語法的文章中,將會出現很多在 Java 里出現或者沒出現過的專業術語,所以第一篇就先來羅列一下,每個術語先給一定的解釋。 有的理解不了沒關係,等這系列文章看完,再回過頭來看這一張基本也都能理解了。先羅列出來,至少有個印象,不至於到時看到一臉懵逼。 ...
聲明
本系列文章內容全部梳理自以下幾個來源:
- 《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),公眾號中有我的聯繫方式,歡迎有事沒事來嘮嗑一下,如果你覺得本篇內容有幫助到你,可以轉載但記得要關註,要標明原文哦,謝謝支持~