JavaScript中的作用域和作用域鏈

作用域:

變量所在的上下文,指的是變量在哪些地方可以訪問

對于JavaScript來說有全局作用域但是沒有塊級作用域,在ES6中引入了關(guān)鍵字let可以生成塊作用域.見以下代碼:

var value = true
if (value) {
  var age = 18
  console.log(`我今年${age}歲了`)
}
console.log (`我也是${age}歲了哦`)

//輸出  "我今年18歲了"   "我也是18歲了哦"
// 可見在if()中不存在塊級作用域

在這里if()里的變量具有全局作用域,全局皆可使用

var value = true
if (value) {
  let age = 18
  console.log(`我今年${age}歲了`)
}
console.log (`我也是${age}歲了哦`)

/*輸出
  "我今年18歲了"
  "error"
  "ReferenceError: age is not defined*/

在這里使用關(guān)鍵字let 使 if () 塊里的變量age產(chǎn)生了塊級作用域,使得它只在這個塊里生效.

JS中有函數(shù)作用域,指的是作用域在函數(shù)內(nèi)部。這里一共說了三種作用域,其實可以說是兩種:一種是全局作用域琉朽,而是局部作用域(函數(shù)作用域莲趣、塊級作用域)惋砂,塊級作用域概念又包括了函數(shù)作用域呆躲。


簡要說下幾個作用域聲明方式:
  1. 全局作用域:在所有函數(shù)外部使用var語句聲明變量或者在聲明變量時忽略var則會隱式轉(zhuǎn)化為全局變量
  2. 函數(shù)作用域: 需要在函數(shù)內(nèi)部使用var 聲明變量才行
  3. 塊級作用域: 在變量名前添加let語句聲明(ES6)

作用域鏈

var a = "你好绽乔,我是a";
function scopeChain(a) {
  var b =1;
  function inScope(a) {
     var c = "螞蟻"
     console.log(`大象愛${c}`)
     console.log(`我是最內(nèi)層的函數(shù)补疑,這里也可以使用a: ${a}`)
  }
  console.log(`能使用a嗎歧沪?${a}`)
  inScope(a)
}
scopeChain(a)

這里a是全局作用域下的變量,b是函數(shù)scopeChain()作用域下的變量莲组,而c是函數(shù)scopeChain()里的inScope()函數(shù)作用域下的變量诊胞。

作用域鏈的前端始終是當前環(huán)境作用域下變量對象,逐層往外作用域鏈接锹杈,最后端是全局變量環(huán)境下的變量撵孤,這些變量時鏈接在一起,在解析一個變量時從鏈前端往后端搜索(從內(nèi)不找外部找)竭望,但是有一點值得注意:每個變量的作用域總是從自身聲明的作用域往外找邪码,而不是調(diào)用它的地方

var a = 1
function fn1(){
  function fn3(){
    var a = 4
    fn2()
  }
  var a = 2
  return fn3
}
function fn2(){
  console.log(a)
}
var fn = fn1()
fn()

 //輸出1

這里就是當fn1() 執(zhí)行后調(diào)用 fn2() 時,發(fā)現(xiàn)fn3()作用域下沒有咬清,也就是作用域鏈前端沒有闭专,往外找一層也就是fn1()作用域下進行查找,作用域也就往后端前進了一步旧烧,發(fā)現(xiàn)還是沒有影钉,繼續(xù)往外層作用域查找找到了全局作用域,也就是作用域鏈的最后端掘剪,找到了后調(diào)用它平委。

但是對于fn2()來說它需要調(diào)用a這個變量,這里也就出現(xiàn)了誤區(qū):在fn3()里有變量a夺谁,那么是用的是這個變量a嗎廉赔?

  • 但其實fn2()是發(fā)現(xiàn)不了這個變量a的肉微,因為fn2()聲明的地方并不在fn3()里,同理fn1()也不是fn2()聲明的地方蜡塌,所以對于fn2()來說它只發(fā)現(xiàn)了全局下的 var a =1 所以調(diào)用它并輸出a時也就等于1.

