• 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();
  • 相关阅读:
    flex 图表使用百分比示例
    flex 图标设置百分比或者其它符号
    大学生求职(打油诗一首)
    flex 图表categoryField设置 labelFunction使用
    如何配置EclipseMe
    google chart图表使用
    Codeforces #Round 632 div2 A~C
    牛客的两道dfs
    约数
    Atcoder ABC162 D RGB Triplets
  • 原文地址:https://www.cnblogs.com/GongQi/p/4043632.html
Copyright © 2020-2023  润新知