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