LINQ to JavaScript 源码分析
在.net平台工作一年有余,最喜欢的应属Linq特性
在几个移动端web小项目过程中,前端需要对json对象集合进行比较复杂的操作,为提高开发效率,引入了LINQ to Javascript,该项目地址:http://jslinq.codeplex.com/
LINQ to JavaScript代码不到两百行,可读性很好,今天来对它的源代码进行下分析
Linq to JavaScript使用示例
var myList = [
{FirstName:"Chris",LastName:"Pearson"},
{FirstName:"Kate",LastName:"Johnson"},
{FirstName:"Josh",LastName:"Sutherland"},
{FirstName:"John",LastName:"Ronald"},
{FirstName:"Steve",LastName:"Pinkerton"}
]; var exampleArray = JSLINQ(myList)
.Where(function(item){ return item.FirstName == "Chris"; })
.OrderBy(function(item) { return item.FirstName; })
.Select(function(item){ return item.FirstName; });
Linq to JavaScript整体架构
(function() {
JSLINQ = window.JSLINQ = function(dataItems) {
return new JSLINQ.fn.init(dataItems);
};
JSLINQ.fn = JSLINQ.prototype = {
init: function(dataItems) {
this.items = dataItems;
},
Where: function(clause) {
...
},
...
}
JSLINQ.fn.init.prototype = JSLINQ.fn;
})();
这个结构的关键点有
- 最外层用一个匿名函数(function(){}))()构造块级作用域
- 不采用new JSLINQ().Where()方式,而是将JSLINQ()作为一个工厂方法,返回init()函数的实例对象
- 为了在init()函数的实例对象上继续调用JSLINQ原型对象的方法,将JSLINQ.fn.init.prototype指向JSLINQ.fn,也即JSLINQ.prototype
- 通过这一操作,调用new JSLINQ().Where()时,首先可以在init()函数的实例对象中查询,未找到后在init.prototype中查询,未找到,继续沿原型链向上查找,在JSLINQ.prototype上找到Where方法
- 如果没有这一操作,调用new JSLINQ().Where()时,将会提示Where方法未被定义
观察Linq to JavaScript整体结构会发现,其结构与JQuery的非常相似
(function( window, undefined ) {
var jQuery = (function() {
// 构建jQuery对象
var jQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context, rootjQuery );
} // jQuery对象原型
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
init: function( selector, context, rootjQuery ) { }
}; // Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn; // 到这里,jQuery对象构造完成,后边的代码都是对jQuery或jQuery对象的扩展
return jQuery;
})(); window.jQuery = window.$ = jQuery;
})(window);
LINQ to JavaScript详细分析
//构造块级作用域
(function() {
//工厂方法,返回init()的实例对象
JSLINQ = window.JSLINQ = function(dataItems) {
return new JSLINQ.fn.init(dataItems);
};
JSLINQ.fn = JSLINQ.prototype = {
init: function(dataItems) {
this.items = dataItems;
}
//clause是一个函数表达式
Where: function(clause) {
var item;
//创建本地数组,存储返回值
var newArray = new Array(); // The clause was passed in as a Method that return a Boolean
for (var index = ; index < this.items.length; index++) {
//将元素传入函数
if (clause(this.items[index], index)) {
newArray[newArray.length] = this.items[index];
}
}
//将结果数组传入JSLINQ(),创建新的init()对象实例,以便可以链式调用
return new JSLINQ(newArray);
},
Select: function(clause) {
var item;
var newArray = new Array(); // The clause was passed in as a Method that returns a Value
for (var i = ; i < this.items.length; i++) {
if (clause(this.items[i])) {
newArray[newArray.length] = clause(this.items[i]);
}
}
return new JSLINQ(newArray);
}
...
JSLINQ.fn.init.prototype = JSLINQ.fn;
}
})();
更多
从LINQ to JavaScript使用示例中可以看到,Where(),Select()等方法中仅支持匿名函数的方式
而在.net3.0之后,LINQ的Where等扩展方法中,已经可以使用便捷的lambda表达式
如果你希望在javascript中也使用lambda表达式语法书写linq,可以关注LINQ for JavaScript,这是另一个提供linq支持的javascript库,项目地址http://linqjs.codeplex.com/
LINQ for JavaScript调用示例
var jsonArray = [
{ "user": { "id": , "screen_name": "d_linq" }, "text": "to objects" },
{ "user": { "id": , "screen_name": "c_bill" }, "text": "g" },
{ "user": { "id": , "screen_name": "b_mskk" }, "text": "kabushiki kaisha" },
{ "user": { "id": , "screen_name": "a_xbox" }, "text": "halo reach" }
]
// ["b_mskk:kabushiki kaisha", "c_bill:g", "d_linq:to objects"]
var queryResult = Enumerable.From(jsonArray)
.Where(function (x) { return x.user.id < })
.OrderBy(function (x) { return x.user.screen_name })
.Select(function (x) { return x.user.screen_name + ':' + x.text })
.ToArray();
// shortcut! string lambda selector
var queryResult2 = Enumerable.From(jsonArray)
.Where("$.user.id < 200")
.OrderBy("$.user.screen_name")
.Select("$.user.screen_name + ':' + $.text")
.ToArray();
LINQ to JavaScript 源码分析的更多相关文章
- 《JavaScript 源码分析》之 jquery.unobtrusive-ajax.js
/*! ** Unobtrusive Ajax support library for jQuery ** Copyright (C) Microsoft Corporation. All right ...
- 《JavaScript 源码分析》之 maxlength.js
/* @author: Terry @params: feedback - the selector for the element that gives the user feedback. Not ...
- JavaScript 模块化及 SeaJs 源码分析
网页的结构越来越复杂,简直可以看做一个简单APP,如果还像以前那样把所有的代码都放到一个文件里面会有一些问题: 全局变量互相影响 JavaScript文件变大,影响加载速度 结构混乱.很难维护 和后端 ...
- Linq扩展最后遗留之SelectMany,Zip,SequenceEqual源码分析
Linq扩展最后遗留之SelectMany,Zip,SequenceEqual源码分析 一: AsParallel [并行化查询] 这个函数的功效就是将计算结果多线程化.[并行计算] =>[多核 ...
- Linq分组操作之GroupBy,GroupJoin扩展方法源码分析
Linq分组操作之GroupBy,GroupJoin扩展方法源码分析 一. GroupBy 解释: 根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值. 查询表达式: var ...
- Linq集合操作之Intersect,Except,Union源码分析
Linq集合操作之Intersect,Except,Union源码分析 linq的集合运算 常见的集合运算有哪些? 这三个扩展方法在我们实际使用中用的还是非常多的,而且这里还涉及到了“复杂度” 无算法 ...
- Linq限定操作之All,Any,Contains源码分析
Linq限定操作之All,Any,Contains源码分析 linq的限定操作 常见的限定操作: All,Any,Contains 一:All 1. 解释: 确定序列中的所有元素是否满足条件. 从字面 ...
- Linq特取操作之ElementAt,Single,Last,First源码分析
Linq特取操作之ElementAt,Single,Last,First源码分析 一:linq的特取操作 First/FirstOrDefault, Last/LastOrDefault, Eleme ...
- Linq聚合操作之Aggregate,Count,Sum,Distinct源码分析
Linq聚合操作之Aggregate,Count,Sum,Distinct源码分析 一:Linq的聚合运算 1. 常见的聚合运算:Aggregate,Count, Sum, Distinct,Max, ...
随机推荐
- UVALive 6869(后缀数组)
传送门:Repeated Substrings 题意:给定一个字符串,求至少重复一次的不同子串个数. 分析:模拟写出子符串后缀并排好序可以发现,每次出现新的重复子串个数都是由现在的height值减去前 ...
- 11.4.2 排序或合并文件(sort命令) - 51CTO.COM
11.4.2 排序或合并文件(sort命令) - 51CTO.COM 11.4.2 排序或合并文件(sort命令) 2010-03-12 14:37 陆松年 电子工业出版社 我要评论(0) 字号:T ...
- POJ 3040 Allowance 贪心
这题目的贪心思路还是有一点细节问题的. 还没有证明,据说是因为题目给的条件是每个价格是比它小的价格的倍数才能这么贪心的. 思路如下: 假设要给奶牛的钱为C 1)从大面值到小面值一次拿钱,能拿多少拿多少 ...
- MySQLdb的安装与使用
一.安装 安装已编译版本号(此方法简便快捷): http://www.codegood.com/downloads 依据自己系统下载,双击安装,搞定 然后import MySQLdb.查看是否成功 我 ...
- Android获得Manifest在<meta-data>元件的值
前段时间攻略完成游戏开发项目.其中用于包装散装. 目前市场上的网络不提交.但是,通过设置Manifest中的Meta_data>去获得相关參数,游戏ID号改变.游戏ID改变,然后游戏内容就改变. ...
- 使用Visual Studio 创建新的Web Part项目
使用Visual Studio 创建新的Web Part项目 Web Part是你将为SharePoint创建的最常见的对象之中的一个.它是平台构建的核心基块. 1. 管理员身份打开Visual St ...
- M I S 开发与管理
今天是开学的第一天,很意外的一天没课.但是我知道还有很多事情在等待这我,不能懈怠!安排好计划,把重要不紧急的事情逐渐蚕食掉,切不可养虎为患,等拖到它变成重要紧急事件后,那就后悔莫及了. 下午看了看自考 ...
- loj1201(最大独立集)
传送门:A Perfect Murder 题意:有一群苍蝇,之间有一些是朋友关系,如果杀了一只苍蝇,那么它的朋友们都会有警惕性,再也杀不了这些朋友了,问最多能杀多少只苍蝇. 分析:根据朋友性连边,最多 ...
- python 入门学习---模块导入三种方式及中文凝视
Python 有三种模块导入函数 1. 使用import 导入模块 import modname : 模块是指一个能够交互使用,或者从还有一Python 程序訪问的代码段.仅仅要导入了一个模块,就能够 ...
- Android bluetooth介绍(四): a2dp connect流程分析
关键词:蓝牙blueZ A2DP.SINK.sink_connect.sink_disconnect.sink_suspend.sink_resume.sink_is_connected.sink_ ...