让操作javascript对象数组像.net lamda表达式一样
随着web应用程序的富客户端化、ajax的广泛使用及复杂的前端业务逻辑。对js对象数组、json数组的各种操作越来越多、越来越复杂。如果处理js对象数组能够像.net lamda一样方便、灵活,这将是一件很美好的事。
由于最近项目中对json对象数组的操作很多,为了方便开发、使用方便、提高代码的重用性,就对js Array扩展一些类似 .net lamda一样的方法。
我们来先看一个例子
我们知道现在用json作为数据传输方式的太多了,如果返回的json数据如下:
var jsonData=[{Id:1,Name:"name1",Age:11},
{Id:2,Name:"name2",Age:22},
{Id:3,Name:"name3",Age:33},
{Id:4,Name:"name4",Age:22},
{Id:5,Name:"name5",Age:32},
{Id:6,Name:"name6",Age:22}];
需求一、查找Age大于22岁的我们应该怎么做?当然我们自然为然的会想到如下的做法,代码如下:
function queryData(list) { var arr=[]; for(var i=0;i<list.length;i++) { var item=list[i]; if(item.Age>22) { arr.push(item); } } return arr; }
这样做就实现了我们想要的功能,但是如果又有一个需求
需求二、查找 Age小于22岁呢?当然也能实现,代码如下:
function queryData2(list) { var arr=[]; for(var i=0;i<list.length;i++) { var item=list[i]; if(item.Age<22) { arr.push(item); } } return arr; }
这时我们有没有发现只是一个查询判断逻辑的不同我们就又要写一个方法并且写着重复的 for循环,这样重复的代码太令人讨厌了(不好的地方就不一一说了)。再想想.net中对数据的各种不同逻辑的查找一个lamda表达式就解决了,js中是否能像.net lamda表达式一样解决不同逻辑的查询、能不能把重复的代码提取出来呢?
这当然可以了我们都应该知道.net lamda的主要核心就是利用匿名函数。刚才需求一、需求二查找数据时主要的不同是查询逻辑的判断,那么我们把查询时逻辑判断那段代码用匿名函数传进方法里,重复的for循环放到函数里不就能实现了我们想要的吗?代码如下:
function findData(list,fn) { var arr=[]; for(var i=0;i<list.length;i++) { var item=list[i]; if(fn(item)) { arr.push(item); } } return arr; }
如上代码,它不仅仅能满足需求一,需求二,而且还能满足查找Age等于22的数据,Age大于30等等各种需求。
上面的findData函数已经能满足各种是查询要求了,我们还可以对其优化让它更好用,更类似lamda表达式,代码如下:
Array.prototype.FindAll = function (fn) { for (var i = 0, len = this.length; i < len; i++) { var o = this[i]; if (fn.call(o, o)) { arr.push(o); } } return arr; };
这样我们调用函数时就可以这样用了:
var data=jsonData.FindAll(function(){return this.Age>22;});//利用call调用函数,不知道的可以查找了解
或
var data=jsonData.FindAll(function(m){return m.Age>22;});
是不是类似我们的lamda表达式的用法,而且代码很简单、优雅、也能满足各种查询要求
以查询为例对Array扩展出FindAll函数,当然我们也可以根据自己的需要扩展出自己要用到的函数。
下面是项目中用到的几个函数的扩展,注视已经很清楚了,大家慢慢看吧!
代码如下:
/* 函数:向对象数组中添加对象数组 参数:对象数组或单个对象 返回:返回添加后的对象数组 调用方式:var result=list.Add({Id:66,Age:66}); var result=list.Add([{Id:66,Age:66},{Id:77,Age:77}]); */ if (Array.prototype.Add && typeof Array.prototype.Add == "function") { alert("Array.prototype.Add 函数已存在,不能再次添加"); } else { Array.prototype.Add = function (obj) { obj instanceof Array ? this.push.apply(this, obj) : this.push.call(this, obj); return this; }; } /* 函数:根据条件从对象数组中获取一个对象 参数:匿名函数,字段,值 返回:查找到的对象,如果没有查找到返回null 调用方式:var result=list.FindOne(function (o) { return o.Age>30; }); var result=list.FindOne(function () { return this.Age>30; }); var result=list.FindOne("Age",22); */ if (Array.prototype.FindOne && typeof Array.prototype.FindOne == "function") { alert("Array.prototype.FindOne 函数已存在,不能再次添加"); } else { Array.prototype.FindOne = function (property, value) { var fn = typeof property === "function" ? property : function () { return this[property] == value; }; for (var i = 0, len = this.length; i < len; i++) { var o = this[i]; if (fn.call(o, o)) { return o; } } return null; }; } /* 函数:根据条件查询对象数组 参数:匿名函数;字段,值 返回:查找到的对象数组 调用方式:var result=list.FindAll(function (m) { return m.Age>30; }); var result=list.FindAll(function () { return this.Age>30; }); var result=list.FindAll("Age",22); */ if (Array.prototype.FindAll && typeof Array.prototype.FindAll == "function") { alert("Array.prototype.FindAll 函数已存在,不能再次添加"); } else { Array.prototype.FindAll = function (property, value) { var arr = [], fn = typeof property === "function" ? property : function () { return this[property] == value; }; for (var i = 0, len = this.length; i < len; i++) { var o = this[i]; if (fn.call(o, o)) { arr.push(o); } } return arr; }; } /* 函数:将对象数组中的每个对象投影到新的对象中 参数:匿名函数 返回:返回新的对象数组 调用方式:var result=list.Select(function () { return {Id=this.Id,Age:this.Age}; }); var result=list.Select(function (m) { return {Id=m.Id,Age:m.Age}; }); var result=list.Select(function () { return this.Id==2?{Id=m.Id,Age:m.Age}:null; }); */ if (Array.prototype.Select && typeof Array.prototype.Select == "function") { alert("Array.prototype.Select 函数已存在,不能再次添加"); } else { Array.prototype.Select = function(fn) { var arr = []; for (var i = 0, len = this.length; i < len; i++) { var o = this[i]; var one = fn.call(o, o); if (!Em.IsNull(one)) { arr.push(one); } } return arr; }; } /* 函数:从对象数组中删除符合条件的对象 参数:匿名函数;字段,值 返回:返回删除后的对象数组 调用方式:var result=list.Del(function (m) { return m.Age>30; }); var result=list.Del(function () { return this.Age>30; }); var result=list.Del("Age",22); */ if (Array.prototype.Del && typeof Array.prototype.Del == "function") { alert("Array.prototype.Del 函数已存在,不能再次添加"); } else { Array.prototype.Del = function (property, value) { var fn = typeof property === "function" ? property : function () { return this[property] == value; }; for (var i = 0; i < this.length; i++) { var o = this[i]; if (fn.call(o, o)) { this.splice(i, 1); i--; } } return this; }; } /* 函数:计算数组对象中某列的和,如果是简单数组直接把数组每项是数字的相加 参数:求各的对象列名 调用方式:var sumValue=ArrayData.Sum("Age"); var sumValue=ArrayData.Sum(); 返回:求和的结果 */ if (Array.prototype.Sum && typeof Array.prototype.Sum == "function") { alert("Array.prototype.Sum 函数已存在,不能再次添加"); } else { Array.prototype.Sum = function(coloumName) { var sumValue = 0, i = this.length; var fn = coloumName ? function() {return isNaN(this[coloumName]) ? 0:this[coloumName];} : function() {return isNaN(this) ?0:this;}; for (; i--;) { var o = this[i]; sumValue+=Number(fn.call(o, o)); } return sumValue; }; }
以上就是主要的内容,当然最重要的是大家有什么好的、不好的想法与意见,
可以尽情的拍砖,以之于能够有更高效、优雅的实现方式!