JS變量聲明提升和函數(shù)聲明提升

  • JS代碼分為兩個階段:編譯階段和執(zhí)行階段页响;
  • 編譯階段:會找到所有的聲明篓足,并用合適的作用域?qū)⑺鼈冴P(guān)聯(lián)起來,這是詞法作用域的核心內(nèi)容闰蚕,包括變量聲明(var a)和函數(shù)聲明(function a(){})在內(nèi)的所有聲明都會在代碼被執(zhí)行前的編譯階段首先被處理栈拖;過程類似于將變量聲明和函數(shù)聲明從他們在代碼中出現(xiàn)的位置被移動到執(zhí)行環(huán)境的頂部,這個過程就叫做提升没陡,只有聲明操作會被提升辱魁,賦值和邏輯操作會被留在原地等待執(zhí)行;

一诗鸭、JS是編譯性語言
???????JavaScript是腳本語言染簇、編譯性語言、解釋性執(zhí)行强岸;和JAVA锻弓、C這種編譯性語言的區(qū)別在于JS并不會像其他的編譯語言一樣進(jìn)行提前編譯,編譯過程通常是在實際執(zhí)行前進(jìn)行的蝌箍,而且也不會產(chǎn)生可移植的編譯結(jié)果青灼;

二、引擎妓盲、編譯器杂拨、作用域

  • 引擎:負(fù)責(zé)整個JS程序的編譯及執(zhí)行過程;
  • 編譯器:負(fù)責(zé)語法分析及代碼生成等工作悯衬;
  • 作用域:收集并維護(hù)由所有聲明的標(biāo)識符(變量)組成的一系列查詢弹沽,實施一套非常嚴(yán)格的規(guī)則,確定當(dāng)前執(zhí)行的代碼對這些標(biāo)識符的訪問權(quán)限筋粗,即作用域是一個變量的“管家”策橘,用一個事先定義好的規(guī)則(詞法作用域)管理變量的查詢與訪問;
  • 變量和函數(shù)在內(nèi)的所有聲明都會在當(dāng)前塊作用域內(nèi)被首先處理娜亿,即類似于提升到最前面聲明丽已,但是賦值處理操作因為是在執(zhí)行階段,因此編譯階段他們原地待命等待執(zhí)行买决;

三沛婴、變量聲明提升

  // 變量聲明可以看成兩部分:聲明操作(var a)+賦值操作(a=10)
  // 聲明操作會在編譯階段進(jìn)行,聲明操作會被提升到執(zhí)行環(huán)境的頂部督赤,值是undefined(未初始化)
  // 賦值操作會留在原地等待執(zhí)行操作
  var a = 2;

  function foo() {
    console.log(a); // undefined
    var a = 10;
    console.log(a); // 10
  }
  foo();
// 上面的代碼相當(dāng)于
var a = 2;

  function foo() {
    var a; 
    console.log(a); // undefined
    a = 10;
    console.log(a); // 10
  }
  foo()

四嘁灯、函數(shù)聲明提升

  • 定義函數(shù)有兩種方法:函數(shù)聲明和函數(shù)表達(dá)式;
  • 函數(shù)聲明:函數(shù)聲明提升會在編譯階段把聲明和函數(shù)體整體都提前到執(zhí)行環(huán)境頂部够挂,所以可以在函數(shù)聲明之前調(diào)用這個函數(shù)旁仿;
  • 函數(shù)表達(dá)式:其實是變量聲明的一種藕夫,聲明操作會被提升到執(zhí)行環(huán)境頂部孽糖,并賦值undefined枯冈,賦值處理操作因為是在執(zhí)行階段,因此編譯階段他們原地待命等待執(zhí)行办悟;
// 函數(shù)聲明
  foo(); // 100
  function foo(){
    console.log(100)
  }
// 函數(shù)表達(dá)式
  foo(); // TypeError: foo is not a function
  var foo = function(){
    console.log(100); 
  }
// 函數(shù)表達(dá)式的等價
var foo;
foo(); // TypeError: foo is not a function
foo = function(){
    console.log(100);
}

五尘奏、控制語句

  • JS中使用函數(shù)級作用域,不存在塊級作用域病蛉,所有普通塊中的聲明都會被提升到頂部炫加,所以控制語句對聲明的控制就顯得完全沒有效果;
