有点蒙蔽,总结一哈,也不知道对不对。。
闭包:有权访问另一个函数作用域中的变量的函数。
由一下俩特性:
1. 内部函数可以用外层的变量(作用链current > out > outout > outoutout ...)
2. 函数名是一个指针,所以可以很多名字指向一个函数体
组合改编(把内部函数作为返回值)一下成为最简单的闭包:
function outFunc(){ var woshiwaimiandebianliang = "a"; return inFunc; //千万~!不能写括号,写括号代表调用,只一个名字代表指向的函数体,返回的是函数体 function inFunc(){ woshiwaimiandebianliang = "我在里面,我可以用外面的变量"; } /* 可以省略内部函数的函数名 return function(){ woshiwaimiandebianliang = "我在里面,我可以用外面的变量"; } */ } var wokeyizhixiangshangmiannagehanshu = outFunc();因为闭包的特性(外层函数结束,也可以通过调用内层函数访问外层函数的变量),因此总会保留一个闭包函数对该对象的引用,即element的引用永远不会为0;
解决:
function assignHandler(){ var element = document.getElementById("someElement"); var id = element.id; element.onclick = function(){ alert(id); }; element = null; }用一个变量代替对外层对象的使用。element=null是因为:闭包会引用包含函数的整个活动对象(即使闭包函数没直接用element,也会保存),所以要设置为null.形式:
(function(){
//这里是块级作用域;<— 函数表达式后可跟(),运行;function被当成函数声明的开始,函数声明不可以跟()运行;所以用括号包裹成为函数表达式。
})();
作用:限制向全局作用域中添加过多的变量和函数;也可以用来减少闭包占用的内存问题
可以通过闭包创建用于访问私有变量/函数的共有方法——特权方法
function Person(name){ //私有变量和私有函数 var privateVariable = 10; function think(){ return "Person can think"; } //特权方法 this.setName = function(value){ name = value; }; this.getName = function(){ return name; }; } var person = new Person("hhh"); alert(person.getName()); //hhh person.setName("lll"); alert(person.getName()); //lll 缺点:必须使用构造函数模式
为单例创建私有变量和特权方法
function BaseComponent(){ //code } function OtherComponent(){ //code } var application = function(){ //私有成员变量 var components = new Array(); //初始化 components.push(new BaseComponent()); //公有 return{ getComponentCount : function(){ return components.length; }, registerComponent : function(component){ //维护私有变量 if(typeof component == "object"){ components.push(component); } } }; }(); 对单例进行初始化又需要维护私有变量。
适用于单例必须是某种类型的实例,同时还必须添加某些属性和(或)方法对其加以增强。
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; }();
