秋招快到了,咱們在準備筆試或者面試題的時候,常常會遇到一些題,給一段js代碼,回答運行後的結果是什麼,下面我來整理一下。java
一、做用域問題面試
(1)全局做用域閉包
值爲0函數
這個函數運行時,外面alert(x)拿到的是全局做用域中x的值,第一個聲明的var x=0;的值是全局做用域中的值,第二個在f函數中聲明的var x=2的值是局部做用域的值,由於用var從新聲明瞭一個變量,兩個指向的是不一樣的做用域,所以alert(x)返回的是0spa
(2)局部做用域3d
若是咱們把var x=2;中的var去掉,變成下面這樣子blog
值爲2作用域
出現這種狀況是由於,var x=0;聲明的是全局做用域的值,f()函數也是全局做用域,而後f函數中的值。x會覆蓋掉外部的值,所以就會致使獲得的值是2it
再來看一個例子io
這個值爲3,4,i is not defined
這個也是由於x,y有聲明而且在全局做用域中,這時就能獲得x,y的值,而i是在f函數中命名的,在外部的全局中就不能調用到。
若是將alert()語句放在f函數中,像下面這樣
值爲3,4,20
二、函數覆蓋問題
值爲1,1
這裏f函數將x的值置爲1,而後雖然兩次調用f()函數,可是函數已經產生覆蓋,第一個函數覆蓋了第二個函數,所以兩次調用都是1
若是將上面的匿名函數f註釋掉,以下
值爲2,2
這時,已經不發生函數覆蓋,就一直是2,
若是將命名函數註釋掉
值爲1,1
像這樣,也不發生函數覆蓋,也是隻調用f函數、
要解決函數覆蓋的方法,就先寫命名函數,再寫匿名函數
值爲2,1
這樣的話,命名函數f()先調用,匿名函數f後調用
總結:之後寫函數時,儘可能寫成匿名函數形式,var f = function(){}
三、變量和函數提高問題
一、函數未定義
變量未定義,直接是undefined
二、函數已定義
這裏聲明瞭變量,js解釋器「前瞻性」查找全部變量定義,把它們「提高」到函數頂部,就出現undefined,第一個未定義就出現undefined,第二個定義了就出現1223
三、內部變量重複定義
這裏使用了閉包函數,第一個name變量提高,就會出現undefined,原本能夠訪問到全局做用域的name,可是內部已經從新聲明瞭,name變量提高,就會出現undefined。這裏典型的使用了函數聲明提早,函數體內的塊級做用域覆蓋住了外部name的全局做用域,而後因爲函數聲明提高,至關於在函數體內,先var name;而後console.log("Original name was"+name);而後name = "Underhill";console.log("New name is" + name);最後的值是同樣的。
所以,建議全部變量的定義,都放在頭部,並使用var a=XX,b=xxx這樣定義。
四、函數直接調用
這裏函數直接調用就沒什麼好說的
五、函數定義提高
函數定義提高僅僅做用域函數定義,而不做用於函數表達式
這裏函數definitionHoisted(),已經提高,而函數定義不做用於函數表達式,所以就拋出TypeError
六、命名函數表達式
在這裏,函數名字是funcName()是函數的一部分,不會獲得提高,而varName()也找不到這個方法
七、閉包函數與全局函數
var result = f1();就調用了f1()函數,這時result即爲f2,函數,result是全局變量
result() 調用完以後的值爲999,這時就是調用了f2函數,並將值輸出
nAdd(),調用完以後,這時nAdd()函數爲全局函數,也是閉包函數,值爲1000,
result(),這個調用f2函數,就輸出1000.
8.閉包中的命名提高。
這裏輸出的值是999,由於1000傳入進去,a的值被覆蓋了,a變量命名提高,輸出就是999;
九、函數覆蓋問題
在js函數中,是沒有函數重載的,之前學java的時候,當函數名是相同的,主要傳遞的類型或者參數不一樣就會出現重載,兩個均可以用,可是在js中
主要出現兩個同名的函數,就會出現函數覆蓋,第二個add函數,覆蓋第一個add函數,而後,因爲函數聲明提早,就會直接將函數覆蓋。
那麼什麼是函數聲明提早呢?
函數聲明提早就是變量在變量聲明以前就是已經可用,通常用在函數體內,在一個函數體內是塊級做用域,通常函數,內部同名函數會覆蓋外部同名函數,而後又因爲函數聲明提早,就能夠有值。
That's all,Thank you!