您现在的位置: 万盛学电脑网 >> 程序编程 >> 脚本专题 >> javascript >> 正文

Javascript实现Linq查询方式

作者:佚名    责任编辑:admin    更新时间:2022-06-22

Linq是.net平台一个重要的技术,全称Language Integrated Query。通过构建快速查询语句,可快速从数据库或集合中筛选数据集、以查询数据库相同的方式操作内存数据。

      在ECMAScript 5th以后的版本中,Javascript实现了有限的有限的Linq查询方式,包括forEach, every, some, filter, map, reduce and reduceRight.        首先需要说明,以上这些方法并不是跨浏览器的,对版本有相应的限制。我们知道Linq的对象需要实现Enumerable接口,本篇文章主要介绍使用JS模拟实现C# 中的Linq查询,包括 聚集查询、迭代查询、条件查询、构建Selector查询器等。   Javascript本质上并不支持类的继承,通过属性的继承可实现类的面向对象的功能,所以这也被认为是面向对象的一种方式,这就意味着可以使用它的属性构建更多面向对象的接口。例如Array,它是继承自Array.prototype 。如果更改了Array.prototype,那么基于这个属性继承的数组必然会变化。有了这些依据后开始构建我们的Linq功能。   举个例子,JS API不支持union方法,但支持concat方法合并数据。   Array.prototype.union 先来看看一个.NET下的简单查询方式     var someArray = new int[] { 1, 2, 3, 4 }; var otherArray = someArray.Select(t => t * 2);    在C#下使用查询数据时使用的是Select,使用一个 Delegate 构建查询。在这个例子中,我们使用了  t => t * 2 是一个 Lambda表达式。 将这个功能嫁接到JS下,定义一个function(){}   JS下的Select查询可以是这样     var someArray = [1, 2, 3, 4]; var otherArray = someArray.select(function (t) { return t * 2 });  然后定义 比较(EqualityComparer)、排序(SortComparer)、条件(Predicate)、查询器(Selector)    比较、排序、条件、查询器     Javascript Linq 查询器  Select   遍历元素下的每一个元素,调用JS.Call方法返回数据。     Array.prototype.select = Array.prototype.map || function (selector, context) {     context = context || window;     var arr = [];     var l = this.length;     for (var i = 0; i < l; i++)         arr.push(selector.call(context, this[i], i, this));     return arr; };     var arr = [1, 2, 3, 4, 5]; var doubled = arr.select(function(t){ return t * 2 });    SelectMany       SelectMany     Take     Array.prototype.take = function (c) {     return this.slice(0, c); };     var arr = [1, 2, 3, 4, 5];  var res = arr.take(2); Skip   跳过指定数后返回集合数据,使用slice。     Array.prototype.skip = function (c) {     return this.slice(c); };    var arr = [1, 2, 3, 4, 5];  var res = arr.skip(2);   First   返回序列的第一个元素,如果没有元素,可以指定一个默认元素。     Array.prototype.first = function (predicate, def) {     var l = this.length;     if (!predicate) return l ? this[0] : def == null ? null : def;     for (var i = 0; i < l; i++)         if (predicate(this[i], i, this))             return this[i];     return def == null ? null : def; };    var arr = [1, 2, 3, 4, 5]; var t1 = arr.first();   var t2 = arr.first(function(t){ return t > 2 });  var t3 = arr.first(function(t){ return t > 10 }, 10); //默认值是10   Union   合并两个集合中的数据,使用concat,不合并重复数据。     Array.prototype.union = function (arr) {     return this.concat(arr).distinct(); };     var arr1 = [1, 2, 3, 4, 5];  var arr2 = [5, 6, 7, 8, 9]; var res = arr1.union(arr2);     Distinct   找出不重复的数据。当有重复元素是只push一个元素进集合。   Array.prototype.distinct = function (comparer) {     var arr = [];     var l = this.length;     for (var i = 0; i < l; i++) {         if (!arr.contains(this[i], comparer))             arr.push(this[i]);     }     return arr; };         var arr1 = [1, 2, 2, 3, 3, 4, 5, 5];    var res1 = arr.distinct();  // [1, 2, 3, 4, 5]   var arr2 = [{Name:"A", Val:1}, {Name:"B", Val:1}]; var res2 = arr2.distinct(function(a, b){ return a.Val == b.Val }); //返回[{Name:"A", Val:1}]    IndexOf   查找指定的值第一次出现的位置。   Array.prototype.indexOf = Array.prototype.indexOf || function (o, index) {     var l = this.length;     for (var i = Math.max(Math.min(index, l), 0) || 0; i < l; i++)         if (this[i] === o) return i;     return -1; };     var arr = [1, 2, 3, 4, 5]; var index = arr.indexOf(2);  // 1    Remove   从集合中移除指定元素。     Array.prototype.remove = function (item) {     var i = this.indexOf(item);     if (i != -1)         this.splice(i, 1); };    var arr = [1, 2, 3, 4, 5]; arr.remove(2);   // [1, 3, 4, 5]   OrderBy     Array.prototype.orderBy = function (selector, comparer) {     comparer = comparer || DefaultSortComparer;     var arr = this.slice(0);     var fn = function (a, b) {         return comparer(selector(a), selector(b));     };       arr.thenBy = function (selector, comparer) {         comparer = comparer || DefaultSortComparer;         return arr.orderBy(DefaultSelector, function (a, b) {             var res = fn(a, b);             return res === 0 ? comparer(selector(a), selector(b)) : res;         });     };       arr.thenByDescending = function (selector, comparer) {         comparer = comparer || DefaultSortComparer;         return arr.orderBy(DefaultSelector, function (a, b) {             var res = fn(a, b);             return res === 0 ? -comparer(selector(a), selector(b)) : res;         });     };       return arr.sort(fn); };            var arr = [{Name:"A", Val:1}, {Name:"a", Val:2}, {Name:"B", Val:1}, {Name:"C", Val:2}];   var res1 = arr.orderBy(function(t){ return t.Name });      var res2 = arr.orderBy(function(t){ return t.Name }, function(a, b){     if(a.toUpperCase() > b.toUpperCase()) return 1;     if(a.toUpperCase() < b.toUpperCase()) return -1;     return 0; });       OrderByDescending   Array.prototype.orderByDescending = function (selector, comparer) {     comparer = comparer || DefaultSortComparer;     return this.orderBy(selector, function (a, b) { return -comparer(a, b) }); };   var arr = [{Name:"A", Val:1}, {Name:"a", Val:2}, {Name:"B", Val:1}, {Name:"C", Val:2}]; var res = arr.orderByDescending(function(t){ return t.Name });      GroupBy   Array.prototype.groupBy = function (selector, comparer) {     var grp = [];     var l = this.length;     comparer = comparer || DefaultEqualityComparer;     selector = selector || DefaultSelector;       for (var i = 0; i < l; i++) {         var k = selector(this[i]);         var g = grp.first(function (u) { return comparer(u.key, k); });           if (!g) {             g = [];             g.key = k;