日期:2014-05-16  浏览次数:20444 次

Javascript 的函数式对象(三)利用闭包模拟类的静态变量和方法

?

?? ? ?除了模拟类的私有变量和私有方法。闭包还可用来模拟类的静态变量和方法。

?

除了再次利用js的闭包特性,还需要借助js语法上的一些特点。看下面一段代码:

?

?

var MyNamespace = {}; // 定义命名空间

MyNamespace.TreeItem = (function(){
    
    //使用闭包产生的私有静态变量,不可被外部访问
    var numTreeItems = 0;
    
    //使用闭包产生的私有静态方法,不可被外部访问
    function counter(){
    	numTreeItems ++;
    	console.log("Created "+numTreeItems+" tree items!");
    }
    
    //该匿名函数的引用将被赋予MyNamespace.TreeItem
    return function(){
        //使用闭包产生的私有类变量,不可被外部访问
    	var label;

    	//可访问私有变量,也可被外部访问的方法
    	this.setLabel = function( newLabel ){
            label = newLabel;
    	}; 

    	this.getLabel = function(){
            return label;
    	};
        
        //该方法用来累计实例的数量
    	counter();
    }
})(); //在函数定义的末尾加上括号,表示该函数在定义后立即执行

//不可访问私有变量以及其它公共方法的静态公共方法
MyNamespace.TreeItem.clone = function(otherInstance){
	
};

MyNamespace.TreeItem.prototype = {
	
    // 不可访问私有变量,但可访问其它公共方法的公共方法
    print: function(){
        console.log(this.getLabel());
    }
};

var treeItem1 = new MyNamespace.TreeItem(); // print 1
var treeItem2 = new MyNamespace.TreeItem(); // print 2
?

?

?

执行上述代码后,浏览器控制台将会输出如下字符串:

?

?Created 1 tree items!

?Created 2 tree items!

?

之所以把上述一些js变量和函数称为“静态”,是借用了Java的提法。

?

这些“静态”变量和方法被保存在闭包中,在内存中是唯一的,

?

不会随着该函数副本的增加而增加。如果一个函数需要被实例化多次,

?

但其中的一些内部函数并不需要访问任何实例数据,从节省内存的角度考虑,

?

可采用上述构建静态函数的方法。js中的“静态”概念,有一点与Java不同:

?

如果上述TreeItem被设为null,即不再有引用指向它,那么它的闭包也将消失,

?

保存在闭包中的静态变量和方法,也将被垃圾回收器择机回收。

?

?

1 楼 bigbighead 2010-11-18  
哦,又学了一招
2 楼 bigbighead 2010-11-18  
请教博主一个问题:
从您文章中,我发现您提到的静态成员是私有的(外界不可访问)
使用JavaScript 闭包,是否可以定义 外界可访问的 成员呢?
3 楼 hbc8848 2010-11-18  
bigbighead 写道
请教博主一个问题:
从您文章中,我发现您提到的静态成员是私有的(外界不可访问)
使用JavaScript 闭包,是否可以定义 外界可访问的 成员呢?


外界如果想访问闭包中的变量,唯一的途径是通过定义一个getXXX()取值器方法.

在上例第15行开始的那个函数中,我们定义一个 getNumTreeItems(){ return numTreeItems;}

方法,外界就可以取到静态私有变量numTreeItems了,这样凡是能拿到TreeItem任意一个实例的对象都会知道一共有几个TreeItem的实例被创建出来。
4 楼 biyelei 2011-01-13  
      
5 楼 sdtm1016 2011-05-24  
请教博主一个问题:
var MyNamespace = {};
  
MyNamespace.TreeItem = (function()
{        
    var numTreeItems = 0;  
      
    function counter()
    {  
        numTreeItems ++;  
        console.log("Created "+numTreeItems+" tree items!");  
	//alert(numTreeItems);
    } 
        
    return counter;
})(); 
  
var treeItem1 = new MyNamespace.TreeItem(); 
var treeItem2 = new MyNamespace.TreeItem();
var treeItem3 = MyNamespace.TreeItem(); 
var treeItem4 = MyNamespace.TreeItem();


匿名闭包,在内存中是唯一的(是否是因为关联了匿名对象呢?),和非匿名闭包,不是唯一,具体的区别在哪里呢?
谢谢
6 楼 sdtm1016 2011-05-24  
http://www.iteye.com/problems/65721
看了他的提问,没想明白
7 楼 HeroCL 2011-05-24  
sdtm1016 写道