第七章:函数表达式
Tips: 内容为知识梳理
目录
定义函数有两种方式:
- 函数声明
function name(arg0,arg1,arg2){
//代码
}
- 用
函数名.name可以访问函数名 - 函数声明会被提升,前几章讲过,即执行其他代码前会先读取函数声明
- 函数表达式
var name =function(arg0,arg1,arg2){ //代码 };
- 这样创建的函数是匿名函数即没有名字
- 这个不会被提升
- 可以将函数作为值返回
1. 递归
- 和java跟c语言递归没啥区别。。。
- 用arguments.callee可替代当前函数,这是一个指向正在执行函数的指针,用于确保无论怎样调用函数都不会出问题
- 严格模式下不能使用arguments.callee
- 严格模式下,用命名函数表达式来达到相同效果
var factorial = (function f(num){
if (num <= 1){
return 1;
} else {
return num * f(num-1);
}
});
上面函数名为f,赋值给了factorial。
2. 闭包
- 闭包定义:指有权访问另一个函数作用域中变量的函数
- 其他的都是关于作用域链的内容,没什么好讲的(之前讲过)
- 过度使用闭包会导致内存占用过多
- 闭包与变量
- 闭包只能取得包含函数变量的最后一个值
此函数返回的数组都是10,因为闭包作用域链保存着包含函数的活动对象,它们引用的都是同一个i,当包含函数返回后,i等于10,所以数组都为10function ceee(){ var sum=new Array(); for(i=0;i<10;i++){ sum[i]=function(){ return i; }; } retuen sum; }
- 关于this对象
- 匿名函数的执行环境具有全局性,它的this通常指向window,比如:
上面代码的this指向window,因为对于最里面的函数的作用域链,它在搜索this时,逐层往上搜索,因为自己的活动对象中存在this,而这个this是指向全局的,所以不会再往上搜索包含函数的this(不知道这样说你理解没有,反正我是理解了),修改方法是把this先保存在一个变量中,再在闭包调用这个变量,此时的this就是指向包含函数var name="abc"; var ob=function(){ name:"fff", getname:function(){ return function(){ return this.name; }; } };
- 内存泄露
- 若闭包中包含一个HTML元素,那么该元素就无法被销毁
- 把变量设置为null就可以解除引用,确保正常回收内存
3. 模仿块级作用域
javascript无块级作用域概念,即在块语句中定义的变量其实也是存在于包含他的外部函数的作用域链中,而不是像java和c语言一样在块语句结束后就被销毁。
- javascript用匿名函数来模仿块级作用域,语法如下:
匿名函数即函数表达式后面可以跟圆括号表示立即调用,而函数声明即有名函数后面不可以跟圆括号(function(){ //这里是块级作用域 })(); - 这样,在块级作用域内就可以拥有自己的私有变量而不怕与外部变量名字冲突
4. 私有变量
- 在函数内定义的变量都是私有变量外部不能直接访问
- 在函数内有权访问函数的私有变量和私有函数的方法叫特权方法
- 有两种模式去定义特权方法
- 第一种是在构造模式中定义特权方法
这样就可以在外部通过访问meth这个函数属性来访问私有变量function mobj(){ var num=1;//私有变量 this.meth = function(){ return num; };//特权方法 } - 不过使用构造函数模式的缺点是每个实例都会创建同样一组新方法,前面讲过,用静态私有变量解决这个问题
1. 静态私有变量
用原型模式和匿名函数将私有变量变为所有实例共享,具体如下
(function (){
var name="abd";//私有变量
mbu = function(){};
mbu.prototype.publicmetho =function(){
return name;
};//在原型对象中设置属性
})();
上面代码首先是创建一个私有作用域,然后定义一个私有变量,再不使用var定义一个全局变量mbu,再对mbu的原型对象添加属性publicmetho
- 这样就可以通过访问全局变量来访问私有变量
- 不过由于是在原型对象中定义,所以所有实例对这个变量进行操作都会反映到其他实例上
2. 模块模式
为单例创建私有变量和特权方法,语法如下:
var single = function(){
var pria =20;//私有变量
return {
publicee :10;
publicmetho: function(){
return pria;
}//返回一个以字面量创建的对象
};
}();
上面代码返回了一个以字面量创建的对象,这个对象可以访问私有变量
- 这种模式在需要对单例进行初始化,同时又需要维护其私有变量时是非常有用的,这时就可以用模块模式
3. 增强的模块模式
增强模块模式即在返回对象前加入对其增强的代码,这种模式适合那些单例必须是某种类型的实例,同时还必须添加某些属性或方法对其增强的情况。