關(guān)于javascript中的function declaration 和 function expression

最近在看《Javascript for Web Developers》积暖,雖然在VT項目中的一個小demo中擔(dān)任了前端工程師,開始了javascript之路郑象,但是真正來看javascript高級語法的時候還是懵逼了册烈。

function declaration 和 function expression在講function的時候貌似講到了弥姻,當(dāng)時看的時候也是以為自己記得了强经,再看塊作用域的時候還是不太清楚睡陪。于是在網(wǎng)上找到了一篇文章,看完做個記錄也好匿情。



什么是 javascript declaration

Function declaration定義了一個命名的函數(shù)變量兰迫,但是并沒有變量賦值(without requiring variable assignment.)。 Function declration必須作為一個單獨的構(gòu)造器出現(xiàn)炬称,而不能被放在no-function的塊中汁果。

可以簡單地這么想,function declaration 就想variable declaration的兄弟一樣玲躯,只是變量聲明首先寫的是var, 而函數(shù)聲明必須以function開頭据德。

ECMA5 定義的語法是這樣的: function?Identifier(FormalParameterListopt) {FunctionBody}

function bar() {return 3;}

bar(); //3

bar; // function


什么是function expression?

Function Expression定義了一個函數(shù),使它作為一個更大的expression語法的一部分(一般是變量賦值)跷车。 通過Function Expression定義的函數(shù)可以是匿名的棘利, 不需要以function開頭。

//anonymous function expression

var a =function() {

return 3;

}

//named function expression

var a =function bar() {

return 3;

}

//self invoking function expression

(functionsayHello() {

alert("hello!");

})();

ECMA5定義的語法是:function?Identifieropt(FormalParameterListopt) {FunctionBody}

The function name (if any) is not visible outside of its scope (contrast with Function Declarations).


案例一

function ?foo(){

? ? function ?bar() {

? ? return ?3;

? ? ?}

? ?return ?bar();

? ?function bar() {

? ? ? ? return 8;

? ? }

}

alert(foo()); ?//8

Hoisting??

Function declarations and function variables are always moved (‘hoisted’) to the top of their JavaScript scope by the JavaScript interpreter

因此在案例一中姓赤,第二次聲明的bar()被放到return bar(); 語句之前了仲吏,相當(dāng)于重新定義了bar, 然后在invoke了bar(), 因此返回值為8.

我們按照習(xí)慣不铆,總覺得return之后的代碼是執(zhí)行不到的蝌焚?

在Javascript的執(zhí)行過程中有一個Context和process。 Context被分為lexical environment誓斥, variable environment 和 this binding只洒。 declartions在進(jìn)入執(zhí)行域時是在variable中的,與statement不一樣劳坑,因此和它們的執(zhí)行流程不一樣毕谴。

案例二

但是在function expression中就不一樣了。

functionfoo(){

var bar =function() {

return 3;

};

return bar();

var bar =function() {

return 8;

};

}

alert(foo()); // 3

(ECMA 5 12.2 A variable with an?initializer?is assigned the value of itsAssignmentExpressionwhen theVariableStatementis executed, not when the variable is created.)

因此該案例的實際執(zhí)行順序如下

//**Simulated processing sequence for Question 2**

functionfoo(){

//a declaration for each function expression

varbar = undefined;

varbar = undefined;

//first Function Expression is executed

bar =function() {

return3;

};

// Function created by first Function Expression is invoked

returnbar();

// second Function Expression unreachable

}

alert(foo());//3


I can see how using Function Declarations can cause confusion but are there any benefits?

Well you could argue that Function Declarations are forgiving – if you try to use a function before it is declared, hoisting fixes the order and the function gets called without mishap. But that kind of forgiveness does not encourage tight coding and in the long run is probably more likely to promote surprises than prevent them. After all, programmers arrange their statements in a particular sequence for a reason.

And there are other reasons to favor Function Expressions?

How did you guess?

a) Function Declarations feel like they were intended to mimic Java-style method declarations but Java methods are very different animals. In JavaScript functions are living objects with values. Java methods are just metadata storage. Both the following snippets define functions but only the Function Expression suggests that we are creating an object.

