码迷,mamicode.com
首页 > 编程语言 > 详细

LINQ to Javascript源码分析

时间:2014-10-24 16:04:10      阅读:256      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   io   ar   java   for   

  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 this
146                 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 Array
179                 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 Array
192                 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源码分析

标签:des   style   blog   http   color   io   ar   java   for   

原文地址:http://www.cnblogs.com/wyf-gis/p/4048470.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!