JavaScript高级程序设计
第七章 函数表达式
- 7.1 递归
- 7.2 闭包
- 7.2.1 闭包与变量
- 7.2.2 关于this对象
- 7.2.3 内存泄漏
- 7.3 模仿块级作用域
- 7.4 私有变量
- 7.4.1 静态私有变量
- 7.4.2 模块模式
- 7.4.3 增强的模块模式
- 7.5 小结
定义函数:
- 函数声明
function functionName(arg0, arg1, arg2){
//函数体
}
- 函数表达式
var functionName = function(arg0, arg1, arg2){
//函数体
};
匿名函数(拉姆达函数): 匿名创建一个函数并将它赋值给变量functionName
function关键字后面没有标识符
name属性是空字符串
7.1 递归
递归函数: 一个函数通过名字调用自身
用arguments.callee实现对函数的递归调用:
function factorial(num){
if (num <=1){
return 1;
} else {
return num * arguments.callee(num-1);
}
}
在严格模式下使用命名函数表达式实现对函数的递归调用:
var factorial = (function f(num) {
if (num <=1){
return 1;
} else {
return num * f(num-1);
}
});
7.2 闭包
定义: 有权访问另一个函数作用域中的变量的函数
创建: 在一个函数内部创建另一个函数
原理:
- 在后台执行环境中,闭包的作用域链包含着它自己的作用域、包含函数的作用域和全局作用域
- 通常,函数的作用域及其所有变量都会在函数执行结束后被销毁
- 但是,当函数返回了一个闭包时,这个函数的作用域将会直在内存中保存到闭包不存在为止
7.3 模仿块级作用域
用作块级作用域(私有作用域)的匿名函数语法:
(function(){
//这里是块级作用域
})();
无论在什么地方,只要临时需要一些变量,就可以使用私有作用域
function outputNumbers (count){
(function() {
for (var i=0; i < count; i++){
alert(i);
}
})();
alert(i) ; //导致一个错误!
}
这个outputNumbers()函数中,在for循环外部插入了一个私有作用域。
在匿名函数中定义的任何变量,都会在执行结束时被销毁。
因此,变量i只能在循环中使用,使用后即被销毁。而在私有作用域中能够访问变量count,是因为这个匿名函数是一个闭包,它能够访问包含作用城中的所有变量。
这种技术经常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数。
一般来说,应该尽量少向全局作用域中添加变量和函数。
7.4 私有变量
私有变量包括函数的参数、局部变量和在函数内部定义的其他函数
特权方法: 有权访问私有变量和私有函数的公有方法
创建:
- 在构造函数中定义特权方法
function MyObject(){
//私有变量和私有函数
var privateVariable = 10;
function privateFunction(){
return false;
}
//特权方法
this. publicMethod = function (){
privateVariable++;
return privateFunction();
};
}
这个模式在构造函数内部定义了所有私有变量和函数。
然后,又继续创建了能够访问这些私有成员的特权方法。
能够在构造函数中定义特权方法,是因为特权方法作为闭包有权访问在构造函数中定义的所有变量和函数。
- 在私有作用域中定义私有变量或函数
(function() {
//私有变量和私有函数
var privateVariable = 10;
function privateFunction() {
return false;
}
//构造函数
MyObject = function() {
};
//公有/特权方法
Myobject .prototype .publicMethod = function(){
privateVariable++;
return privateFunction();
};
}) ();
区别:私有变量和函数是由实例共享的