首页 > 代码库 > LINQ to Javascript源码分析

LINQ to Javascript源码分析

  1 //-----------------------------------------------------------------------  2 // Part of the LINQ to JavaScript (JSLINQ) v2.20 Project - http://jslinq.codeplex.com  3 // Copyright (C) 2012 Chris Pietschmann (http://pietschsoft.com). All rights reserved.  4 // This license can be found here: http://jslinq.codeplex.com/license  5 //-----------------------------------------------------------------------  6 (function () {  7     var JSLINQ = window.jslinq = window.JSLINQ = function (dataItems) {  8         return new JSLINQ.fn.init(dataItems);  9     }, 10     utils = { 11         processLambda: function (clause) { 12             // This piece of "handling" C#-style Lambda expression was borrowed from: 13             // linq.js - LINQ for JavaScript Library - http://lingjs.codeplex.com 14             // THANK!! 15             if (utils.isLambda(clause)) { 16                 var expr = clause.match(/^[(\s]*([^()]*?)[)\s]*=>(.*)/); 17                 return new Function(expr[1], "return (" + expr[2] + ")"); 18             } 19             return clause; 20         }, 21         isLambda: function (clause) { 22             return (clause.indexOf("=>") > -1); 23         }, 24         randomIndex: function (max, existing) { 25             var q, r, f = function () { return this == r; }; 26             if (!existing) { 27                 return parseInt(Math.random() * max, 10); 28             } else { 29                 q = JSLINQ(existing); 30                 r = -1; 31                 while (r < 0 || q.Where(f).Count() !== 0) { 32                     r = utils.randomIndex(max); 33                 } 34                 return r; 35             } 36         } 37     }; 38     JSLINQ.fn = JSLINQ.prototype = { 39         init: function (dataItems) { 40             this.items = dataItems; 41         }, 42  43         // The current version of JSLINQ being used 44         jslinq: "2.20", 45  46         toArray: function () { return this.items; }, 47         where: function (clause) { 48             var newArray = [], len = this.items.length; 49  50             // The clause was passed in as a Method that return a Boolean 51             for (var i = 0; i < len; i++) { 52                 if (clause.apply(this.items[i], [this.items[i], i])) { 53                     newArray[newArray.length] = this.items[i]; 54                 } 55             } 56             return JSLINQ(newArray); 57         }, 58         select: function (clause) { 59             var item, newArray = [], field = clause; 60             if (typeof (clause) !== "function") { 61                 if (clause.indexOf(",") === -1) { 62                     clause = function () { return this[field]; }; 63                 } else { 64                     clause = function () { 65                         var i, fields = field.split(","), obj = {}; 66                         for (i = 0; i < fields.length; i++) { 67                             obj[fields[i]] = this[fields[i]]; 68                         } 69                         return obj; 70                     }; 71                 } 72             } 73  74             // The clause was passed in as a Method that returns a Value 75             for (var i = 0; i < this.items.length; i++) { 76                 item = clause.apply(this.items[i], [this.items[i]]); 77                 if (item) { 78                     newArray[newArray.length] = item; 79                 } 80             } 81             return JSLINQ(newArray); 82         }, 83         orderBy: function (clause) { 84             var tempArray = []; 85             for (var i = 0; i < this.items.length; i++) { 86                 tempArray[tempArray.length] = this.items[i]; 87             } 88  89             if (typeof (clause) !== "function") { 90                 var field = clause; 91                 if (utils.isLambda(field)) { 92                     clause = utils.processLambda(field); 93                 } 94                 else { 95                     clause = function () { return this[field]; }; 96                 } 97             } 98  99             return JSLINQ(100             tempArray.sort(function (a, b) {101                 var x = clause.apply(a, [a]), y = clause.apply(b, [b]);102                 return ((x < y) ? -1 : ((x > y) ? 1 : 0));103             })104         );105         },106         orderByDescending: function (clause) {107             var tempArray = [], field;108             for (var i = 0; i < this.items.length; i++) {109                 tempArray[tempArray.length] = this.items[i];110             }111 112             if (typeof (clause) !== "function") {113                 field = clause;114                 if (utils.isLambda(field)) {115                     clause = utils.processLambda(field);116                 }117                 else {118                     clause = function () { return this[field]; };119                 }120             }121 122             return JSLINQ(tempArray.sort(function (a, b) {123                 var x = clause.apply(b, [b]), y = clause.apply(a, [a]);124                 return ((x < y) ? -1 : ((x > y) ? 1 : 0));125             }));126         },127         selectMany: function (clause) {128             var r = [];129             for (var i = 0; i < this.items.length; i++) {130                 r = r.concat(clause.apply(this.items[i], [this.items[i]]));131             }132             return JSLINQ(r);133         },134         count: function (clause) {135             if (clause === undefined) {136                 return this.items.length;137             } else {138                 return this.Where(clause).items.length;139             }140         },141         distinct: function (clause) {142             var item, dict = {}, retVal = [];143             for (var i = 0; i < this.items.length; i++) {144                 item = clause.apply(this.items[i], [this.items[i]]);145                 // TODO - This doesn‘t correctly compare Objects. Need to fix this146                 if (dict[item] === undefined) {147                     dict[item] = true;148                     retVal.push(item);149                 }150             }151             dict = null;152             return JSLINQ(retVal);153         },154         any: function (clause) {155             for (var i = 0; i < this.items.length; i++) {156                 if (clause.apply(this.items[i], [this.items[i], i])) { return true; }157             }158             return false;159         },160         all: function (clause) {161             for (var i = 0; i < this.items.length; i++) {162                 if (!clause(this.items[i], i)) { return false; }163             }164             return true;165         },166         reverse: function () {167             var retVal = [];168             for (var i = this.items.length - 1; i > -1; i--) {169                 retVal[retVal.length] = this.items[i];170             }171             return JSLINQ(retVal);172         },173         first: function (clause) {174             if (clause !== undefined) {175                 return this.Where(clause).First();176             }177             else {178                 // If no clause was specified, then return the First element in the Array179                 if (this.items.length > 0) {180                     return this.items[0];181                 } else {182                     return null;183                 }184             }185         },186         last: function (clause) {187             if (clause !== undefined) {188                 return this.Where(clause).Last();189             }190             else {191                 // If no clause was specified, then return the First element in the Array192                 if (this.items.length > 0) {193                     return this.items[this.items.length - 1];194                 } else {195                     return null;196                 }197             }198         },199         elementAt: function (i) {200             return this.items[i];201         },202         concat: function (array) {203             var arr = array.items || array;204             return JSLINQ(this.items.concat(arr));205         },206         intersect: function (secondArray, clause) {207             var clauseMethod, sa = (secondArray.items || secondArray), result = [];208             if (clause !== undefined) {209                 clauseMethod = clause;210             } else {211                 clauseMethod = function (item, index, item2, index2) { return item === item2; };212             }213 214             for (var a = 0; a < this.items.length; a++) {215                 for (var b = 0; b < sa.length; b++) {216                     if (clauseMethod(this.items[a], a, sa[b], b)) {217                         result[result.length] = this.items[a];218                     }219                 }220             }221             return JSLINQ(result);222         },223         defaultIfEmpty: function (defaultValue) {224             if (this.items.length === 0) {225                 return defaultValue;226             }227             return this;228         },229         elementAtOrDefault: function (i, defaultValue) {230             if (i >= 0 && i < this.items.length) {231                 return this.items[i];232             }233             return defaultValue;234         },235         firstOrDefault: function (defaultValue) {236             return this.First() || defaultValue;237         },238         lastOrDefault: function (defaultValue) {239             return this.Last() || defaultValue;240         },241         take: function (count) {242             return this.Where(function (item, index) { return index < count; });243         },244         skip: function (count) {245             return this.Where(function (item, index) { return index >= count; });246         },247         each: function (clause) {248             var len = this.items.length;249             for (var i = 0; i < len; i++) {250                 clause.apply(this.items[i], [this.items[i], i]);251             }252             return this;253         },254         random: function (count) {255             var len = this.Count(), rnd = [];256             if (!count) { count = 1; }257             for (var i = 0; i < count; i++) {258                 rnd.push(utils.randomIndex(len - 1, rnd));259             }260             rnd = JSLINQ(rnd);261             return this.Where(function (item, index) {262                 return rnd.Where(function () {263                     return this == index;264                 }).Count() > 0;265             });266         }267     };268 269     (function (fn) {270         fn.ToArray = fn.toArray;271         fn.Where = fn.where;272         fn.Select = fn.select;273         fn.OrderBy = fn.orderBy;274         fn.OrderByDescending = fn.orderByDescending;275         fn.SelectMany = fn.selectMany;276         fn.Count = fn.count;277         fn.Distinct = fn.distinct;278         fn.Any = fn.any;279         fn.All = fn.all;280         fn.Reverse = fn.reverse;281         fn.First = fn.first;282         fn.Last = fn.last;283         fn.ElementAt = fn.elementAt;284         fn.Concat = fn.concat;285         fn.Intersect = fn.intersect;286         fn.DefaultIfEmpty = fn.defaultIfEmpty;287         fn.ElementAtOrDefault = fn.elementAtOrDefault;288         fn.FirstOrDefault = fn.firstOrDefault;289         fn.LastOrDefault = fn.lastOrDefault;290         fn.Take = fn.take;291         fn.Skip = fn.skip;292         fn.Each = fn.each;293         fn.Random = fn.random;294     })(JSLINQ.fn);295 296     JSLINQ.fn.init.prototype = JSLINQ.fn;297 })();

具体分析下次有时间再写!

LINQ to Javascript源码分析