作用域

了解JavaScript的機制

我們學習作用域的方法是將這個過程模擬成幾個人之間的對話劫哼,那么我們先看一下都有誰參與到了這個對話:

演員表

引擎:從頭到尾負責整個JavaScript的編譯和執(zhí)行的過程
編譯器:引擎的好朋友之一,主要的工作是語法的分析和代碼的生成
作用域:引擎的另外一位好朋友浑彰,負責收集并且維護所有聲明的標識符進而組成一系列的查詢颇玷,并執(zhí)行一非常嚴格的規(guī)則锌云,確定當前執(zhí)行的代碼的這些標識符的訪問權限。

對話

當我們看到var a = 2褂乍;這段程序的時候持隧,很可能認為這是一句聲明的語句。但是在引擎的眼中逃片,這個是兩個過程:一個由編譯器在編譯的時候處理屡拨,另外的一個是引擎在執(zhí)行的時候處理。
我們仔細的看一下這段代碼在底層究竟是如何實現(xiàn)的:

  • 遇到var a题诵;這個語句的時候洁仗,會詢問作用域是否已經(jīng)有一個該名字的變量存在在同一個作用域中,如果有的話性锭,就會忽略這個聲明赠潦,否則,他會要求作用域在當前作用域的集合中聲明一個新的變量草冈。
  • 接下來編譯器會為引擎生成運行時需要的代碼她奥,這些代碼用來處理a = 2這個賦值操作,引擎運行時先訪問作用域怎棱,在當前的作用中是否有一個叫做a的變量哩俭,如果有,引擎就會使用這個變量拳恋,如果沒有凡资,引擎就會繼續(xù)查找這個變量,如果找到這個變量谬运,就會將2賦值給他隙赁,如果沒有找到的話,就會拋出一個異常梆暖。

函數(shù)作用域

在任意的代碼片段外添加包裝函數(shù)伞访,可以將內(nèi)部的變量和函數(shù)定義隱藏起來,導致外部是沒有辦法訪問內(nèi)部的任何內(nèi)容的轰驳。

var  a = 2;
foo = ()=>{ // <--添加了這一行
  var a = 3;
  console.log(a); //3
}// <--添加了這一行
foo();// <--添加了這一行
console.log(a) // 2

這個技術解決了一寫問題厚掷,但是還是有一點不理想弟灼,因為會導致一些其他的問題,因為這么做應該先聲明一個具名函數(shù)foo(),但是這個foo()污染了全局作用域冒黑,其次田绑,還是需要顯示的調(diào)用才可以,但是我們期望可以不用使用函數(shù)名抡爹,并且可以自行運行辛馆,這樣就更加理想了。

var a = 2;
(()=>{ // <--添加了這一行
  var a = 3;
  console.log(a); // 3
})()  // <--添加了這一行

console.log(a) // 2

匿名和具名

對于函數(shù)表達式最熟悉的場景就是毀掉參數(shù)豁延,舉個例子:

setTimeout(()=>{
  console.log("I waited 1 second")
})

上面的就是匿名函數(shù)表達式,因為function()..沒有名稱標識符腊状,函數(shù)表達式是可以匿名的诱咏,然而函數(shù)表達式是不可以忽略函數(shù)名的-- 在JavaScript中是違法的。
匿名函數(shù)的缺點:

  • 匿名韓式在棧追蹤中不會顯示出有具體意義的函數(shù)名缴挖,讓調(diào)試變得很有困難袋狞。
  • 沒有函數(shù)名,當函數(shù)需要引用自身的時候只能使用已經(jīng)過期的arguments.callee引用映屋,比如:在遞歸中苟鸯,另一個行數(shù)需要引用自身的例子,在時間觸發(fā)之后時間監(jiān)聽器需要解綁自身棚点。
  • 匿名函數(shù)省略了對于代碼可讀性/可理解性很重要的函數(shù)名早处,一個描述性的名稱可以讓代碼不言而喻。

