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;
})();

这个结构的关键点有

  1. 最外层用一个匿名函数(function(){}))()构造块级作用域
  2. 不采用new JSLINQ().Where()方式,而是将JSLINQ()作为一个工厂方法,返回init()函数的实例对象
  3. 为了在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 = 0; 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 = 0; 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": 100, "screen_name": "d_linq" }, "text": "to objects" },
    { "user": { "id": 130, "screen_name": "c_bill" }, "text": "g" },
    { "user": { "id": 155, "screen_name": "b_mskk" }, "text": "kabushiki kaisha" },
    { "user": { "id": 301, "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 < 200 })
    .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();
时间: 2024-10-13 04:58:02

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 reserve

Linq扩展最后遗留之SelectMany,Zip,SequenceEqual源码分析

Linq扩展最后遗留之SelectMany,Zip,SequenceEqual源码分析 一: AsParallel [并行化查询] 这个函数的功效就是将计算结果多线程化.[并行计算] =>[多核] 二:AsQueryable [将lambda表达式作为数据结构存储起来,Expresstion 表达式树] 三:Join 多表关联操作,我们可以用"查询关键字"解决. 为了更加的脱俗易懂,我们建议用人性化的"查询关键字"来解决这个复杂的Join,lambda. 四:

Linq特取操作之ElementAt,Single,Last,First源码分析

Linq特取操作之ElementAt,Single,Last,First源码分析 一:linq的特取操作 First/FirstOrDefault, Last/LastOrDefault, ElementAt/ElementAtOrDefault, Single/SingleOrDefault 二:First/FirstOrDefault 介绍 解释: 用于返回序列中的第一个值 异常: 如果当前集合没有值的话,如果你取第一个值,会抛出throw Error.NoElements();异常. pu

Linq分区操作之Skip,SkipWhile,Take,TakeWhile源码分析

Linq分区操作之Skip,SkipWhile,Take,TakeWhile源码分析 二:linq的分区操作 常用的分区操作:Take,TakeWhile,Skip,SkipWhile 三:Take 1. 注释: 从序列的开头返回指定数量的连续元素 2. 实战: var nums = new int[] { 10, 20, 30, 40, 50, 60 }; var query = nums.Take(2).ToList(); // 10,20 3. 探究源码: 四:TakeWhile 1. 注

ABP源码分析三十三:ABP.Web

ABP.Web模块并不复杂,主要完成ABP系统的初始化和一些基础功能的实现. AbpWebApplication : 继承自ASP.Net的HttpApplication类,主要完成下面三件事一,在Application_Start完成AbpBootstrapper的初始化.整个ABP系统的初始化就是通过AbpBootstrapper完成初始化的.二,在Application_BeginRequest设置根据request或cookie中的Culture信息,完成当前工作线程的CurrentCu

Cordova Android源码分析系列一(项目总览和CordovaActivity分析)

PhoneGap/Cordova是一个专业的移动应用开发框架,是一个全面的WEB APP开发的框架,提供了以WEB形式来访问终端设备的API的功能.这对于采用WEB APP进行开发者来说是个福音,这可以避免了原生开发的某些功能.Cordova 只是个原生外壳,app的内核是一个完整的webapp,需要调用的原生功能将以原生插件的形式实现,以暴露js接口的方式调用. Cordova Android项目是Cordova Android原生部分的Java代码实现,提供了Android原生代码和上层We

Jquery源码分析

1.概述 jQuery是一个非常优秀的Js库,与prototype,YUI,Mootools等众多的Js类库相比,它剑走偏锋,从web开发最实用的角度出发,抛除了一些中看但不实用的东西,为开发者提供一个短小精悍的类库.由于其个短小精悍,使用简单方便,性能相对高效.众多的开发者都选择Jquery来进行辅助的web开发. 在使用jquery时开发,我们也会时常碰到许多的问题,但是jquery的代码很晦涩,难起看懂,当开发时出现了问题,看不懂源码,不知道如何去排错. John Resig,Jquery

java使用websocket,并且获取HttpSession,源码分析

一:本文使用范围 此文不仅仅局限于spring boot,普通的spring工程,甚至是servlet工程,都是一样的,只不过配置一些监听器的方法不同而已. 本文经过作者实践,确认完美运行. 二:Spring boot使用websocket 2.1:依赖包 websocket本身是servlet容器所提供的服务,所以需要在web容器中运行,像我们所使用的tomcat,当然,spring boot中已经内嵌了tomcat. websocket遵循了javaee规范,所以需要引入javaee的包 <

jquery源码分析(二)——结构

再来复习下整体架构: jQuery源码分析(基于 jQuery 1.11 版本,共计8829行源码) (21,94)                定义了一些变量和函数jQuery=function(){} (96,280)        给jQuery添加一些方法和属性,jQuery.fn=jQuery.prototype(285,347)        extend:        jQuery的一些继承方法        更容易进行后续的扩展