函数定义方式之函数直接量函数定义的第三种方式是函数直接量,ECMAScript v3 定义了函数直接量,JavaScript 1.2 实现了它。函数直接量是一个表达式,它即可以定义一个匿名函数,也可以定义一个带函数名的函数:
清单 4.1
2
3
4
5
6
7
8
9
10
| var sum = function(a, b){
return a+b;
}
var f = function fact(x){
if(x<= 1){
return 1;
}else{
return x * fact(x-1);
}
}
|
函数直接量和使用 Function()构造函数来创建函数的方法非常相似,因为两种方法都是通过 JavaScript 的表达式创建的,而不是由语句创建的;所以使用他们的方式也更灵活,尤其是那些只使用一次,而且不需要命名的函数。比如把它传递给其他的函数:
清单 5.1
2
3
4
5
6
| var desc = function(a, b){
return a<b;
}
var a = [2,1,4,3,6,7];
a.sort(desc);// 把desc函数当作参数传给数组的sort方法
alert(a.join(','))// 输出7,6,4,3,2,1
|
区别三种方式的区别,可以从作用域、效率以及加载顺序来区分。首先,从作用域上来说,函数声明式和函数直接量使用的是局部变量,而 Function()构造函数却是全局变量:
清单 6.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| var y = 'global';
function a(){
var y = 'local a';
return y;
}
alert(a());//显示'local a'
var b = function(){
var y = 'local b';
return y;
}
alert(b()) //显示'local b'
function c(){
var y = 'local c';
return new Function('return y');
}
alert(c()());//显示'global',因为Function()返回的是全局变量y,而不是函数体内的局部变量。
|
其次是执行效率上来说,Function()构造函数的效率要低于其他两种方式,尤其是在循环体中,因为构造函数每执行一次都要重新编译,并且生成新的函数对象:
清单 7.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| var start = new Date().getTime();
for(var i=0; i<10000000; i++){
var f = new Function(‘a’, ‘b’, ‘return a+b’);
f(i, i+1);
}
var end = new Date().getTime();
alert(end-start);//结果显示~11s
start = new Date().getTime();
var f = function(a, b){
return a+b;
}
for(var i=0; i<10000000; i++){
f(i, i+1);
}
end = new Date().getTime();
alert(end-start);//结果显示~7s
|
由此可见,在循环体中,函数直接量的执行效率是 Function()构造函数的 0.6 倍。所以在 Web 开发中,为了加快网页加载速度,提高用户体验,我们不建议选择 Function ()构造函数方式来定义函数。
最后是加载顺序,function 方式(即函数声明式)是在 JavaScript 编译的时候就加载到作用域中,而其他两种方式则是在代码执行的时候加载,如果在定义之前调用它,则会返回 undefined:
清单 8.1
2
3
4
5
6
7
8
9
10
11
12
| <code>alert (typeof f)//显示 function
alert (typeof c)//显示 undefined,因为 c 还没有定义
alert (typeof d)//显示 undefined,因为 d 还没有定义
function f(){
return true
}
var c = function(){
return true;
}
alert(typeof c);//显示 function,上面已经定义,所以不是 undefined
var d = new Function(‘return true’)
alert(typeof d);//显示 function,上面已经定义,所以不是 undefined</code>
|
|