立即執(zhí)行函數(shù)表達式

var a = 2;
(foo =()=>{
  var a = 3;
  console.log(a); // 3
})();

console.log(a); // 2

上面的函數(shù)被包含在一個括號的內(nèi)部瘫析,因此形成了一個表達式砌梆,然后在結尾還添加了一個(),可以來立即執(zhí)行這個函數(shù),比如(foo=()={..})()
立即執(zhí)行函數(shù)表達式的進階使用方法:就是你把他們當做函數(shù)調(diào)用并傳遞參數(shù)進去贬循。

var a = 2;
(function foo(global){
  var a = 3;
  console.log(a); // 3
  console.log(global.a); // 2
})(window);

console.log(a); // 2

我們將window對象的引用傳遞進去咸包,并將其命名為global,因此在代碼風格上對全局對象的引用變得比引用一個沒有全局字樣的變量更加清楚啦杖虾。這個模式的另外的一個應用場景就是解決undefined標識符的默認值被錯誤覆蓋導致異常的情況烂瘫。比如說:我們將一個參數(shù)命名成undefined,但是在對應的位置不傳入任何的值奇适,這樣就可以保證在代碼塊中的undefined標識符的值就是undefined坟比。

undefined = true; // 這樣做對其他的代碼是不好的,一定不要這么做
(foo= (undefined)=>{
  var a ;
  if(a ===undefined){
    console.log('undefined is safe here');
  }
})();

任何的聲明在某個作用域內(nèi)的變量滤愕,都將依附于這個作用域温算。

a = 2;
var a;
console.log(a); // 2

// ===> 等價于
var a; // 進行編譯
a = 2; // 執(zhí)行的時候進行賦值
console.log(a)
console.log(a); // undefined
var a = 2;

導致上面的結果很簡單,聲明本身會被提升间影,提升到最開始注竿,然而賦值或是其他的運行邏輯,會被留在原地。注意一下巩割,我們在進行狀態(tài)提升的時候會先提升函數(shù)的狀態(tài)裙顽,其次才是函數(shù)的狀態(tài)。

foo(); // 1
var foo;
function foo(){
  console.log(1);
}
 foo = function(){
  console.log(2)
}

因為對于上面的代碼宣谈,JavaScript的引擎是這樣進行理解的:

function foo(){
  console.log(1);
}
foo();
 foo = function(){
  console.log(2)
}
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末愈犹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子闻丑,更是在濱河造成了極大的恐慌漩怎,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嗦嗡,死亡現(xiàn)場離奇詭異勋锤,居然都是意外死亡,警方通過查閱死者的電腦和手機侥祭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門叁执,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人矮冬,你說我怎么就攤上這事谈宛。” “怎么了胎署?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵吆录,是天一觀的道長。 經(jīng)常有香客問我硝拧,道長径筏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任障陶,我火速辦了婚禮滋恬,結果婚禮上,老公的妹妹穿的比我還像新娘抱究。我一直安慰自己恢氯,他們只是感情好,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布鼓寺。 她就那樣靜靜地躺著勋拟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪妈候。 梳的紋絲不亂的頭發(fā)上敢靡,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天,我揣著相機與錄音苦银,去河邊找鬼啸胧。 笑死赶站,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的纺念。 我是一名探鬼主播贝椿,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼陷谱!你這毒婦竟也來了烙博?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤烟逊,失蹤者是張志新(化名)和其女友劉穎渣窜,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宪躯,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡图毕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了眷唉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡囤官,死狀恐怖冬阳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情党饮,我是刑警寧澤肝陪,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站刑顺,受9級特大地震影響氯窍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蹲堂,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一狼讨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧柒竞,春花似錦政供、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽趟济。三九已至,卻和暖如春衅檀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背霎俩。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工哀军, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留沉眶,地道東北人。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓排苍,卻偏偏與公主長得像沦寂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子淘衙,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

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