????????作用域(scope)馏鹤,程序設(shè)計概念砖织,通常來說款侵,一段程序代碼中所用到的名字并不總是有效/可用的,而限定這個名字的可用性的代碼范圍就是這個名字的作用域镶苞。
? ? ? ? 在理解前喳坠,先提及幾個名詞:全局變量,局部變量茂蚓,變量提升壕鹉,聲明,賦值聋涨,樹晾浴;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 為什么?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?肯定是因為這幾個詞對作用域的理解有關(guān)半拱住脊凰!
????????對于作用域概念的理解,廢話不多說茂腥,直接上題:
? ? ? ? 1.先對以上代碼進行拆分狸涌;
? ? ? ? 2.局部變量:只作用于它所在的作用域內(nèi);而下圖局部變量 a 存在于 f1 函數(shù)內(nèi)最岗,所以局部變量a 的作用范圍僅限于 f1 函數(shù)內(nèi)帕胆,局部變量 a 的作用域就是 f1 函數(shù);
? ? ? ? 3.根據(jù) 圖a. 圖b. 理解般渡,那么 a 是多少懒豹??
????????????????A. a = 1? ? ? ?
? ? ? ? ? ? ? ? B. a = 2
? ? ? ? ? ? ? ? C. undefined
? ? ? ? ? ? ? ? 答案:C.undefined
????????出乎意料嗎?竟然是 undefined 驯用,如果對該答案感到疑惑脸秽,那肯定是忽略了變量提升,以及JavaScript 程序的執(zhí)行單位為行(line)蝴乔,也就是一行一行地執(zhí)行记餐。
? ? ? ? 由于是在作用域 f1 函數(shù)內(nèi),那么全局變量 a 可以排除了薇正,所以 A 答案是錯的剥扣,這個好理解巩剖,那 B 答案是錯的該如何理解呢?
? ? ? ? 首先钠怯,先理解變量提升佳魔;
? ??????JavaScript 引擎的工作方式是,先解析代碼晦炊,獲取所有被聲明的變量鞠鲜,然后再一行一行地運行。這造成的結(jié)果断国,就是所有的變量的聲明語句贤姆,都會被提升到代碼的頭部,這就叫做變量提升(hoisting)稳衬。
? ? ? ? 這也就是為何要先開始第一步:拆分代碼霞捡;
? ??????變量的聲明和賦值,是分開的兩個步驟薄疚,只是聲明變量而沒有賦值碧信,則該變量的值是undefined。
? ? ? ? var a = 2 是在 alert ( a ) 之后街夭,所以 alert ( a ) 此時所求的 a 僅聲明未賦值砰碴,所以,正確的答案是 undefined 板丽。
? ? ? ? 那么呈枉,如果 f1 函數(shù)中沒有聲明 a 及賦值 a ,那 alert ( a ) 所求的 a 值則取至于全局變量 a 埃碱,這里就引申出另一個概念 樹 猖辫。可以這么理解,當 f1 函數(shù)內(nèi)不存在所需變量時砚殿,便會向父級調(diào)用變量啃憎。
? ? ? ? 1.依舊先變量提升;
? ? ? ? 2.求console.log ( a )瓮具,由于 f2 函數(shù)內(nèi)無變量荧飞,向父級調(diào)用變量凡人,而?f1 函數(shù)沒包含 f2 函數(shù)名党,所以 f1 函數(shù)不是 f2 函數(shù)的父級,所以 f2 函數(shù)調(diào)用的變量為全局變量 a 挠轴,也就是 a = 1 传睹,所以得console.log ( a ) 的值為1。?