if (false) {
    var a = 10;
  }
  console.log(a); // undefined
// 相當(dāng)于
var a;
  if (false) {
    a = 10;
  }
  console.log(a); // undefined
  • 奇怪的函數(shù)聲明:函數(shù)聲明發(fā)生在所有代碼執(zhí)行之前铺然,所以盡管a函數(shù)的定義過程寫在了if分支中俗孝,但是理論上,它是不會影響函數(shù)聲明提升的魄健,在新版本的瀏覽器中會出現(xiàn)此問題赋铝,舊版本的瀏覽器中會在控制臺中打印出100,這也提醒了我們盡量不要在控制語句中進(jìn)行聲明沽瘦,會造成很多無法預(yù)知的bug革骨;
console.log(a); // undefined
  if(false){
    function a(){
      console.log(100);
    }
  }
  a(); // TypeError: a is not a function 理論上應(yīng)該是100

六、函數(shù)聲明規(guī)則

  • 函數(shù)優(yōu)先:
    1)提升操作會優(yōu)先進(jìn)行函數(shù)的聲明析恋;
    2)函數(shù)會首先被提升然后才是變量良哲,重復(fù)的變量聲明會被忽略,只剩下賦值操作助隧,多個函數(shù)聲明可以進(jìn)行覆蓋筑凫;
  • 聲明的順序是這樣的:
    1)找到所有的函數(shù)聲明,初始化函數(shù)體并村,如有同名的函數(shù)則會進(jìn)行覆蓋漏健;
    2)查找變量聲明,初始化為undefined橘霎,如果已經(jīng)存在同名的變量蔫浆,就什么也不做直接略過;
  // 1
  foo(); //200

  function foo() {
    console.log(100);
  }

  function foo() {
    console.log(200);
  }
  
  // 2
  console.log(foo); //function foo(){...}

  function foo() {
    console.log(200);
  }
  var foo = 100;

七姐叁、猿輔導(dǎo)的面試題

var x = 1,
    y = z = 0;

  function add(n) {
    n = n + 1;
  }
  y = add(x);

  function add(n) {
  n = n + 3;
  }
  z = add(x);
  console.log(x, y, z); // 1 undefined undefined
var x = 1,
    y = z = 0;

  function add(n) {
    n = n + 1;
    return n;
  }
  y = add(x);

  function add(n) {
    n = n + 3;
    return n;
  }
  z = add(x);
  console.log(x, y, z); // 1 4 4

參考鏈接:https://www.cnblogs.com/Gary-Guoweihan/p/6251870.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末瓦盛,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子外潜,更是在濱河造成了極大的恐慌原环,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件处窥,死亡現(xiàn)場離奇詭異嘱吗,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門谒麦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來俄讹,“玉大人,你說我怎么就攤上這事绕德』继牛” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵耻蛇,是天一觀的道長踪蹬。 經(jīng)常有香客問我,道長臣咖,這世上最難降的妖魔是什么跃捣? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮夺蛇,結(jié)果婚禮上枝缔,老公的妹妹穿的比我還像新娘。我一直安慰自己蚊惯,他們只是感情好愿卸,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著截型,像睡著了一般趴荸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上宦焦,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天发钝,我揣著相機(jī)與錄音,去河邊找鬼波闹。 笑死酝豪,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的精堕。 我是一名探鬼主播孵淘,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼歹篓!你這毒婦竟也來了瘫证?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤庄撮,失蹤者是張志新(化名)和其女友劉穎背捌,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體洞斯,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡毡庆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片么抗。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡毅否,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出乖坠,到底是詐尸還是另有隱情搀突,我是刑警寧澤刀闷,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布熊泵,位于F島的核電站,受9級特大地震影響甸昏,放射性物質(zhì)發(fā)生泄漏顽分。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一施蜜、第九天 我趴在偏房一處隱蔽的房頂上張望卒蘸。 院中可真熱鬧,春花似錦翻默、人聲如沸缸沃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽趾牧。三九已至,卻和暖如春肯污,著一層夾襖步出監(jiān)牢的瞬間翘单,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工蹦渣, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留哄芜,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓柬唯,卻偏偏與公主長得像认臊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子锄奢,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

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