亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > JavaScript > 正文

JavaScript中的函數聲明和函數表達式區別淺析

2024-05-06 16:17:45
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了JavaScript中的函數聲明和函數表達式區別淺析,本文總結的淺顯易懂,非常好的一篇技術文章,需要的朋友可以參考下
 

記得在面試騰訊實習生的時候,面試官問了我這樣一道問題。

復制代碼代碼如下:

//下述兩種聲明方式有什么不同
 
function foo(){};
 
var bar = function foo(){}; 

 

當初只知道兩種聲明方式一個是函數聲明一個是函數表達式,具體有什么不同沒能說得很好。最近正好看到這方面的書籍,就想好好總結一番。

  在ECMAScript中,有兩個最常用的創建函數對象的方法,即使用函數表達式或者使用函數聲明。對此,ECMAScript規范明確了一點,即是,即函數聲明 必須始終帶有一個標識符(Identifier),也就是我們所說的函數名,而函數表達式則可以省略。

函數聲明:

復制代碼代碼如下:

function Identifier ( FormalParameterList opt){ FunctionBody }

函數聲明解析過程如下:

 

  1. 創建一個new Function對象,FormalParameterList指定參數,FunctionBody指定函數體。將當前正在運行環境中作用域鏈作為它的作用域。

  2. 為當前變量對象創建一個名為Identifier的屬性,值為Result(1)。

函數表達式:

  (函數表達式分為匿名和具名函數表達式)

復制代碼代碼如下:

  function Identifier opt( FormalParameterList opt){ FunctionBody }  //這里是具名函數表達式

 

具名函數表達式的解析過程如下:

1. 創建一個new Object對象
2. 將Result(1)添加到作用域鏈的頂端
3. 創建一個new Function對象,FormalParameterList指定參數,FunctionBody指定函數體。將當前正在運行的執行環境中作用域鏈作為它的作用域。
4. 為Result(1)創建一個名為Identifier 的屬性,其值為為Result(3),只讀,不可刪除
5. 從作用域鏈中移除Result(1)
6. 返回Result(3)

官方文檔讀起來十分拗口。簡單來說,ECMAScript是通過上下文來區分這兩者的:假如 function foo(){} 是一個賦值表達式的一部分,則認為它是一個函數表達式。而如果 function foo(){} 被包含在一個函數體內,或者位于程序(的最上層)中,則將它作為一個函數聲明來解析。顯然,在省略標識符的情況下,“表達式” 也就只能是表達式了。

 

復制代碼代碼如下:

function foo(){}; // 聲明,因為它是程序的一部分
 
var bar = function foo(){}; // 表達式,因為它是賦值表達(AssignmentExpression)的一部分
 
new function bar(){}; // 表達式,因為它是New表達式(NewExpression)的一部分
 
(function(){
    function bar(){}; // 聲明,因為它是函數體(FunctionBody)的一部分
})();

 

還有一種情況:

復制代碼代碼如下:

(function foo(){})

 

這種情況也是函數表達式,它被包含在一對圓括號中的函數,在其上下文環境中,()構成了一個分組操作符,而分組操作符只能包含表達式,更多的例子:

復制代碼代碼如下:

function foo(){}; // 函數聲明
 
(function foo(){}); // 函數表達式:注意它被包含在分組操作符中
 
try {
(var x = 5); // 分組操作符只能包含表達式,不能包含語句(這里的var就是語句)
}
catch(err) {
// SyntaxError(因為“var x = 5”是一個語句,而不是表達式——對表達式求值必須返回值,但對語句求值則未必返回值。——譯
}

 

下面簡單說說函數聲明與函數表達式的異同。聲明和表達式的行為存在著十分微妙而又十分重要的差別。

  首先,函數聲明會在任何表達式被解析和求值之前先行被解析和求值。即使聲明位于源代碼中的最后一行,它也會先于同一作用域中位于最前面的表達式被求值。還是看個例子更容易理解。在下面這個例子中,函數 fn 是在 alert 后面聲明的。但是,在alert 執行的時候,fn已經有定義了:

復制代碼代碼如下:

alert(fn()); //輸出Helloworld!   
 
function fn() {
return 'Helloworld!';
}

 


簡單總結,區別在什么地方呢?

