JavaScript
中的函数使用function
关键字,后跟一组参数以及函数体。例如:函数
function foo(arg0, arg1,...,arg) {
...
}
var foo = function () {
...
};
(function () {
...
})();
复制代码
在JavaScript
中有三种函数类型:函数声明,函数表达式和函数构造器建立的函数。下面分别介绍这三种函数类型。工具
函数声明由一系列的function
关键字组成,依次为:post
例如:学习
function foo(arg0, arg1,...,arg) {
var a = 1;
console.log(a);
}
复制代码
函数表达式和函数声明很是类似,依次为:ui
例如:spa
var foo = function () {
var b = 2;
console.log(b);
};
var foo = function bar() {
var b = 2;
console.log(b);
};
(function() {
var c = 3;
console.log(c);
})();
复制代码
能够经过Function
对象使用new
操做符建立一个构造函数。例如:debug
new Function('alert('hello'); alert('world');');
复制代码
这里重点学习函数声明和函数表达式。建立函数的最经常使用的两个方法是函数表达式和函数声明。调试
函数声明:code
function 函数名称 (参数:可选){ 函数体 }cdn
函数表达式:
function 函数名称(可选)(参数:可选){ 函数体 }
因此,建立一个函数若是不声明函数名称,它确定是表达式,可若是声明了函数名称的话,如何判断是函数声明仍是函数表达式呢?
区分函数声明和表达式最简单的方法是看 function
关键字出如今声明中的位 置(不单单是一行代码,而是整个声明中的位置)。若是 function
是声明中 的第一个词,那么就是一个函数声明,不然就是一个函数表达式。或者这么理解function foo(){}
是做为赋值表达式的一部分的话,那它就是一个函数表达式,若是function foo(){}
被包含在一个函数体内,或者位于程序的最顶部的话,那它就是一个函数声明。
例如:
function foo(){} // 声明,由于它是程序的一部分
var bar = function foo(){}; // 表达式,由于它是赋值表达式的一部分
new function bar(){}; // 表达式,由于它是new表达式
(function(){
function bar(){} // 声明,由于它是函数体的一部分
})();
(function foo(){}); // 表达式 包含在分组操做符内
复制代码
对于函数表达式,最熟悉的场景就是回调,例如:
setTimeout(function(){
console.log("hello world!");
},1000);
复制代码
这是一个匿名函数表达式,在平常开发和工具库中这种模式很常见。可是它也有几个缺点须要考虑。
例如:
具名函数
function foo(){
return bar();
}
function bar(){
return baz();
}
function baz(){
debugger;
}
foo(); //当调试器debugger的调用栈,栈中显示了baz,bar,foo。
// 这是一个自执行的函数,函数内部执行自身,递归
function self() {
self();
}
复制代码
匿名函数
function foo(){
return bar();
}
var bar = (function(){
return function(){
return baz();
};
})();
function baz(){
debugger;
}
foo();//当调试器debugger的调用栈,栈中显示了baz,(anonymous),foo。
// 这是一个自执行的匿名函数,由于没有标示名称
// 必须使用arguments.callee属性来执行本身
var self = function () {
arguments.callee(); //在严格模式下,ES5禁止使用 arguments.callee()。
};
复制代码
给函数表达式指定一个函数名,不会影响其功能,反而是一个比较好的实现方式,例如:
setTimeout(function handle(){
console.log("hello world!");
},1000);
复制代码
(function foo() {
var a = 1;
console.log(1);
})();
(function () { /* code */ } ()); // 推荐使用这个
(function () { /* code */ })(); // 可是这个也是能够用的
复制代码
因为函数被包含在一对 ( ) 括号内部,所以成为了一个表达式,经过在末尾加上另一个 ( ) 能够当即执行这个函数,好比(function foo(){ .. })()
。第一个 ( ) 将函数变成表 达式,第二个 ( ) 执行了这个函数。这种模式也叫当即执行函数表达式(IIFE)。
除了( ) 括号外,还有不少其余的方式也能让一个函数变成函数表达式,例如:
//&&,异或,逗号等操做符
true && function () { /* code */ } ();
1, function () { /* code */ } ();
//一元操做符号
!function () { /* code */ } ();
~function () { /* code */ } ();
-function () { /* code */ } ();
+function () { /* code */ } ();
复制代码
可是依然使用( ) 括号,括号内部原本指望的就是函数表达式,主要是为了方便开发人员阅读。
IIFE一些常见应用,例如:
var a = 1;
(function ( global ) {
var a = 2;
console.log( a ); // 2
console.log( global.a ); // 1
})( window );
console.log( a ); // 1
复制代码
var module = (function () {
var i = 0;
return {
get: function () {
return i;
},
set: function (val) {
i = val;
},
add: function () {
return ++i;
}
};
} ());
module.get(); // 0
module.set(1);
module.add(); // 1
module.i // undefined 由于i不是返回对象的属性
复制代码
这一节是对学习JavaScript做用域中的函数做用域的一个补充。这样把琐碎的知识串联起来,更容易造成体系。