感谢《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>