<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>函数声明和函数表达式</title>
<script src="../unitl/test.js"></script>
<style>
#results li.pass {color:green;}
#results li.fail {color:red;}
</style>
</head>
<body>
<ul id="results"></ul>
</body>
<script>
//独立的函数声明
function myFunctionDeclaration() {
//内部函数声明
function innerFunction(){}
}
// 函数表达式作为变量声明赋值语句中的一部分
var myFunc = function(){};
//函数表达式作为一次函数调用中的参数。
myFunc = (function() {
return function(){};
});
//作为函数调用的一部分,命名函数表达式会被立即调用。
(function namedFunctionExpression() {})();
//函数表达式可以作为医院操作符的参数立即调用
+function(){}();
-function(){}();
!function(){}();
-function(){}();
</script>
</html>
示例代码的开头是标准函数声明,其包含一个内部函数声明:
function myFunctionDeclaration() {
function innerFunction() {}
}
从这个示例中你能够看到,函数声明是如何作为JavaScript代码中的独立表达式的,但它也能够包含在其他函数体内。与之比较的是函数表达式,它通常作为其他语句的一部分。
他们被放在表达式级别,作为变量声明(或者赋值)的右值,如:
var myFunc = function(){};
或其他作为另一个函数调用的参数或返回值。
myFunc(function() {
return function(){};
});
函数声明和函数表达式除了在代码中的位置不同以外,还有一个更重要的不同点是:
对于函数声明来说,函数名是强制性的,而对于函数表达式来说,函数名则完全是可选的。
函数声明具有函数名是以为它们是独立语句。一个函数的基本要求是它应该能够被调用,所以它必须具有一种被引用方式,于是唯一的方式就是通过它的名字。例如:
function hello() {
console.log("Hello World");
}
hello();
另外,函数表达式也是JavaScript表达式的一部分,所以也就具有了调用他们的替代方案。例如,如果一个函数表达式被赋值给一个变量,我们可以用该变量来调用函数。
var doNothing = function(){};
doNothing();
或者,如果它是另外一个函数的参数,我们可以在该函数通过相应的参数名来调用它。
function doSomething(action) {
action();
}
立即函数
当想进行函数调用时,我们需要使用能够求值得到函数的表达式,其后跟着一对函数调用括号,括号内包含参数。在最基本的函数调用中,我们把求值得到函数的标识符作为左值。如上图,
不过用于被括号调用的表达式不必只是一个简单的标识符,它也可以是任何能够求值得到函数的表达式。例如,指定一个求值得到函数表达式的最简单是使用函数表达式。
如图中右图所示,我们首先创建一个函数,然后立即调用这个新创建的函数。这种函数被叫作立即调用函数表达式(IIFE),又或者简称为立即函数。
这一特性能够模拟JavaScript中的模块化,故可以说它是JavaScript开发中的重要概念。
加括号的函数表达式
- 立即调用的函数表达式方式:函数表达式被包裹在一对括号内。为什么这样做呢? 其原因是纯语法层面的。JavaScript解析必须能够轻易区分函数声明和函数表达式之间的区别。
如果去掉包裹函数表达式的括号,把立即调用作为一个独立语句function(){}(3),javaScript开始解析时便会结束,因为这个独立语句以function开头,那么解析器就会认为它在处理一个函数申明。
每个函数声明必须有一个名字(然而这里并没有指定名字)所以程序执行到这里会报错。为了避免错误,函数表达式要放在括号内。为JavaScript解析器指明它正在处理一个函数表达式而不是语句。 - 还有一种相对简单的替代方案(function(){}(3))也能达到相同目标(然而这种方案有些奇怪,故不常使用)。把立即函数的定义和调用都放在括号内同样可以为JavaScript解析器指名它正在处理函数表达式。
在本例最后4个表达式都是立即调用表达式主题的4个不同版本,在JavaScript库中会经常简单这几个形式:
+function(){}();
-function(){}();
!function(){}();
~function(){}();
不同有加括号的方式区分函数表达式和函数声明,这里我们使用一元操作符+-!~,这种做法也是用于向javascript引擎指明它处理的是表达式,而不是语句。从计算机的角度来讲,注意应用一元操作符得到的结果没有存储到任何
地方并不重要,只有调用IIFE(立即函数)才重要。