- 首先要明白一点,闭包比较消耗资源。看下面这个函数:
1 function createFunctions(){ 2 var arr=new Array(); 3 for(var i=0;i<10;i++){ 4 arr[i]=function(){ 5 return i; 6 }; 7 } 8 return arr; 9 } 10 var a=createFunctions(); 11 console.log(a);
这个函数的意图目的是为了返回一个数组,数组有十个整数,分别从0-10。但是运行后结果为: [ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ],生成的全部都是f对象实例。如果想要生成意图中的结果,只需要:
1 function createFunctions(){ 2 var arr=new Array(); 3 for(var i=0;i<10;i++){ 4 arr[i]=function(){ 5 return i; 6 }(i); 7 } 8 return arr; 9 } 10 var a=createFunctions(); 11 console.log(a);
- this 对象的作用域和闭包
1 //this object 2 var name="window"; 3 var object={ 4 name:"object", 5 getName: function(){ 6 return function(){//return的为一个匿名的函数,而其作用域为全局 7 return this.name; 8 } 9 } 10 } 11 console.log(object.getName()());//the window
这里的返回式window,。表示this的调用者为全域的window。为什么在对象内声明了,却不显示object。因为返回的式匿名函数,作用域在全局,如果不显式声明,那么默认为全局作用域。改善的方法为:
1 var name="window"; 2 var object={ 3 name:"object", 4 getName: function(){ 5 var obj_this=this; 6 return function(){ 7 return obj_this.name; 8 } 9 } 10 } 11 console.log(object.getName()());//object
定义闭包前,this对象赋给obj_this,那么定义闭包后,即可调用object对象的name。
- 内存泄漏问题
1 function handler(){ 2 var elements=getDocumentsById("id"); 3 elements.onclick=function(){ 4 alert(elements.id) 5 } 6 }
这个函数的活动对象为elements,同时函数内部具有一个对这个elements的引用(因为匿名函数要求返回它的id),那么这个引用会占用内存,且无法消除。
1 function handler(){ 2 var elements=getDocumentsById("id"); 3 var id=elements.id 4 elements.onclick=function(){ 5 alert(id) 6 } 7 elements=null; 8 }
改变的方法也不难,只需要将elements的id赋给一个id副本,然后将elements这个引用置空即可。
- 块级作用域
如果想要将函数声明变成函数表达式,需要在函数外部加一个括号,再即刻调用才行,否则会报错。
1 (function (){ 2 alert('hi'); 3 })();
而内部alert部分为块级作用域
- 私有变量
任何在函数中定义的变量,都可以称作私有变量
1 //private variable 2 function myObject(){ 3 var privateVal=10; 4 function privateFunc(){ 5 return false; 6 } 7 this.publicFunc=function(){//previleged method 8 return privateFunc(); 9 } 10 }
myObject为函数对象,里面有一个私有的privateVal和一个私有函数privateFunc,同时通过特权方法:即调用闭包函数publicFunc来访问、修改和返回私有变量。
要记住特权函数的声明方式:
this.xxx=function(){......)
- 静态私有变量:
- 为什么需要静态私有变量?因为调用这个构造函数的时候,每个实例都会创建同样一组新的方法,例如var person=new function("Mike")的同时,会创建一组新的getName等方法,这样比较占内存,所以通过创建静态私有变量,让每个实例共享这些方法,会比较方便
- 如何创建静态私有变量?
1 //private static variable 2 (function(){ 3 var privateVal=10; 4 function privateFunc(){ 5 return false; 6 } 7 myObject=function(){};//不用var,使得myObjct这个构造函数可以在全局访问。 8 myObject.prototype.publicFunc=function(){ 9 privateVal++; 10 return privateFunc(); 11 } 12 })();
首先,创造一个私有作用域
接着,前半部分没什么变化,主要是后面两个步骤不同。分别为创建一个构造函数myObject,然后在其原型上定义一个共有变量,这样所有实例就会共享这个publicFunc方法。
这样,privateVal和privateFunc便由实例所共享,所有的实例通过原型上的publicFunc方法来访问私有变量。
- 模块模式
- 该模式使用单例方法,借助匿名函数实现。
1 //block mode 2 var singleton=function(){ 3 var privateVal=10; 4 function privateFunc(){ 5 return false; 6 } 7 return{ 8 publicProperty:true;//不用var声明,全局作用域 9 publicFunc:function(){ 10 privateVal++; 11 return privateFunc(); 12 } 13 } 14 }
2. 如果必须创建一个对象并以某些数据对其进行初始化,同时还要公开一些能够访问这些私有 数据的方法,那么就可以使用模块模式
浙公网安备 33010602011771号