函数表达式
递归
-
递归函数是在一个函数通过名字调用自身的情况下构成的
function factrial(num){ if(num<=1){ return 1; }else { return num*factrial(num-1); } }
-
argument.callee是一个指向正在执行的函数的指针,因此可以用它来实现对函数的递归调用
function factorial(num){ if(num<=1){ return 1; }else { return num*argument.callee(num-1) } }
-
严格模式下不能通过脚本访问argument.callee,访问这个属性会导致错误,不过可以使用命名函数表达式类达成相同的结果
var factorial=(function f(num){ if(num<=1){ return 1; }else { return num*f(num-1); } })
闭包
-
闭包是指有权访问另一个函数作用域中的变量的函数
function compare(value1,value2){ if(value1<value2){ return -1; }else if(value1>value2){ return 1; }else { return 0; } } var result=compare(5,10)
//创建函数 var compareNames = createComparisonFunction("name"); //调用函数 var result = compareNames({ name: "Nicholas" }, { name: "Greg" }); //解除对匿名函数的引用(以便释放内存) compareNames = null;
闭包与变量
-
闭包只能取得包含函数中任何变量的最后一个值,i值为10
function creatFunctions(){ var result=new Array(); for(var i=0;i<10;i++){ result[i]=function(){ return i; }; }; return result; }
-
通过匿名函数强制让闭包的行为符合预期
function createFuntion(){ var result=new Array(); for(var i=0;i<10;i++){ result[i]=function(num){ return function(){ return num; }; }(i); } return result; }
关于this对象
- 匿名函数的执行环境具有全局性,因此其this对象通常指向window
-
把外部作用域中的this对象保存在一个闭包能够访问到的变量里,就可以了让闭包访问这个对象了
var name="The Window"; var object={ name:"My Object", getNameFunc:function(){ var that=this; return function(){ return that.name }; } }; alert(object.getNameFunc()());//"My Object"
- 定义米明函数之前,我们把this对象赋值给了一个名叫that的变量,而在定义了这个闭包之后,闭包也可以访问这个变量,因此它是我们在包含函数中特意声明的一个变量,即使在函数返回之后,that也仍然引用这object
内存泄漏
-
如果闭包作用域中保存着一个HTML元素,那么久意味着该元素将无法被销毁
function assignHandler(){ var element=docunemt.getElementById("someElement"); element.onclick=function(){ alert(element.id) } }
-
以上代码段中的element占用的内存永远不会被回收
function assignHandler(){ var element=document.getElementById("someElement"); var id=element.id; element.onclick=function(){ alert(id); } element=null; }
模仿块级作用域
function outputNumbers(count){
for(var i=0;i<count;i++){
alert(i);
}
var i;//重新声明变量
alert(i);//计数
}
-
JavaScript从来不会告诉你是否多次声明了同一个变量,遇到这种情况,只会对后续的声明视而不见,不过会执行后续声明中的变量初始化。匿名函数可以用来模仿块级作用域来避免这个问题
(function(){ //这里是块级作用域 })()
-
代码定义并立即调用了一个匿名函数,将函数声明包含在一对圆括号中,表示它实际上是一个函数表达式,而紧随其后的另一对圆括号会立即调用这个函数。
function outputNumbers(count){ (function(){ for(var i=0;i<count;i++){ alert(i) } })(); alert(i);//导致一个错误 }
- 这种技术经常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数。一般来说,我们应该尽量少向全局作用域中添加变量和函数
私有变量
- JavaScript中灭有私有成员的概念,所以对象属性都是共有的。任何在函数中定义的变量,都可以认为是私有变量,因为不能在函数的外部访问这些变量,私有变量包括函数的参数、局部变量和在函数内部定义的其他函数。
- 如果在函数内部创建一个闭包,那么闭包通过自己的作用域链也可以访问函数内的变量
静态私有变量
(funciton(){
//私有变量和私有函数
var privateVariable=10;
function privateFunction(){
return false;
}
//构造函数
MyObject=function(){}
//公有/特权方法
MyObject.prototype.publicMethod=function(){
privateVariable++;
return privateFunciton();
}
})();
- 在私有作用域中,首先定义了私有变量和私有函数,然后又定义了构造函数及其公有方法
模块模式
-
模块模式是为单例创建私有变量和特权方法。单例指的就是只有一个实例的对象。按照惯例,JavaScript是以字面量的方式来创建单例对象的
var singleton={ name:value, method:function(){ //这里是代码方法 } }
-
模块模式通过为单例添加私有变量和特权的方法能够使其得到增强
var singleton=function(){ //私有变量和私有函数 var privateVariable=10; funciton privateFunction(){ return false; } //特权/公有方法和属性 return { publicProperty:true, publicMethod:function(){ privateVariable++; return privateFunction(); } }; }();
增强的模块模式
var application = function(){
//私有变量和函数
var components = new Array();
//初始化
components.push(new BaseComponent());
//创建 application 的一个局部副本
var app = new BaseComponent();
//公共接口
app.getComponentCount = function(){
return components.length;
};
app.registerComponent = function(component){
if (typeof component == "object"){
components.push(component);
}
};
//返回这个副本/
return app;
}();
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。