感谢《JavaScript王者归来》作者月影,之前对闭包一点都不懂,看过他的书后,终于懂一点了。以下的例子是创建一个集合,这个集合可以指定数据类型,也可以不指定。另外一个each方法很有意思。
/** * 生成一个泛型的List集合 */ function ListClassFactory(type){ var data=[]; var ret = function(){ this.append.apply(this,arguments); } ret.base = Array; ret.prototype= new Object(); ret.prototype.append = function(){ for(var i=0; i< arguments.length; i++){ var element = arguments[i]; if(typeof type == 'undefined'){ data.push(element); continue; } if(typeof(element) == type || (typeof(type)=='function' && element instanceof type)){ data.push(element); continue; } throw new TypeError("you are about to add an unavailable type of element. The specified type is /'"+ type+"/'"); } } ret.prototype.toArray = function(){ return this.subarr.apply(this , [0,data.length]); } ret.prototype.count = function(){ return data.length; } ret.prototype.get = function(i){ return data[i]; } //最核心的方法,循环每个元素,作为函参的参数 //如果函参运行的返回值为false,这个返回值就不添加到新的集合中去 ret.prototype.each = function(closure){ var newListClass = ListClassFactory(ret.type); var newret = new newListClass(); if(typeof closure =='undefined') closure = function(x){return x;}; for(var i=0; i<data.length; i++){ var rval = closure.apply(this,[data[i]].concat(i)); if(rval || rval === 0) newret.append(rval); } return newret; } //求是否所有元素都符合函参的要求 ret.prototype.all = function(closure){ //alert(this.count()); return this.each.call(this,closure).count()==this.count(); } //求是否其中一个元素符合函参的要求 ret.prototype.any = function(closure){ return this.each.call(this, closure).count() > 0; } //求是否含有指定元素 ret.prototype.contain = function(el){ return this.any.call(this,function(x){return x == el;}); } //求元素下标 ret.prototype.indexOf = function(el){ var newList = this.each.call(this,function(x,i){ if(x == el) return i; return false; }); var firstElement = newList.get(0); return firstElement ? firstElement : -1 ; } //求子集 ret.prototype.subarr = function(start,end){ var newAry = []; for(var i=start; i<end; i++){ newAry[i] = data[i]; } return newAry; } return ret; }
<html> <head> <title>js test</title> <script type="text/javascript" src="ListClassFactory.js"></script> <script> <!-- function dwn(s){ document.write(s+"<br/>"); } function Student(name,age){ this.name=name; this.age= age; } Student.prototype.toString=function(){ return "my name is:"+this.name +"/rmy age is:"+this.age; } //创建数据类型的集合 var ListClass = ListClassFactory('number'); var list = new ListClass(1,2,3); dwn(list.toArray()); //循环集合每个元素,各元素加自己所有位置下标 var newlist1 = list.each(function(x,i){return x+i;}); newlist1.append(9); dwn (newlist1.toArray()); //测试是否每个元素都大于0 dwn (list.all(function(x){ return x>0; })); //测试不传入函参的情况 dwn (list.all()); //测试是否其中一个元素值大于2 dwn (list.any(function(x){ return x > 2; })); //测试是否有一个元素值为9 dwn (list.contain(9)); //测试元素值为3的下标 dwn (list.indexOf(3)); //测试求子集 dwn(list.subarr(0,2)); /* //测试function类型,并混一个非function类型的元素。抛异常仍正常。 var ListClass = ListClassFactory(Student); var listObj = new ListClass(new Student("1",1),1); dwn(listObj.toArray()); */ --> </script> </head> <body> </body> </html>