摘要:主要聊聊局部變量作用域變量聲明提升作用域中有以下兩種作用域全局作用域函數作用域全局作用域是函數之外最外層代碼的作用域。相對于全局作用域,可以稱之為局部作用域相對于全局變量可以將其成為局部變量。然而,這里的是在下一行進行聲明的局部變量。
主要聊聊局部變量、作用域、變量聲明提升 作用域
JavaScript中有以下兩種作用域
全局作用域
函數作用域
全局作用域是函數之外(最外層代碼)的作用域。在函數之外進行聲明的名稱屬于全局作用域。這些名稱就是所謂的全局變量以及全局函數。
而在函數內部進行聲明的名稱擁有的是函數作用域,它們僅在函數內部才有效。相對于全局作用域,可以稱之為局部作用域;相對于全局變量可以將其成為局部變量。作為函數形參的參數變量也屬于函數作用域。
var x = 1; function f() { alert("x:"+x); var x = 2; alert("x:"+x); }; f(); // undefined | 2
可能會認為函數f內第一個alert顯示的是全局變量x。然而,這里的x是在下一行進行聲明的局部變量x。這是因為,局部變量x的作用域是整個函數f內部。由于此時還沒有對其進行賦值,因此變量x的值為undefined。
等價于:
function f() { var x; alert("x:"+x); x = 2; alert("x:"+x); }; f();
所以,未避免發生錯誤,一般建議在函數開始處對所有的局部變量進行聲明。
塊級作用域var x = 1; {var x = 2;alert(x);} // 2 alert(x); // 2
如果認為塊級作用域存在,則會認為第二個alert的結果會是1,可是結果是2
看似是在代碼塊中重新聲明了塊級作用域中的變量x,但實際上,它只是將全局變量賦值為了2。等價于:
var x = 1; {x:2;alert(x);} // 2 x = 2; alert(x); // 2
在函數作用域中也存在對塊級作用域的誤解。在for語句中對循環變量進行聲明是一種習慣做法,不過該循環變量的作用域并不局限與for語句內。下面的代碼中,其實是對局部變量i進行了循環使用。
function f() { var i = 1; for (var i=1;i<10;i++) { // 省略 } // 此時變量i的值為10 };let與塊級作用域
ECMAScript5中沒有塊級作用域,但是JavaScript自帶有let這一增強功能。感興趣的可以試一試
嵌套函數與作用域在JavaScript中可以對函數進行嵌套聲明。就是說,在一個函數中聲明另一個函數。這時,內部函數可以訪問外部函數的作用域。從形式上來說,名稱的查找是由內向外的。在最后會查找全局作用域中的名稱。
function f1() { var x = 1; // 函數f1的局部變量 // 嵌套函數聲明 function f2() { var y = 2; // 函數f2的局部變量 alert(x); // 將向上一層訪問f1的局部變量 alert(y); }; function f3() { alert(y); // 如果不存在全部變量y,將返回ReferenceError } // 調用 f2(); f3(); }; f1();變量隱藏
指的是,通過作用域較小的變量(或者函數),來隱藏作用域較大的同名變量(或函數)。這種情況常常會在無意中發生,從而造成錯誤。如:
var n = 1; function f() { var n = 2; alert(n); }; f(); // 這里就是局部變量隱藏了全局變量接下來做題做題:
var a = 10; function test(){ a = 100; console.log(a); console.log(this.a); var a; console.log(a); } test();
在JS腳本執行前,JS解釋器會對整個腳本聲明部分做解析,從而確定變量作用域,這里的var a會因為變量聲明提升,會被首先執行,然后才是賦值(賦值的時間嚴格按照程序執行順序來進行),第一個console輸出100;
第二個console我們發現了this引用,看見this引用就必須想this被誰調用,test函數是全局函數,當然是全局對象調用,所以就等于window.a,而全局變量已經在開頭聲明過了var a=10,輸出10;
最后一個console,這個a是誰?因為處于函數作用域內,查找由內至外,局部變量已經存在,當然輸出局部變量,結果為100;
100/10/100
var a = 100; function test(){ console.log(a); var a = 10; console.log(a); } test()
分析函數,變量聲明提前,所以var a = 10會在函數執行前先進行聲明,但是未被賦值!賦值的時間按照源碼的順序照常執行。所以第一個console是undefined;
然后進行賦值a = 10,之后再console,結果10。
undefined/10
var a = 100; function test(){ console.log(a); a = 10; console.log(a); } test(); console.log(a);
這里test函數內部有聲明var嗎?沒有,所以這里的a其實是全局變量中的a,則第一個console結果為100;
之后賦值覆蓋了原來a變量的值,console結果10;
最后在函數外部的console,顯然的這里全局變量已經被重新賦值,所以console結果為10;
100/10/10
最后來一題:
var foo = 1; function main(){ alert(foo); var foo = 2; alert(this.foo) this.foo = 3; }; // 請給出以下兩種方式調用函數時,alert的結果,并說明原因。 var m1 = main(); // undefined | 1 var m2 = new main(); // undefined | undefined
首先是m1,這里的main函數是普通調用,則按照普通函數處理。內部var foo = 2會被提前聲明,所以第一個alert彈出undefined,之后賦值2;
第二個alert調用的是this.foo,this引用此時指向window全局對象,所以彈出的是全局變量foo的值1;
最后將全局變量重新賦值為3;
但是m1的值是什么?是undefined。這個函數沒有指定return,默認返回undefined。
在來看m2,這里是構造函數調用,當時函數內部該執行的會繼續執行,但是我們肯定知道的是構造函數的實例對象的引用會賦值給m2;
第一個alert不變,值為undefined,之后局部變量foo被賦值為2;
運行到第二個alert,這里的this引用指向誰?指向m2。等價于m2.foo,但是此時的m2未被定義(在下一行代碼)。所以alert彈出undefined。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/82987.html
摘要:再來看書中的例子變量引用了構造函數新生成的變量,所以相當于與。而全局變量是全局對象的屬性。延伸知識點最近學,發現這幾個知識點最好形成思維導圖來理解作用域變量聲明提升全局對象全局變量引用上下文構造函數原型鏈與原型。 全局變量 可以先看W3C:JavaScript 全局對象、MDN:this 全局變量,W3C里說得很清楚(JavaScript Window - 瀏覽器對象模型): sho...
摘要:全局執行環境的變量對象始終是作用域鏈中的最后一個變量對象。綜上,每個函數對應一個執行環境,每個執行環境對應一個變量對象,而多個變量對象構成了作用域鏈,如果當前執行環境是函數,那么其活動對象在作用域鏈的前端。 1.幾個概念 先說幾個概念:函數、執行環境、變量對象、作用域鏈、活動對象。這幾個東東之間有什么關系呢,往下看~ 函數 函數大家都知道,我想說的是,js中,在函數內部有兩個特殊...
摘要:全局變量函數內的局部作用域和是函數內的局部變量,而對的賦值將會覆蓋全局作用域內的同名變量。命名空間只有一個全局作用域導致的常見錯誤是命名沖突。另外兩種方式結論推薦使用匿名包裝器譯者注也就是自執行的匿名函數來創建命名空間。 盡管 JavaScript 支持一對花括號創建的代碼段,但是并不支持塊級作用域; 而僅僅支持 函數作用域。 function test() { // 一個作用域 ...
摘要:局部變量在函數中聲明的變量,函數的參數作用域是局部性的,在函數體外,或者說的當前作用域的上層是無法直接讀取的。執行結果這樣我們就在外層取得了函數內部局部變量的也就是閉包實現從外部讀取局部變量的能力。 淺談作用域 ??當我們新建一個可以儲存變量的值,怎么才能讀取到這個變量呢?能訪問到這個變量,就說明符合作用域規則,作用域規則就可以說是js引擎讀取變量的規則。??在js中變量分為兩種,全局...
摘要:變量作用域一個變量的作用域表示這個變量存在的上下文。在這種情況下,僅僅函數聲明的函數體被提升到頂部。雖然我們無需用來修飾形式參數,但是形式參數的確也是變量,并且被自動提升到次高的優先級函數聲明。 關于作用域,變量提升,函數提升的個人理解 參考: 阮一峰的JavaScript參考教程2.7函數部分 思否上一篇關于作用域,提升的博客 一篇關于作用域和提升的個人博客 MockingBird...
閱讀 3215·2021-11-24 09:39
閱讀 2944·2021-11-23 09:51
閱讀 900·2021-11-18 10:07
閱讀 3550·2021-10-11 10:57
閱讀 2757·2021-10-08 10:04
閱讀 3010·2021-09-26 10:11
閱讀 1056·2021-09-23 11:21
閱讀 2798·2019-08-29 17:28