JavaScript中的變量提升和函數(shù)提升
前言
在js中對變量進行操作后打印值經(jīng)常會出現(xiàn)undefined的現(xiàn)象。其實原因是因為js中有一個叫做變量提升的功
舉例:
var data="lyyyyy"; getData(); function getData(){ //第一次打印 console.log("data值為: ", data); var data="yyyyyyy"; //第二次打印 console.log("data值為: ", data); }
打印的值第一個為undefined,而第二個打印的值為yyyyy.
原因:
在執(zhí)行g(shù)etData()方法的時候會在函數(shù)內(nèi)部首先將變量的聲明提升到第一步。然后再聲明函數(shù)內(nèi)部的函數(shù)(如果函數(shù)內(nèi)部有函數(shù)的話)。之后才會按照方法內(nèi)部的邏輯先后順序執(zhí)行代碼。前兩步只是聲明!??!看到這里應(yīng)該就已經(jīng)知道為什么會有上面那樣的結(jié)果了。
實際的方法內(nèi)部代碼執(zhí)行順序應(yīng)該是這樣的:
function getData(){ //一。聲明變量 var data; //二。聲明函數(shù)(如果函數(shù)內(nèi)部有函數(shù)的話) //三。按照代碼的順序執(zhí)行 console.log("data值為: ", data); data="yyyyyyy"; //第二次打印 console.log("data值為: ", data); }
看到拆分后的代碼執(zhí)行順序?qū)Y(jié)果也就不迷茫了。
為什么有變量提升
那么為什么會出現(xiàn)變量提升這個現(xiàn)象呢?
其實js和其他語言一樣,都要經(jīng)歷編譯和執(zhí)行階段。而js在編譯階段的時候,會搜集所有的變量聲明并且提前聲明變量,而其他的語句都不會改變他們的順序,因此,在編譯階段的時候,第一步就已經(jīng)執(zhí)行了,而第二步則是在執(zhí)行階段執(zhí)行到該語句的時候才執(zhí)行。
javascript變量提升和函數(shù)提升
變量提升是把變量提升提到函數(shù)頂部。需要說明的是,變量提升只是提升變量的聲明,并不會把賦值也提升上來。函數(shù)提升是把整個函數(shù)都提到前面去。函數(shù)表達式不能被提升,函數(shù)聲明形式能被提升。
<!DOCTYPE html> <html lang="en"> <head> </head> <body> <script> ? ? //變量提升 ? ? function test(){ ? ? ? ? a=2; ? ? ? ? var a; ? ? ? ? console.log(a); ? //2 ? ? } ? ? test(); ? ? //變量提升,不會把賦值也提升上來 ? ? var v='Hello World'; ? ? (function(){ ? ? ? ? var v; ? ? ? ? console.log(v); ?//undefined ? ? ? ? v='I love you'; ? ? })(); ? ? //函數(shù)聲明形式能被提升 ? ? function myTest(){ ? ? ? ? foo(); ? ? ? ? function foo(){ ? ? ? ? ? ? console.log("hello world"); ?//hello world ? ? ? ? } ? ? } ? ? myTest(); ? ? //函數(shù)表達式不能被提升 ? ? function myTest2(){ ? ? ? ? foo(); ? ?//foo is not a function ? ? ? ? var foo =function foo(){ ? ? ? ? ? ? console.log("hello world"); ? ? ? ? } ? ? } ? ? myTest2(); </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> </head> <body> <script> //輸出Goodbye Jack var name = 'World!'; (function () { if (typeof name === 'undefined') { var name = 'Jack'; console.log('Goodbye ' + name); } else { console.log('Hello ' + name); } })(); //輸出Hello World! var name2 = 'World!'; (function () { if (typeof name2 === 'undefined') { name2 = 'Jack'; console.log('Goodbye ' + name2); } else { console.log('Hello ' + name2); } })(); //輸出Hello World! var name3 = 'World!'; (function () { if (typeof this.name3 === 'undefined') { var name3 = 'Jack'; console.log('Goodbye ' + name3); } else { console.log('Hello ' + this.name3); } })(); </script> </body> </html>
總結(jié)
- 1.js會將變量的聲明提升到j(luò)s頂部執(zhí)行,因此對于這種語句:var a = 2;其實上js會將其分為var a;和a = 2;兩部分,并且將var a這一步提升到頂部執(zhí)行。
- 2.變量提升的本質(zhì)其實是由于js引擎在編譯的時候,就將所有的變量聲明了,因此在執(zhí)行的時候,所有的變量都已經(jīng)完成聲明。
- 3.當(dāng)有多個同名變量聲明的時候,函數(shù)聲明會覆蓋其他的聲明。如果有多個函數(shù)聲明,則是由最后的一個函數(shù)聲明覆蓋之前所有的聲明。
到此這篇關(guān)于JavaScript中的變量提升和函數(shù)提升的文章就介紹到這了,更多相關(guān)js變量提升內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript canvas實現(xiàn)刮刮樂案例
這篇文章主要為大家詳細介紹了JavaScript canvas實現(xiàn)刮刮樂案例,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-10-10js中document.write和document.writeln的區(qū)別
這篇文章主要介紹了js中document.write和document.writeln的區(qū)別,需要的朋友可以參考下2018-03-03JavaScript實現(xiàn)可拖拽的拖動層Div實例
這篇文章主要介紹了JavaScript實現(xiàn)可拖拽的拖動層Div的方法,拖拽頁面中的div塊可實現(xiàn)div塊按照拖動軌跡移動的效果,涉及javascript鼠標(biāo)事件、頁面元素樣式結(jié)合事件函數(shù)動態(tài)操作的相關(guān)技巧,需要的朋友可以參考下2015-08-08Javascript實現(xiàn)通過選擇周數(shù)顯示開始日和結(jié)束日的實現(xiàn)代碼
這篇文章主要介紹了Javascript實現(xiàn)通過選擇周數(shù)顯示開始日和結(jié)束日的實例代碼的相關(guān)資料,非常不錯具有參考借鑒價值,需要的朋友可以參考下2016-05-05JavaScript高階函數(shù)_動力節(jié)點Java學(xué)院整理
這篇文章主要介紹了JavaScript高階函數(shù),詳細講解了什么是高階函數(shù)和高階函數(shù)的用法,有興趣的可以了解下2017-06-06詳細分析Javascript中創(chuàng)建對象的四種方式
這篇文章詳細介紹了Javascript中創(chuàng)建對象的幾種方式與每種方式的優(yōu)缺點,其中包括工廠模式、構(gòu)造函數(shù)模式、原型模式和組合使用構(gòu)造函數(shù)模式和原型模式,有需要的小伙伴們一起來學(xué)習(xí)學(xué)習(xí)吧。2016-08-08