????????作用域(scope),程序設(shè)計(jì)概念,通常來(lái)說(shuō),一段程序代碼中所用到的名字并不總是有效/可用的,而限定這個(gè)名字的可用性的代碼范圍就是這個(gè)名字的作用域。
? ? ? ? 在理解前,先提及幾個(gè)名詞:全局變量,局部變量,變量提升,聲明,賦值,樹(shù);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 為什么?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?肯定是因?yàn)檫@幾個(gè)詞對(duì)作用域的理解有關(guān)?。?/p>
????????對(duì)于作用域概念的理解,廢話不多說(shuō),直接上題:

? ? ? ? 1.先對(duì)以上代碼進(jìn)行拆分;

? ? ? ? 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 ,如果對(duì)該答案感到疑惑,那肯定是忽略了變量提升,以及JavaScript 程序的執(zhí)行單位為行(line),也就是一行一行地執(zhí)行。
? ? ? ? 由于是在作用域 f1 函數(shù)內(nèi),那么全局變量 a 可以排除了,所以 A 答案是錯(cuò)的,這個(gè)好理解,那 B 答案是錯(cuò)的該如何理解呢?
? ? ? ? 首先,先理解變量提升;
? ??????JavaScript 引擎的工作方式是,先解析代碼,獲取所有被聲明的變量,然后再一行一行地運(yùn)行。這造成的結(jié)果,就是所有的變量的聲明語(yǔ)句,都會(huì)被提升到代碼的頭部,這就叫做變量提升(hoisting)。
? ? ? ? 這也就是為何要先開(kāi)始第一步:拆分代碼;
? ??????變量的聲明和賦值,是分開(kāi)的兩個(gè)步驟,只是聲明變量而沒(méi)有賦值,則該變量的值是undefined。
? ? ? ? var a = 2 是在 alert ( a ) 之后,所以 alert ( a ) 此時(shí)所求的 a 僅聲明未賦值,所以,正確的答案是 undefined 。
? ? ? ? 那么,如果 f1 函數(shù)中沒(méi)有聲明 a 及賦值 a ,那 alert ( a ) 所求的 a 值則取至于全局變量 a ,這里就引申出另一個(gè)概念 樹(shù) 。可以這么理解,當(dāng) f1 函數(shù)內(nèi)不存在所需變量時(shí),便會(huì)向父級(jí)調(diào)用變量。

? ? ? ? 1.依舊先變量提升;

? ? ? ? 2.求console.log ( a ),由于 f2 函數(shù)內(nèi)無(wú)變量,向父級(jí)調(diào)用變量,而?f1 函數(shù)沒(méi)包含 f2 函數(shù),所以 f1 函數(shù)不是 f2 函數(shù)的父級(jí),所以 f2 函數(shù)調(diào)用的變量為全局變量 a ,也就是 a = 1 ,所以得console.log ( a ) 的值為1。?