关于javascript中的function declaration 和 function expression

最近在看《Javascript for Web Developers》,虽然在VT项目中的一个小demo中担任了前端工程师,开始了javascript之路,但是真正来看javascript高级语法的时候还是懵逼了。

function declaration 和 function expression在讲function的时候貌似讲到了,当时看的时候也是以为自己记得了,再看块作用域的时候还是不太清楚。于是在网上找到了一篇文章,看完做个记录也好。



什么是 javascript declaration

Function declaration定义了一个命名的函数变量,但是并没有变量赋值(without requiring variable assignment.)。 Function declration必须作为一个单独的构造器出现,而不能被放在no-function的块中。

可以简单地这么想,function declaration 就想variable declaration的兄弟一样,只是变量声明首先写的是var, 而函数声明必须以function开头。

ECMA5 定义的语法是这样的: function Identifier(FormalParameterListopt) {FunctionBody}

function bar() {return 3;}

bar(); //3

bar; // function


什么是function expression?

Function Expression定义了一个函数,使它作为一个更大的expression语法的一部分(一般是变量赋值)。 通过Function Expression定义的函数可以是匿名的, 不需要以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(); 语句之前了,相当于重新定义了bar, 然后在invoke了bar(), 因此返回值为8.

我们按照习惯,总觉得return之后的代码是执行不到的?

在Javascript的执行过程中有一个Context和process。 Context被分为lexical environment, variable environment 和 this binding。 declartions在进入执行域时是在variable中的,与statement不一样,因此和它们的执行流程不一样。

案例二

但是在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.)

因此该案例的实际执行顺序如下

//**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.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容