将一段函数表达式存储在一个变量中。函数表达式是一种可以用表达式(而不是语句)声明的未命名函数,也称为匿名函数(之前我们定义的函数称为命名函数,或函数语句)。
区别类 | 函数表达式 | 函数语句 |
---|---|---|
引用 | 只能是在创建后才能被引用,且必须按照代码编写的顺序。 | 无论该函数是在定义之前或定义之后都可以被脚本引用 |
函数表达式实际是作为一组语句的封装标示 | 可以被作为另一些函数或方法的参数 | |
内存管理和垃圾回收方面 | 不像函数语句那样独立存在,当把函数表达式赋给一个变量时,就会在代码中创建对该函数表达式的唯一引用。如果该函数表达式所附加到的变量(也可以作为数组元素或者属性的值)不再可用,那么就无法再访问该函数表达式,例如,让函数表达式所附着的变量等于 | |
null (如果是作为数组元素或者属性的值,那么使用 delete 删除),那么其后就再也无法调用函数了 | 函数语句则不同,它是以对象的形式独立存在的,无法删除,但如果将函数语句附加到变量、数组元素或者属性,就可以让变量等于 null ,或者使用 | |
delete 删除数组元素或者属性,但该函数仍将存在,只是变量不可再用来调用函数 |
如果不是有特殊的用途(例如用于定义对象的方法),则不推荐使用函数表达式,因为函数语句相比起来更容易阅读和理解。与函数表达式相比,函数语句使代码更为简洁而且不容易引起混淆,因为函数表达式既需要 var 关键字又需要 function 关键字。
但是,在某些情况下,函数表达式非常有用,一个常见用法就是将函数表达式用于那些使用一次后便丢弃的函数,这样有利于内存管理。另一个用法就是向 prototype 属性附加函数以实现对象方法的定义,这个用法在 JavaScript 面向对象编程时最常见。
由于函数是一个封闭的作用域范围,并且可以嵌套函数,所以可以使用这种匿名自执行函数来实现封装自己的所有函数和变量,从而避免来自多个开发者的多个函数相互冲突,并且,由于它们位于同一个函数中,所以可以互相引用(请参照闭包原理)。
由于外部无法引用函数内部的变量,因此在执行完后很快就会被释放,关键是这种机制不会污染全局对象。这同时也相当于定义了一个命名空间,来自不同的开发者的功能位于自己的命名空间内。
那么如何访问匿名自执行函数里面的函数和对象呢?通常是为函数定义一个参数,该参数是一个对象,在里面的函数或变量前加上一个对该对象的引用,这样该函数或变量就成为该对象的方法或属性了。
例如下面的代码,首先定义一个对象,然后将该对象作为匿名自执行函数的参数传进去:
var o = new Object();
(function (_obj) {
_obj.privateMethod = function () {
return '一些数据或者变量 ';
};
})(o);
alert(o.privateMethod());
最常用到的是将全局对象 window 作为参数传进去,这样函数或变量就成为全局函数和变量了。
很多的库函数都是用了这种匿名自定义函数定义,例如 jQuery ,整个库定义都位于匿名自执行函数中,并传递 window 作为参数:
(function (window, undefined) {
// jQuery 定义
})(window);