摘要:在中,沒有塊級作用域一說在或者等語言中,等語句塊內可以包含自己的局部變量,這些變量的作用域是這些語句的語句塊,而在中,不存在塊級作用域的說法。作用域鏈如果要深入理解中變量的作用域,那就必須拿出作用域鏈這個終極武器。
Javascript 這門語言與其他的大部分語言相比,有很多特殊性,這是很多人喜歡它或者討厭它的原因。其中變量的作用域問題,對很多初學者來說就是一個又一個「坑」。
變量的作用域在編程技能中算是一個基本概念,而在 Javascript 中,這一基本概念往往挑戰者初學者的常識。
基本的變量作用域先上例子:
javascriptvar scope = "global"; function checkScope(){ var scope = "local"; console.log(scope); // local } checkScope(); console.log(scope); // global
上面的例子中,聲明了全局變量 scope 和函數體內的局部變量 scope。在函數體內部,局部變量的優先級比通明的全局變量要高,如果一個局部變量的名字與一個全局變量相同,那么,在聲明局部變量的函數體范圍內,局部變量將覆蓋同名的全局變量。
下面再看一個例子:
javascriptscope = "global"; function checkScope(){ scope = "local"; console.log(scope); // local myScope = "local"; console.log(myScope); // local } checkScope(); console.log(scope); // local console.log(myScope); // local
對于初學者來說,可能會有兩個疑問:為什么在函數體外,scope 的值也變成了 local ?為什么在函數體外可以訪問 myScope 變量?
這兩個問題都源于一個特性。在全局作用域中聲明變量可以省略 var 關鍵字,但是如果在函數體內聲明變量時不使用 var 關鍵字,就會發生上面的現象。首先,函數體內的第一行語句,把全局變量中的 scope 變量的值改變了。而在聲明 myScope 變量時,由于沒有使用 var 關鍵字,Javascript 就會在全局范圍內聲明這個變量。因此,在聲明局部變量時使用 var 關鍵字是個很好的習慣。
在 Javascript 中,沒有「塊級作用域」一說在 C 或者 Java 等語言中,if、for 等語句塊內可以包含自己的局部變量,這些變量的作用域是這些語句的語句塊,而在 Javascript 中,不存在「塊級作用域」的說法。
看下面的例子:
javascriptfunction checkScope(obj){ var i = 0; if (typeof obj == "object") { var j = 0; for (var k = 0; k < 10; k++) { console.log(k); } console.log(k); } console.log(j); } checkScope(new Object());
在上面的例子中,每一條控制臺輸出語句都能輸出正確的值,這是因為,由于 Javascript 中不存在塊級作用域,因此,函數中聲明的所有變量,無論是在哪里聲明的,在整個函數中它們都是有定義的。
如果要更加強調上文中 函數中聲明的所有變量,無論是在哪里聲明的,在整個函數中它們都是有定義的 這句話,那么還可以在后面跟一句話:函數中聲明的所有變量,無論是在哪里聲明的,在整個函數中它們都是有定義的,即使是在聲明之前。對于這句話,有個經典的困擾初學者的「坑」。
javascriptvar a = 2; function test(){ console.log(a); var a = 10; } test();
上面的例子中,控制臺輸出變量 a 的值為 undefined,既不是全局變量 a 的值 2,也不是局部變量 a 的值 10。首先,局部變量在整個函數體內都是有定義的,因此,局部變量 a 會在函數體內覆蓋全局變量 a,而在函數體內,在 var 語句之前,它是不會被初始化的。如果要讀取一個未被初始化的變量,將會得到一個默認值 undefined。
所以,上面示例中的代碼與下面的代碼時等價的:
javascriptvar a = 2; function test(){ var a; console.log(a); a = 10; } test();
可見,把所有的函數聲明集合起來放在函數的開頭是個良好的習慣。
變量的真相可能很多人已經注意到,在 Javascript 當中,一個變量與一個對象的一個屬性,有很多相似的地方,實際上,它們并沒有什么本質區別。在 Javascript 中,任何變量都是某個特定對象的屬性。
全局變量都是全局對象的屬性。在 Javascript 解釋器開始運行且沒有執行 Javascript 代碼之前,會有一個「全局對象」被創建,然后 Javascript 解釋器會給它與定義一些屬性,這些屬性就是我們在 Javascript 代碼中可以直接使用的內置的變量和方法。之后,每當我們定義一個全局變量,實際上是給全局對象定義了一個屬性。
在客戶端的 Javascript 當中,這個全局變量就是 Window 對象,它有一個指向自己的屬性 window ,這就是我們常用的全局變量。
對于函數的局部變量,則是在函數開始執行時,會有一個對應的「調用對象」被創建,函數的局部變量都作為它的屬性而存儲。這樣可以防止局部變量覆蓋全局變量。
作用域鏈如果要深入理解 Javascript 中變量的作用域,那就必須拿出「作用域鏈」這個終極武器。
首先要理解的一個名詞就是「執行環境」,每當 Javascript 執行時,都會有一個對應的執行環境被創建,這個執行環境中很重要的一部分就是函數的調用對象(前面說過,調用對象是用來存儲相應函數的局部變量的對象),每一個 Javascript 方法都是在自己獨有的執行環境中運行的。簡而言之,函數的執行環境包含了調用對象,調用對象的屬性就是函數的局部變量,每個函數就是在這樣的執行環境中執行,而在函數之外的代碼,也在一個執行環境中,這個執行環境包含了全局變量。
在 Javascript 的執行環境中,還有一個與之對應的「作用域鏈」,它是一個由對象組成的列表或鏈。
當 Javascript 代碼需要查詢一個變量 x 的時候,會有一個被稱為「變量名解析」的過程。它會首先檢查作用域鏈的第一個對象,如果這個對象包含名為 x 的屬性,那么就采用這個屬性的值,否則,會繼續檢查第二個對象,依此類推。當檢查到最后一個對象的時候仍然沒有相應的屬性,則這個變量會被認定為是「未定義」的。
在全局的 Javascript 執行環境中,作用域鏈中只包含一個對象,就是全局對象。而在函數的執行環境中,則同時包含函數的調用對象。由于 Javascript 的函數是可以嵌套的,因此每個函數執行環境的作用域鏈可能包含不同數目個對象,一個非嵌套的函數的執行環境中,作用域鏈包含了這個函數的調用對象和全局對象,而在嵌套的函數的執行環境中,作用域鏈包含了嵌套的每一層函數的調用對象以及全局變量。
我們可以用一個圖來直觀地解釋作用域鏈和變量名解析的過程:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/85791.html
前言 JavaScript中有一個被稱為作用域(Scope)的特性。雖然對于許多新手開發者來說,作用域的概念并不是很容易理解,本文我會盡我所能用最簡單的方式來解釋作用域和作用域鏈,希望大家有所收獲! 想閱讀更多優質文章請猛戳GitHub博客 作用域(Scope) 1.什么是作用域 作用域是在運行時代碼中的某些特定部分中變量,函數和對象的可訪問性。換句話說,作用域決定了代碼區塊中變量和其他資源的可見...
前言 JavaScript中有一個被稱為作用域(Scope)的特性。雖然對于許多新手開發者來說,作用域的概念并不是很容易理解,本文我會盡我所能用最簡單的方式來解釋作用域和作用域鏈,希望大家有所收獲! 想閱讀更多優質文章請猛戳GitHub博客 作用域(Scope) 1.什么是作用域 作用域是在運行時代碼中的某些特定部分中變量,函數和對象的可訪問性。換句話說,作用域決定了代碼區塊中變量和其他資源的可見...
摘要:作用域是代碼的不同部分在運行期間的可見性。大多數開發者想當然地理解作用域,但毫無疑問,有它自己的說明。變量可能是全局作用域的,或者是方法作用域的。總而言之,不要重復聲明變量,使用良好命名,盡力避免在聲明前調用和執行任何東西。 原文鏈接:https://hackernoon.com/unders... 什么是作用域? 就像JavaScript中的其他東西一樣,作用域并無特別之處。盡管大多...
摘要:也毫不例外,但在中作用域的特性與其他高級語言稍有不同,這是很多學習者久久難以理清的一個核心知識點。主要使用的是函數作用域。 關于作用域:About Scope 作用域是程序設計里的基礎特性,是作用域使得程序運行時可以使用變量存儲值、記錄和改變程序的狀態。JavaScript 也毫不例外,但在 JavaScript 中作用域的特性與其他高級語言稍有不同,這是很多學習者久久難以理清的一個核...
摘要:講作用域鏈首先要從作用域講起,下面是百度百科里對作用域的定義作用域在許多程序設計語言中非常重要。原文出處談談語法里一些難點問題二 3) 作用域鏈相關的問題 作用域鏈是javascript語言里非常紅的概念,很多學習和使用javascript語言的程序員都知道作用域鏈是理解javascript里很重要的一些概念的關鍵,這些概念包括this指針,閉包等等,它非常紅的另一個重要原因就...
閱讀 1184·2023-04-26 00:34
閱讀 3357·2023-04-25 16:47
閱讀 2120·2021-11-24 11:14
閱讀 3106·2021-09-26 09:55
閱讀 3718·2019-08-30 15:56
閱讀 3217·2019-08-29 16:57
閱讀 1911·2019-08-26 13:38
閱讀 2669·2019-08-26 12:22