1. 聲明總是在作用域開始時先行解析;
2. 表達式在遇到時候才運算。

函數聲明還有另外一個重要的特點,即通過條件語句控制函數聲明的行為并未標準化,因此不同環境下可能會得到不同的結果。即是:

 

復制代碼代碼如下:

// 千萬不要這樣做!
// 不同瀏覽器會有不同返回結果,
 
if (true) {
function foo() {
return 'first';
}
}
else {
function foo() {
return 'second';
}
}
foo();
 
 
// 記住,這種情況下要使用函數表達式:
var foo;
if (true) {
foo = function() {
return 'first';
};
}
else {
foo = function() {
return 'second';
};
}
foo();

 

 那么,使用函數聲明的實際規則到底是什么? 

  FunctionDeclaration(函數聲明)只能出現在Program(程序)或FunctionBody(函數體)內。從句法上講,它們 不能出現在Block(塊)({ ... })中,例如不能出現在 if、while 或 for 語句中。因為 Block(塊) 中只能包含Statement(語句), 而不能包含FunctionDeclaration(函數聲明)這樣的SourceElement(源元素)。

  另一方面,仔細看一看產生規則也會發現,唯一可能讓Expression(表達式)出現在Block(塊)中情形,就是讓它作為ExpressionStatement(表達式語句)的一部分。但是,規范明確規定了ExpressionStatement(表達式語句)不能以關鍵字function開頭。而這實際上就是說,FunctionExpression(函數表達式)同樣也不能出現在Statement(語句)或Block(塊)中(別忘了Block(塊)就是由Statement(語句)構成的)。

  由于存在上述限制,只要函數出現在塊中(像上面例子中那樣),實際上就應該將其看作一個語法錯誤,而不是什么函數聲明或表達式。

  

  那么我們應該在什么時候使用函數聲明或函數表達式呢?函數聲明只能出現在“程序代碼”中,意味著只能在其它函數體中或者全局空間;它們的定義不能不能賦值給一個變量或屬性,或者作為一個參數傳遞出現在函數調用中;下面的例子是函數聲明的允許的用法,foo(),bar()和local()都是通過函數聲明模式聲明:

 

復制代碼代碼如下:

// 全局環境
function foo() {} 
 
function local() { 
// 局部環境 
    function bar() {} 
        return bar; 
}

 

  當你在語法上不能使用函數聲明的時候,你就可以使用函數表達式。比如:傳遞一個函數作為參數或者在對象字面量中定義一個函數:

 

復制代碼代碼如下:

// 這是一個匿名函數表達式
callMe(function () { 
 
//傳遞一個函數作為參數
}); 
 
// 這是一個具名函數表達式
callMe(function me() { 
  
// 傳遞一個函數作為參數,函數名為me
}); 
 
