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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM