摘要:但是變量只有其聲明被提前在作用域的最開始處,賦值結果仍然還在原來位置。
這篇博文是之前在CSDN寫的,現在移至sf。
有過C或者Java類編程經驗的同學,對于“先聲明后使用”的規則很熟悉,如果使用未聲明的變量或者函數,編譯時程序會報錯!但是,JavaScript卻是一個‘大奇葩’,可以在變量或者函數聲明之前使用,現在根據我的理解在做一下說明。
首先說明JS的hoist分為變量hoist和函數hoist兩種。
一、變量hoist看一段程序
???????var?a=10;?? ???????function?fun(){?? ?????????console.log(a);?? ?????????var?a=100;?? ?????????console.log(a);?? ??????}?? ???????fun();//undefined???100?? ???????console.log(a);//10??
?
我們知道在js中,作用域分為全局作用域和函數作用域兩種(ES6新特性,增加了塊級作用域,另做說明)。全局變量聲明有三種方式:
var(關鍵字)+變量名(標識符)方式在function外部聲明,顯示聲明
沒有使用var,直接給標識符賦值,隱式聲明
使用window全局對象來聲明,全局對象的屬性也應是全局變量?eg:window.test=50;?alert(test);
??
好,很顯然,var?a=10;在程序中是全局變量。那么,按照我們正常的邏輯輸出結果為:10??100??10。但是,實際輸出結果為:undefined 100??10,其實是JS解析器的解析原因,它會將當前作用域中聲明的所有變量和函數,放在作用域的最開始處。但是變量只有其聲明被提前在作用域的最開始處,賦值結果仍然還在原來位置。上述代碼對于解析器來說,其實是:
???????var?a=10;?? ???????function?fun(){ ??????????var?a;?? ????????? console.log(a);?? ??????????a=100;?? ????????? console.log(a);?? ???????}?? ???????fun();//undefined???100?? ???????console.log(a);//10二、函數hoist
?
講完變量hoist,現在再講一下函數hoist,函數hoist又分為兩種情況。一種是函數聲明,另一種是函數作為值賦值給變量。
先說第一種情況:
???fun();//2?? ???function?fun(){console.log(2);}?
在這種情況下,可以看出,函數JS解釋器允許在函數聲明之前使用函數,其實也就說明,在這種情況,不僅函數名提前了,同時,函數體也被提前。所以可以上述代碼可以執行。再說第二種情況:
?????fun();?? ?????var?fun=function(){?? ????????console.log(2);?? ?????}
結果為:Uncaught?TypeError:?fun?is?not?a?function??可以看出在此例中,函數只是變量聲明聲明提前,但是賦值沒有提前,并且被提前的變量默認為undefined,所以報的錯誤類型為“typeerror”,因為undefined不是函數,不能被調用。
三、變量名和函數名相同時的hoist???????function?fun(){console.log(1);}?? ???????fun();//2?? ???????function?fun(){console.log(2);}?? ???????fun();//2?? ???????var?fun=100;?? ???????console.log(fun);//100?? ???????fun();//報錯
在此例中,函數名和變量名相同,都是fun,都會提前,那么在提前時,有什么需要注意的地方呢??
函數聲明比變量聲明更置頂
聲明過得變量不會重復聲明
??
所以上述代碼等效于:
function?fun(){console.log(1);}?? ?????function?fun(){console.log(2);}//函數體覆蓋上一層函數體?? ?????var?fun;//實際無效?? ?????fun();?? ?????fun();?? ?????fun=100;?? ?????console.log(fun);?? ?????fun();
以上就是本人對于JS的hoist問題的理解,如果哪位同學,發現其中有誤,歡迎指正!我的微信號為:Alfred-kai。?
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/101930.html
摘要:原文鏈接譯者這個示例演示了與代碼拆分相結合的。這是示例的依賴圖實線表示同步導入,虛線表示異步導入除之外的所有模塊都是模塊。為了避免沖突,模塊中的模塊連接標識符被重命名,并簡化了內部導入。根模塊的外部導入和導出使用現有的結構。 原文鏈接:https://github.com/webpack/we...譯者:@justjavac 這個示例演示了與代碼拆分相結合的 Scope Hoistin...
摘要:每個構造函數都有一個屬性,用于設置所有實例對象需要共享的屬性和方法。憑直覺,函數重載可以通過或者實現,這就不去管它了。自從年雙十一正式上線,累計處理了億錯誤事件,得到了金山軟件等眾多知名用戶的認可。 譯者按:能夠讀懂這篇博客的JavaScript開發者,運氣不會太差... 原文: 10 JavaScript concepts every Node.js programmer must ...
摘要:每個構造函數都有一個屬性,用于設置所有實例對象需要共享的屬性和方法。函數重載所謂函數重載,就是函數名稱一樣,但是輸入輸出不一樣。憑直覺,函數重載可以通過或者實現,這就不去管它了。 10個JavaScript難點 1.立即執行函數 立即執行函數,即Immediately Invoked Function Expression (IIFE),正如它的名字,就是創建函數的同時立即執行。它沒有...
摘要:函數作用域和塊作用域前面講了是詞法作用域,那么什么時候會創建作用域呢主要是基于函數級別的作用域,也就是每一個函數都會創建一個作用域。函數會被當作函數表達式而不是一個標準的函數聲明來處理。 什么是作用域 來一段《你不知道的JavaScript-上卷》中的原話: 幾乎所有編程語言最基本的功能之一,就是能夠儲存變量當中的值,并且能在之后對這個 值進行訪問或修改,這些變量住在哪里?換句話說,它...
摘要:換句話說,定義在閉包中的函數可以記憶它被創建時候的環境。詞法環境的概念定義摘自百科。一個詞法環境由一個環境記錄項和可能為空的外部詞法環境引用構成。中使用詞法環境管理靜態作用域。 一個資深的同事在我出發去面試前告誡我,問JS知識點的時候千萬別主動提閉包,它就是一個坑啊!坑啊!啊! 閉包確實是js的難點和重點,其實也沒那么可怕,關鍵是機制的理解,可以和函數一起單獨拿出來說說,其實關于閉包的...
閱讀 3483·2021-11-18 10:02
閱讀 1612·2021-10-12 10:12
閱讀 2990·2021-10-09 09:53
閱讀 4858·2021-09-09 09:34
閱讀 848·2021-09-06 15:02
閱讀 2777·2021-08-05 10:02
閱讀 3134·2019-08-30 15:44
閱讀 3121·2019-08-28 18:04