摘要:執(zhí)行結(jié)果執(zhí)行了函數(shù)同名函數(shù)后者會(huì)覆蓋前者函數(shù)執(zhí)行了函數(shù)函數(shù)執(zhí)行了函數(shù)執(zhí)行結(jié)果執(zhí)行了聲明式函數(shù)在預(yù)編譯期聲明函數(shù)及被處理了,所以即使調(diào)用函數(shù)放在聲明函數(shù)前也能執(zhí)行。
if ("a" in window) { var a = 1; } alert(a);
先來看這個(gè)題會(huì)alert出什么呢?答案很顯然會(huì)是:1
不過這道題目放在以前考我的話,那我一定會(huì)答錯(cuò),后來查找了一番資料,了解到兩個(gè)新名詞:預(yù)編譯和變量提升,為了以后不會(huì)忘記,還是留個(gè)筆記吧。
首先來了解一下什么是預(yù)編譯:對(duì)var關(guān)鍵字(值先設(shè)為undefined,執(zhí)行時(shí)才給實(shí)際值)和函數(shù)定義式進(jìn)行提前聲明,再接著順序執(zhí)行代碼,函數(shù)定義式在預(yù)編譯時(shí)期就被解析,執(zhí)行時(shí)期仍然用這個(gè)值,而無論是聲明的變量還是聲明式函數(shù),在執(zhí)行的時(shí)候,可以覆蓋預(yù)編譯時(shí)期的值。
下面我們來解釋一下上面的題目為什么是1呢,首先上面的代碼等價(jià)于下面的代碼:
var a; if("a" in window){ a = 1; }
因?yàn)閖s沒有塊級(jí)作用域,所以if里面的也是全局的,所以在預(yù)編譯過程中里面的變量a會(huì)被提出來并被賦值為undefined,然后在執(zhí)行if語句時(shí)候此時(shí)a已經(jīng)存在于window中了,只不過值暫時(shí)是undefined,于是就會(huì)去執(zhí)行if里面的代碼,所以結(jié)果為1;
再來一題:
var a = 1; function a(x){} alert(a); 等價(jià)于: var a; a = function(x){} a = 1; alert(a);
預(yù)編譯階段尋找代碼中的var(實(shí)際將var a=1拆分為var a;a=1兩部分,第一部分置頂,第二部分掛在語法樹上)以及function兩個(gè)關(guān)鍵字并置頂,在此將a以及a()分別置頂,之后在執(zhí)行階段再對(duì)a從語法樹進(jìn)行賦值,最后a為1。
理解了上面的代碼,下面再看一個(gè)類似的題目:
function a(x) { return x ; } var a; alert(a); 等價(jià)于: var a; function a(x){ return x; } alert(a);
這個(gè)題目跟上一個(gè)有點(diǎn)類似,但是卻又不同,原因就是在這里a并沒有被賦值,而只是聲明一個(gè)變量;在預(yù)編譯階段會(huì)將這種形式提前置頂,然后將function也置頂,但是function在a之后,于是預(yù)編譯后二者順序完全倒過來了,所以最后執(zhí)行結(jié)果是function a(x){return x;}。
如果顯式的給a賦值一個(gè)a=undefined;那么結(jié)果就是undefined。因?yàn)榇藭r(shí)牽扯到賦值了 賦值的話 就在執(zhí)行階段去執(zhí)行。
Fn(); //執(zhí)行結(jié)果:"執(zhí)行了函數(shù)2",同名函數(shù)后者會(huì)覆蓋前者 function Fn(){ //函數(shù)1 alert("執(zhí)行了函數(shù)1"); } function Fn(){ //函數(shù)2 alert("執(zhí)行了函數(shù)2"); }
Fn(); //執(zhí)行結(jié)果:"執(zhí)行了聲明式函數(shù)",在預(yù)編譯期聲明函數(shù)及被處理了,所以即使Fn()調(diào)用函數(shù)放在聲明函數(shù)前也能執(zhí)行。 function Fn(){ //聲明式函數(shù) alert("執(zhí)行了聲明式函數(shù)"); } var Fn = function(){ //賦值式函數(shù) alert("執(zhí)行了賦值式函數(shù)"); }
通過對(duì)比上面兩段代碼,我們不難發(fā)現(xiàn),聲明式函數(shù)與賦值式函數(shù)的區(qū)別在于:在JS的預(yù)編譯期,聲明式函數(shù)將會(huì)先被提取出來,然后才按順序執(zhí)行js代碼,所以才有這樣的結(jié)果。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/78330.html
摘要:預(yù)編譯發(fā)生在函數(shù)執(zhí)行前也就是說函數(shù)執(zhí)行時(shí),預(yù)編譯已經(jīng)結(jié)束。五總結(jié)理解預(yù)編譯需要明白變量函數(shù)聲明和變量賦值。預(yù)編譯階段,只進(jìn)行變量函數(shù)聲明,不會(huì)進(jìn)行變量的初始化即變量賦值,所有變量的值都是變量賦值是在解釋執(zhí)行階段才進(jìn)行的。 一、JS的概念 JavaScript ( JS ) 是一種具有函數(shù)優(yōu)先的輕量級(jí)解釋型或即時(shí)編譯型的編程語言。 二、JS語言特點(diǎn) 2.1 單線程 (1)JavaScri...
摘要:轉(zhuǎn)載文章公司的平臺(tái)功能越堆越多,打包也越來越費(fèi)勁,一次十幾分鐘,運(yùn)維很不爽,搗鼓了一下預(yù)編譯,試了一下大概縮短了七八分鐘,目前感覺還行,現(xiàn)在把它記下來,給需要的童鞋當(dāng)做參考,也給自己記錄一下。 (轉(zhuǎn)載文章)公司的平臺(tái)功能越堆越多,打包也越來越費(fèi)勁,一次十幾分鐘,運(yùn)維很不爽,so搗鼓了一下預(yù)編譯,試了一下大概縮短了七八分鐘,目前感覺還行,現(xiàn)在把它記下來,給需要的童鞋當(dāng)做參考,也給自己記錄...
摘要:大家都知道是解釋型語言,既然是解釋型語言,就是編譯一行,執(zhí)行一行,那又何來預(yù)編譯一說呢腳本執(zhí)行引擎都做了什么呢今天我們就來看看吧。全局域就是一切聲明的全局變量,全是的屬性等同于函數(shù)預(yù)編譯發(fā)生在函數(shù)執(zhí)行前一刻。 大家都知道JavaScript是解釋型語言,既然是解釋型語言,就是編譯一行,執(zhí)行一行,那又何來預(yù)編譯一說呢?腳本執(zhí)行js引擎都做了什么呢?今天我們就來看看吧。 1-JavaScr...
摘要:所以覺得把這個(gè)執(zhí)行的詳細(xì)過程整理一下,幫助更好的理解。類似的語法報(bào)錯(cuò)的如下圖所示三預(yù)編譯階段代碼塊通過語法分析階段之后,語法都正確的下回進(jìn)入預(yù)編譯階段。另開出新文章詳細(xì)分析,主要介紹執(zhí)行階段中的同步任務(wù)執(zhí)行和異步任務(wù)執(zhí)行機(jī)制事件循環(huán)。 一、概述 js是一種非常靈活的語言,理解js引擎的執(zhí)行過程對(duì)于我們學(xué)習(xí)js是非常有必要的。看了很多這方便文章,大多數(shù)是講的是事件循環(huán)(event loo...
摘要:所以變量聲明提升和函數(shù)聲明提升會(huì)出現(xiàn)一個(gè)先后順序預(yù)編譯過程結(jié)束。 先科普: 1.javaScript是解釋型語言,就是編譯一行,執(zhí)行一行.....2.javaScript沒有塊級(jí)及作用域......3.javaScript具有變量和函數(shù)聲明提升功能.....4.AO對(duì)象和GO對(duì)象....5.預(yù)編譯就是解決代碼執(zhí)行順序問題,與java語言類似(jvm).... 例如: (function...
閱讀 914·2019-08-30 15:54
閱讀 3394·2019-08-29 15:33
閱讀 2768·2019-08-29 13:48
閱讀 1378·2019-08-26 18:26
閱讀 3387·2019-08-26 13:55
閱讀 1577·2019-08-26 10:45
閱讀 1238·2019-08-26 10:19
閱讀 362·2019-08-26 10:16