// 其他函數表達式
var myobject = { 
    say: function () { 
 
// I am a function expression 

}; 

 

學識有限,如有錯誤,歡迎指正。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久久这里只有精品| 欧美在线精品免播放器视频| 97精品久久久| 中文字幕不卡av| 日韩精品极品视频免费观看| 欧美性xxxxx极品娇小| 亚洲国产成人久久| 一本一本久久a久久精品牛牛影视| 亚洲字幕一区二区| 国产日本欧美一区二区三区| 亚洲精品v欧美精品v日韩精品| 亚洲国产精品成人va在线观看| 亚洲第一区中文字幕| 色妞欧美日韩在线| 国产欧美一区二区三区四区| 中文一区二区视频| 欧美一级在线播放| 69视频在线免费观看| 久久成人人人人精品欧| 亚州国产精品久久久| 久久这里有精品| 91成人性视频| 亚洲最大福利网| 亚洲欧美日韩中文在线| 91系列在线播放| 久久久久久久爱| 久久久噜噜噜久久久| 国产在线拍偷自揄拍精品| 日日狠狠久久偷偷四色综合免费| 亚洲一区久久久| 亚洲色图欧美制服丝袜另类第一页| 精品久久久久久久久久久久久| 正在播放欧美一区| 国产成人精品久久二区二区91| 在线精品高清中文字幕| 欧美日韩一区二区三区在线免费观看| 欧美体内谢she精2性欧美| 精品久久久国产| 亚洲国产欧美自拍| 欧美激情xxxxx| 亚洲男人第一网站| 欧美性xxxxx极品娇小| 国产精品十八以下禁看| 欧美精品在线免费播放| 亚洲精品视频二区| 国产精品扒开腿做爽爽爽男男| 国产精品极品美女在线观看免费| 欧美黑人巨大xxx极品| 国产精品入口免费视| 日韩精品在线观看视频| 国产精品久久久久久久久久尿| 亚洲天堂av综合网| 91精品视频播放| 欧美国产亚洲精品久久久8v| 精品中文字幕在线| 亚洲国产精品久久久久秋霞不卡| 欧洲日本亚洲国产区| 26uuu国产精品视频| 78m国产成人精品视频| 日本国产精品视频| 日韩精品极品在线观看播放免费视频| 亚洲乱码一区av黑人高潮| 成人久久久久久久| 久久久久久久爱| 国产视频精品自拍| 亚洲最大福利视频| 欧美日韩国产一区在线| 91国产精品电影| 国产91热爆ts人妖在线| 91亚洲人电影| 久久精品国产亚洲精品2020| 亚洲丁香婷深爱综合| 成人在线小视频| 日韩av一区二区在线观看| 国产精品96久久久久久又黄又硬| 国产精品在线看| 一区二区欧美激情| 亚洲欧美一区二区三区在线| 精品成人国产在线观看男人呻吟| 日韩高清av一区二区三区| 色yeye香蕉凹凸一区二区av| 欧美亚洲在线观看| 国产三级精品网站| 国产精品99久久久久久人| 在线视频一区二区| 奇米影视亚洲狠狠色| 亚洲精品美女视频| 国产精品永久免费在线| 日韩欧美国产视频| 97成人精品区在线播放| 在线观看欧美视频| 亚洲国产精品嫩草影院久久| 一本一本久久a久久精品综合小说| 2020国产精品视频| 欧美日韩国产精品一区二区三区四区| 欧美福利视频网站| 亚洲色图美腿丝袜| 亚洲精品久久视频| 成人福利网站在线观看| 91精品国产高清久久久久久91| 亚洲免费av片| 成人网欧美在线视频| 国产精品pans私拍| 精品国产欧美一区二区三区成人| 久久精品免费播放| 欧美成人全部免费| 日韩av电影手机在线| 欧美激情视频在线免费观看 欧美视频免费一| 日韩电视剧免费观看网站| 亚洲欧美一区二区三区在线| 成人a在线观看| 欧美精品久久久久久久久久| 国产精品99久久久久久www| 久久中文字幕国产| 亲子乱一区二区三区电影| 精品久久久国产| 一本色道久久综合狠狠躁篇的优点| 国产亚洲精品久久久| 在线观看日韩av| 欧美成人精品在线视频| 日韩美女在线观看一区| 日韩亚洲国产中文字幕| 日韩av电影在线免费播放| 国产精品久久久久福利| 91精品久久久久久久久不口人| 国产成人高潮免费观看精品| 亚洲欧美在线免费观看| 国产精品视频导航| 日韩精品在线观看一区| 自拍偷拍亚洲在线| 视频在线观看99| 国产日韩av高清| 日本不卡免费高清视频| 国产精品久久久久久久久久| 欧美色道久久88综合亚洲精品| 茄子视频成人在线| 欧美成人四级hd版| 久久综合久久88| 青青久久av北条麻妃黑人| 日本精品一区二区三区在线播放视频| 欧美亚洲在线观看| 成人免费高清完整版在线观看| 欧美日韩国产一区二区三区| 色多多国产成人永久免费网站| 国产精品电影久久久久电影网| 911国产网站尤物在线观看| 亚洲视频在线观看视频| 亚洲第一免费播放区| 欧美亚洲成人免费| 亚洲男人的天堂在线播放| 这里只有精品丝袜| 欧美日韩国产精品| 精品动漫一区二区| 日本不卡免费高清视频| 成人精品在线观看| xxx成人少妇69| 51精品在线观看| 国产日韩精品一区二区| 成人国产亚洲精品a区天堂华泰| 久久久精品2019中文字幕神马| 国产69精品久久久久9| 欧美精品在线极品| 亚洲国产日韩精品在线| 亚洲无线码在线一区观看|