js 變量作用域問題 以及 let

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)榉嗦耍植孔兞縳的作用域是整個(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語句中對(duì)循環(huán)變量進(jìn)行聲明是一種習(xí)慣做法谴返,不過該循環(huán)變量的作用域并不局限與for語句內(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自帶有l(wèi)et這一增強(qiáng)功能习绢。感興趣的可以試一試

嵌套函數(shù)與作用域
在JavaScript中可以對(duì)函數(shù)進(jìn)行嵌套聲明渠抹。就是說,在一個(gè)函數(shù)中聲明另一個(gè)函數(shù)闪萄。這時(shí)梧却,內(nèi)部函數(shù)可以訪問外部函數(shù)的作用域。從形式上來說败去,名稱的查找是由內(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ù)),來隱藏作用域較大的同名變量(或函數(shù))吓妆。這種情況常常會(huì)在無意中發(fā)生赊时,從而造成錯(cuò)誤。如:

    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腳本執(zhí)行前行拢,JS解釋器會(huì)對(duì)整個(gè)腳本聲明部分做解析祖秒,從而確定變量作用域,這里的var a會(huì)因?yàn)樽兞柯暶魈嵘鄣欤瑫?huì)被首先執(zhí)行狈涮,然后才是賦值(賦值的時(shí)間嚴(yán)格按照程序執(zhí)行順序來進(jìn)行),第一個(gè)console輸出100鸭栖;

第二個(gè)console我們發(fā)現(xiàn)了this引用歌馍,看見this引用就必須想this被誰調(diào)用,test函數(shù)是全局函數(shù)晕鹊,當(dāng)然是全局對(duì)象調(diào)用松却,所以就等于window.a暴浦,而全局變量已經(jīng)在開頭聲明過了var a=10,輸出10晓锻;

最后一個(gè)console歌焦,這個(gè)a是誰?因?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颠通。

 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;
之后賦值覆蓋了原來a變量的值,console結(jié)果10吏砂;
最后在函數(shù)外部的console撵儿,顯然的這里全局變量已經(jīng)被重新賦值,所以console結(jié)果為10狐血;

100/10/10

最后來一題:

var foo = 1;
function main(){
    alert(foo);
    var foo = 2;
    alert(this.foo)
    this.foo = 3;
};
// 請(qǐng)給出以下兩種方式調(diào)用函數(shù)時(shí)淀歇,alert的結(jié)果,并說明原因匈织。
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。

在來看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引用指向誰?指向m2琢岩。等價(jià)于m2.foo投剥,但是此時(shí)的m2未被定義(在下一行代碼)师脂。所以alert彈出undefined担孔。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市吃警,隨后出現(xiàn)的幾起案子糕篇,更是在濱河造成了極大的恐慌,老刑警劉巖酌心,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拌消,死亡現(xiàn)場離奇詭異,居然都是意外死亡安券,警方通過查閱死者的電腦和手機(jī)墩崩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來侯勉,“玉大人鹦筹,你說我怎么就攤上這事≈访玻” “怎么了铐拐?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長练对。 經(jīng)常有香客問我遍蟋,道長,這世上最難降的妖魔是什么螟凭? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任虚青,我火速辦了婚禮,結(jié)果婚禮上螺男,老公的妹妹穿的比我還像新娘棒厘。我一直安慰自己钟些,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布绊谭。 她就那樣靜靜地躺著政恍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪达传。 梳的紋絲不亂的頭發(fā)上篙耗,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音宪赶,去河邊找鬼宗弯。 笑死,一個(gè)胖子當(dāng)著我的面吹牛搂妻,可吹牛的內(nèi)容都是我干的蒙保。 我是一名探鬼主播,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼欲主,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼邓厕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起扁瓢,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤详恼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后引几,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體昧互,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年伟桅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了敞掘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡楣铁,死狀恐怖玖雁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情民褂,我是刑警寧澤茄菊,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站赊堪,受9級(jí)特大地震影響面殖,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜哭廉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一脊僚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦辽幌、人聲如沸增淹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽虑润。三九已至,卻和暖如春加酵,著一層夾襖步出監(jiān)牢的瞬間拳喻,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來泰國打工猪腕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留冗澈,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓陋葡,卻偏偏與公主長得像亚亲,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子腐缤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 一捌归、作用域 一個(gè)變量的作用域(scope)是程序源代碼中定義的這個(gè)變量的區(qū)域。 1. 在JS中使用的是詞法作用域(...
    掙脫吧小白閱讀 437評(píng)論 0 0
  • 記憶是最無情的存在终惑,你以為想念的人就這樣輕易地被你遺忘绍在,你以為記得的人就這么飄散在風(fēng)中。長相思兮長相憶雹有,相思最是耐...
    無言ai閱讀 689評(píng)論 1 2
  • 從8月29日起偿渡,到9月30日止,共5周霸奕。 任務(wù)溜宽,億師學(xué)網(wǎng)課《教》85節(jié),《綜》35節(jié). 計(jì)劃: 《教》17節(jié)/周质帅;...
    18bdd29b4605閱讀 603評(píng)論 0 0
  • 前言 對(duì)于流行音樂适揉,我沒法說那是我的夢(mèng)想。只能是說我通過電臺(tái)接觸到流行音樂后煤惩,曾經(jīng)夢(mèng)想成為音樂DJ來推薦優(yōu)秀的流行...
    木白的真名是徐樂閱讀 607評(píng)論 0 0
  • 人心太復(fù)雜嫉嘀,最近微博上各種劇情反轉(zhuǎn)的大戲看得我瞠目結(jié)舌,忍不住懷疑人生魄揉,于是又跑到李子柒小仙女的世外桃源里...
    小魚大大閱讀 250評(píng)論 1 1