日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Javascript 函数声明和函数表达式的区别

發(fā)布時間:2025/4/16 java 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Javascript 函数声明和函数表达式的区别 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

2019獨角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

Javascript Function無處不在,而且功能強大!通過Javascript函數(shù)可以讓JS具有面向?qū)ο蟮囊恍┨卣?#xff0c;實現(xiàn)封裝、繼承等,也可以讓代碼得到復(fù)用。但事物都有兩面性,Javascript函數(shù)有的時候也比較“任性”,你如果不了解它的“性情”,它很可能給你制造出一些意想不到的麻煩(bugs)出來。 ?

Javascript Function有兩種類型:

1)函數(shù)聲明(Function Declaration);

// 函數(shù)聲明function funDeclaration(type){return type==="Declaration";}

2)函數(shù)表達式(Function Expression)。

// 函數(shù)表達式var funExpression = function(type){return type==="Expression";}

上面的代碼看起來很類似,感覺也沒什么太大差別。但實際上,Javascript函數(shù)上的一個“陷阱”就體現(xiàn)在Javascript兩種類型的函數(shù)定義上。下面看兩段代碼(分別標(biāo)記為代碼1段和代碼2段):

funDeclaration("Declaration");//=> truefunction funDeclaration(type){return type==="Declaration";} funExpression("Expression");//=>errorvar funExpression = function(type){return type==="Expression";} 用函數(shù)聲明創(chuàng)建的函數(shù)funDeclaration可以在funDeclaration定義之前就進行調(diào)用; 而用函數(shù)表達式創(chuàng)建的funExpression函數(shù)不能在funExpression被賦值之前進行調(diào)用。 為什么會這樣呢?!這就要理解Javascript Function兩種類型的區(qū)別: 用函數(shù)聲明創(chuàng)建的函數(shù)可以在函數(shù)解析后調(diào)用(解析時進行等邏輯處理); 而用函數(shù)表達式創(chuàng)建的函數(shù)是在運行時進行賦值,且要等到表達式賦值完成后才能調(diào)用。 這個區(qū)別看似微小,但在某些情況下確實是一個難以發(fā)現(xiàn)的陷阱。 出現(xiàn)這個陷阱的本質(zhì)原因體現(xiàn)在這兩種類型在Javascript function hoisting(函數(shù)提升) 和運行時機(解析時/運行時)上的差異關(guān)于變量提升,可見我的另外一篇博文<JavaScript變量提升>上面兩段代碼的函數(shù)提升可示意為下圖:

代碼1段JS函數(shù)等同于:

function funDeclaration(type){return type==="Declaration";}funDeclaration("Declaration");//=> true

代碼2段JS函數(shù)等同于:

var funExpression;funExpression("Expression");//==>errorfunExpression = function(type){return type==="Expression";}

上述代碼在運行時,只定義了funExpression變量,但值為undefined。因此不能在undefined上進行函數(shù)調(diào)用。此時funExpression賦值語句還沒執(zhí)行到。為了進一步加深JS函數(shù)兩種類型的區(qū)別,下面給出一個更具迷惑性的示例,請看下面的代碼(代碼段4):

var sayHello;console.log(typeof (sayHey));//=>function console.log(typeof (sayHo));//=>undefinedif (true) {function sayHey() {console.log("sayHey");}sayHello = function sayHo() {console.log("sayHello");}} else {function sayHey() {console.log("sayHey2");}sayHello = function sayHo() {console.log("sayHello2");}} sayHey();// => sayHey2 sayHello();// => sayHello

分析:sayHey是用函數(shù)聲明創(chuàng)建的,在JS解析時JS編譯器將函數(shù)定義進行了函數(shù)提升,也就是說,在解析JS代碼的時候,JS編譯器(條件判斷不形成新的作用域,兩個sayHey函數(shù)定義都被提升到條件判斷之外)檢測到作用域內(nèi)有兩個同名的sayHey定義,第一個定義先被提升,第二個定義接著被提升(第二個定義在第一個定義之下),第二個定義覆蓋了第一個sayHey定義,所以sayHey()輸出sayHey2;而sayHello是用函數(shù)表達式創(chuàng)建的,其表達式的內(nèi)容是在JS運行時(不是解析時)才能確定(這里條件判斷就起到作用了),所以sayHello表達式執(zhí)行了第一個函數(shù)定義并賦值,則sayHello()輸出sayHello。

  代碼段4的代碼實際上等同于下面的代碼(代碼段5):

var sayHello;function sayHey() {console.log("sayHey");}function sayHey() {console.log("sayHey2");}console.log(typeof (sayHey));//=>function console.log(typeof (sayHo));//=>undefinedif (true) {//hoisting...sayHello = function sayHo() {console.log("sayHello");}} else {//hoisting...sayHello = function sayHo() {console.log("sayHello2");}} sayHey();// => sayHey2 sayHello();// => sayHello

有的人也許會懷疑函數(shù)sayHey的定義是第二個覆蓋第一個了么?我們可以把sayHey的源代碼進行輸出,有圖有真相,如下圖所示:

總結(jié)

  Javascript 中函數(shù)聲明和函數(shù)表達式是存在區(qū)別的,函數(shù)聲明在JS解析時進行函數(shù)提升,因此在同一個作用域內(nèi),不管函數(shù)聲明在哪里定義,該函數(shù)都可以進行調(diào)用。而函數(shù)表達式的值是在JS運行時確定,并且在表達式賦值完成后,該函數(shù)才能調(diào)用。這個微小的區(qū)別,可能會導(dǎo)致JS代碼出現(xiàn)意想不到的bug,讓你陷入莫名的陷阱中。

  最后附上代碼段4中sayHello和sayHey兩個函數(shù)的核心步驟(個人理解,若有異議歡迎留言探討):

  上圖為sayHello函數(shù)執(zhí)行的主要步驟示意圖。

上圖為sayHey函數(shù)執(zhí)行主要步驟的示意圖。若對閉包感興趣,可以看另外一篇博文<JavaScript高級特性 閉包>

轉(zhuǎn)載于:https://my.oschina.net/u/3703858/blog/1787942

《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的Javascript 函数声明和函数表达式的区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。