var a = 1
function fn1(){
  function fn2(){
    console.log(a)
  }
  function fn3(){
    var a = 4
    fn2()
  }
  var a = 2
  return fn3
}
var fn = fn1()
fn()

//輸出多少碉纳?
  • 由以上的論述可以分析出這段代碼,當fn1()被調(diào)用時也就是return fn3 ,也就調(diào)用了fn3()岗照,然后fn3()里又是調(diào)用fn2()村象,而fn() 是在fn1()里聲明的,自然也就使用了fn1()里的變量a攒至,又因為a變量在調(diào)用前聲明并賦值了,故此輸出為2

var a = 1
function fn1(){

  function fn3(){
    function fn2(){
      console.log(a)
    }
    var a

    fn2()
    a = 4
  }
  var a = 2
  return fn3
}
var fn = fn1()
fn()

//輸出多少躁劣?

分析這段代碼迫吐,發(fā)現(xiàn)與上面代碼不同之處在于先聲明了 ``` var a ``后沒有里脊賦值,在調(diào)用了fn2()后再進行的賦值账忘,那么這里應(yīng)該是多少呢志膀?

  • 這里也就牽涉到了聲明前置,對于fn3()下鳖擒,當聲明 var a時溉浙,也就是執(zhí)行到了fn3()代碼前,函數(shù)聲明和變量聲明會提前至代碼前端蒋荚,所以這里聲明并沒有影響到輸出值得改變戳稽,但是賦值操作是按照程序順序執(zhí)行的,當調(diào)用前期升,a只聲明沒有賦值惊奇,則會輸出undefined。 而具體變量查找是符合作用域鏈的順序來的.

總結(jié)如下:

  1. 函數(shù)在執(zhí)行的過程中播赁,先從自己內(nèi)部找變量
  2. 如果找不到颂郎,再從創(chuàng)建當前函數(shù)所在的作用域去找, 以此往上
  3. 注意找的是變量的當前的狀態(tài)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市容为,隨后出現(xiàn)的幾起案子乓序,更是在濱河造成了極大的恐慌,老刑警劉巖坎背,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件替劈,死亡現(xiàn)場離奇詭異,居然都是意外死亡沼瘫,警方通過查閱死者的電腦和手機抬纸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來耿戚,“玉大人湿故,你說我怎么就攤上這事阿趁。” “怎么了坛猪?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵脖阵,是天一觀的道長。 經(jīng)常有香客問我墅茉,道長命黔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任就斤,我火速辦了婚禮悍募,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘洋机。我一直安慰自己坠宴,他們只是感情好,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布绷旗。 她就那樣靜靜地躺著喜鼓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪衔肢。 梳的紋絲不亂的頭發(fā)上庄岖,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天,我揣著相機與錄音角骤,去河邊找鬼隅忿。 笑死,一個胖子當著我的面吹牛启搂,可吹牛的內(nèi)容都是我干的硼控。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼胳赌,長吁一口氣:“原來是場噩夢啊……” “哼牢撼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起疑苫,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤熏版,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后捍掺,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體撼短,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年挺勿,在試婚紗的時候發(fā)現(xiàn)自己被綠了曲横。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖禾嫉,靈堂內(nèi)的尸體忽然破棺而出灾杰,到底是詐尸還是另有隱情,我是刑警寧澤熙参,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布艳吠,位于F島的核電站,受9級特大地震影響孽椰,放射性物質(zhì)發(fā)生泄漏昭娩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一黍匾、第九天 我趴在偏房一處隱蔽的房頂上張望栏渺。 院中可真熱鬧,春花似錦膀捷、人聲如沸迈嘹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至融痛,卻和暖如春壶笼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背雁刷。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工覆劈, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人沛励。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓责语,卻偏偏與公主長得像,于是被迫代替她去往敵國和親目派。 傳聞我的和親對象是個殘疾皇子坤候,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

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