//Function Declaration

function add(a,b) {returna + b};

//Function Expression

var add =function(a,b) {returna + b};

b) Function Expressions are more versatile. A Function Declaration can only exist as a “statement” in isolation. All it can do is create an object variable parented by its current scope. In contrast, a Function Expression (by definition) is part of a larger construct. If you want to create an anonymous function or assign a function to a prototype or as a property of some other object you need a Function Expression. Whenever you create a new function using a high order application such as?curry?or?compose?you are using a Function Expression. Function Expressions and Functional Programming are inseparable.

//Function Expression

var sayHello = alert.curry("hello!");

Do Function Expressions have any drawbacks?

Typically functions created by Function Expressions are unnamed. For instance, the following function is anonymous,today is just a reference to an unnamed function:

1

var today = function() {return newDate()}

Does this really matter? Mostly it doesn’t, but as?Nick Fitzgerald?has pointed out debugging with anonymous functions can be frustrating. He suggests using Named Function Expressions (NFEs) as a workaround:

1

var today =function today() {returnnewDate()}

However as Asen Bozhilov points out (and Kangax?documents) NFEs do not work correctly in IE < 9

Conclusions?

Badly placed Function Declarations are misleading and there are few (if any) situations where you can’t use a Function Expression assigned to a variable instead. However if you must use Function Declarations, it will minimize confusion if you place them at the top of the scope to which they belong. I would never place a Function Declarations in an?if?statement.

Having said all this you may well find yourself in situations where it makes sense to use a Function Declaration. That’s fine. Slavish adherence to rules is dangerous and often results in tortuous code. Much more important is that you understand the concepts so that you can make your own informed decisions. I hope this article helps in that regard.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末距芬,一起剝皮案震驚了整個濱河市涝开,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌框仔,老刑警劉巖舀武,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異离斩,居然都是意外死亡银舱,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門跛梗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寻馏,“玉大人,你說我怎么就攤上這事核偿〕锨罚” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵宪祥,是天一觀的道長聂薪。 經(jīng)常有香客問我,道長蝗羊,這世上最難降的妖魔是什么藏澳? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮耀找,結(jié)果婚禮上翔悠,老公的妹妹穿的比我還像新娘。我一直安慰自己野芒,他們只是感情好蓄愁,可當(dāng)我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著狞悲,像睡著了一般撮抓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上摇锋,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天丹拯,我揣著相機(jī)與錄音站超,去河邊找鬼。 笑死乖酬,一個胖子當(dāng)著我的面吹牛死相,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播咬像,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼算撮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了县昂?” 一聲冷哼從身側(cè)響起肮柜,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎七芭,沒想到半個月后素挽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡狸驳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年预明,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片耙箍。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡撰糠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出辩昆,到底是詐尸還是另有隱情阅酪,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布汁针,位于F島的核電站术辐,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏施无。R本人自食惡果不足惜辉词,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望猾骡。 院中可真熱鬧瑞躺,春花似錦、人聲如沸兴想。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嫂便。三九已至捞镰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背岸售。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工几迄, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人冰评。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像木羹,于是被迫代替她去往敵國和親甲雅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容

  • **2014真題Directions:Read the following text. Choose the be...
    又是夜半驚坐起閱讀 9,437評論 0 23
  • { "Unterminated string literal.": "未終止的字符串文本坑填。", "Identifi...
    栗子雨閱讀 7,862評論 0 3
  • "Unterminated string literal.": "未終止的字符串文本抛人。", "Identifier...
    兩個心閱讀 8,351評論 0 4
  • 空氣中彌漫著寒冷 太陽偷了懶躲在家里不想出門 清晨 街上人并不多 走進(jìn)一家名為 情人坊 的花店 推開門 看到一束紅...
    珂先生啊喂閱讀 317評論 0 0
  • 如果我是一只動物,我愿是一只小狗脐瑰,每天在主人跟前妖枚,享受主人的愛撫,平時懶洋洋地一躺苍在,打個滾绝页,不高興時可以嗯嗯地表達(dá)...
    今生要舍得閱讀 364評論 0 0