匿名函数就是没有名字的函数,有时候也称为拉姆达(lambda)函数。
function functionName(){};
这是一个函数声明
在代码执行以前被加载到作用域中
var functionName = function(){};
这是一个函数表达式
在代码执行到那一行时才会有定义
7.1 递归
arguments.callee是一个指向正在执行的函数的指针,可以实现函数的递归调用
function factorial(num){
if(num <= 1){
return 1;
} else {
return num * arguments.callee(num - 1);
}
}
var anotherFactorial = factorial;
factorial = null;
alert(anotherFactorial(4)); // output 24
7.2 闭包
闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。
function fn(propertyName){
return function(object1){
var v1 = object1[propertyName]; //访问了外部变量propertyName变量
}
}
由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存,过度使用闭包可能会导致内存占用过多。所以建议只是在绝对必要时再考虑使用闭包。
7.2.1 闭包与变量
function createFunctions(){
var result = [];
for(var i=0; i<10; i++){
result[i] = function(num){
return function(){
return num;
}
}(i);
}
}
var funcs = createFunctions();
for(var i=0; i<funcs.length; i++){
document.write(funcs[i] + ‘<br />’); //output 0,1,2,3…9
}
7.2.2 this对象
this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象。不过,匿名函数的执行环境具有全局性,因此对象通常指向window.
7.2.3 内存泄漏
如果闭包的作用域中保存着一个HTML元素,那么就意味着该元素无法被销毁。
function assignHandler(){
var element = document.getElementById(‘someElement’);
var id = element.id;
element.onclick = function(){
alert(id);
};
element = null; //变量设置为null,才能解除对DOM对象的引用,顺利减少引用数,确保正常回收其占用的内存
}
7.3 模仿块级作用域
匿名函数可以用来模仿块级作用域:
(function(){
//这里是块级作用域
})();
将函数声明包含在一对圆括号中,表示它实际上是一个函数表达式,而紧随其后的另一对圆括号会立即调用这个函数。
相当于:
var someFunction = function(){};
someFunction();
function(){}();
这一段会导致语法错误,因为JavaScript将function关键字当作一个函数声明的开始,而函数声明后面不能跟圆括号。然而,函数表达式的后面可以跟圆括号。要将函数声明转换成函数表达式,只要加上一对括号即可。
7.4 私有变量
任何在函数中定义的变量,都可以认为是私有变量。因为在函数外部不能访问这些变量。
把有权访问私有变量和私有函数的公有方法叫特权方法。
function MyObject(){
//私有变量
var privateVariable = 10;
function privateFunction(){
return false;
}
//特权方法
this.publicMethod = function(){
privateVariable ++;
return privateFunction();
}
}
7.4.1 静态私有变量
(function(){
var privateVariable = 10;
function privateFunction(){
}
Myobject = function(){
}
//公有/特权方法
Myobject.prototype.publicMethod = function(){
privateVariable ++;
return privateFunction();
}
})()
这个模式创建了一个私有作用域,并在其中封装了一个构造函数及相应的方法。
7.4.2 模块模式
单例创建私有变量和特权方法。所谓单例就是只有一个实例的对象。简单的语法如下:
var singleton = {
name: value,
method: function(){
//这里是方法
}
}
还可以添加私有变量和特权方法
var singleton = function(){
//私有变量和私有函数
var privateVariable = 10;
function privateFunction(){}
//特权/公有方法和属性
return {
publicProperty: true,
publicMethod: function(){
privateVariable++;
return privateFunction();
}
}
}
这个模式返回了一个匿名函数,在函数内部,定义私有变量和函数,然后将一个对象字面量作为函数的值返回。返回的对象字面量中只包含可以公开的属性和方法。
7.4.3 增强的模块模式
var singleton = function(){
//私有变量和私有函数
var privateVariable = 10;
function privateFunction(){
return false;
}
//创建对象
var object = new CustomType();
//添加特权/仅有属性和方法
object.publicProperty = true;
object.publicMethod = function(){
privateVariable++;
return privateFunction();
};
return object;
}