首頁 web前端 js教程 用函數模板,寫一個簡單高效的 JSON 查詢器的方法介紹_javascript技巧

用函數模板,寫一個簡單高效的 JSON 查詢器的方法介紹_javascript技巧

May 16, 2016 pm 05:36 PM
json

JSON可謂是JavaScript的亮點,它能用優雅簡練的程式碼實作Object和Array的初始化。同樣是基於文字的資料定義,它比符號分隔更有語義,比XML更簡潔。因此在越來越多的JS開發中,使用它作為資料的傳輸和儲存。

JS陣列內建了不少有用的方法,方便我們對資料的查詢和篩選。例如我們有一堆資料:

複製程式碼 程式碼如下:

var heros = [
var heros = [
        // 名============攻=====防=======力量====敏捷=====智力====
        { name:'冰室女巫', DP:38, AP:1.3, Str:16, Agi:16, Int:21},
        {name:'沉默術士', DP:39, AP:1.1, StrStr: 17, Agi:16, Int:21},
        {name:'娜迦海妖', DP:51, AP:6.0, Str:21, Agi:21, Int:18},
 :'賞金獵人', DP:39, AP:4.0, Str:17, Agi:21, Int:16},
        {name:'劇毒術士', DP:45, AP:3.1, Str: 18, Agi:22, Int:15},
        {name:'光之守衛', DP:38, AP:1.1, Str:16, Agi:15, Int:22},
 '煉金術士', DP:49, AP:0.6, Str:25, Agi:11, Int:25}
        //...
    ];
...

    ];

複製程式碼


程式碼如下:

 var match = heros.filter(function(e) {
        return e.DP > 40 && e.AP     });

回傳得到一個陣列,包括符合條件的2個結果。 比起手工去寫循環判斷,filter方法為我們提供了很大的方便。但它是基於函數回呼的,所以每次使用必須寫一個function,對於簡單的查詢很是累贅,而且使用回呼效率也大大降低。但這是也沒辦法的,想簡單必然要犧牲一定性能。 如果能使用比這更簡單的語句,並且完全擁有程式碼展開時效率,該有是多麼完美的事。

先來想像下,要是能將上面的程式碼寫成這樣,並且查詢速度和手寫的遍歷判斷一樣
複製程式碼


程式碼如下:

    var match = heros.select('@DP>40 AND @AP看起來有點像SQL,連文法都換了?這樣豈不是要寫一個詞法分析,語意解釋等等等等一大堆的腳本引擎的功能了,沒個幾千上萬行程式碼都搞不定,而且效率肯定更糟了。 。 。如果想到那麼複雜,那麼你還沒深刻的理解腳本的精髓。但凡是腳本語言,都有運行時動態解釋代碼的接口,例如vbs的execute();js的eval(),new Function(),甚至創建一個<script>動態寫入代碼。 <P>顯然,如果能將另一種語言,翻譯成js程式碼,那麼就可直接交給宿主來執行了! <P> <P>例如上面select中的字符,我們簡單的將"@"替換成"e.", "AND"替換成"&&",於是就成了一個合法的js表達​​式,完全可以交給eval來執行。 <P>所以我們要做的,就是將原始語句翻譯成js語句來執行。並且為了提高效率,將翻譯好的js表達​​式內聯到一個上下文環境,產生一個可執行的函數體,而不是每次遍歷中都依靠回調來判斷。 <STRONG> <br>於是,函數模版就要派上用場了。 <br> <BR>函數模版簡介<div class="codetitle"><span><a style="CURSOR: pointer" data="84492" class="copybut" id="copybut84492" onclick="doCopy('code84492')">在C 裡面,有宏和類模版這麼東西,可以讓一些計算在編譯階段就完成了,大幅提升了運行時代碼的性能。雖然腳本沒有嚴格意義上的編譯,但在第一次執行的時候會解析並充分的最佳化,這是目前主流瀏覽器相互競爭點。所以,我們要將重複eval的程式碼,鑲嵌到事先提供的樣板函數裡:一個準備就緒,就差表達式計算的函數:<U>複製程式碼<🎜 ><🎜><🎜> 程式碼如下:<🎜><div class="codebody" id="code84492"><BR> /**<BR>     * 模版: tmplCount<BR>     * 功能: 統計arr陣列中符合$express表達式的數量<BR>    */<BR>    function tmplCount(arr) {<BR>        var count = 0; <P>        for(var i = 0; i < arr.length; i ) {<BR>            var e = arr[i]; <P>            if($express) {<BR>                 }<BR>        return count;<BR>    }<BR><BR><BR>上面就是一個範本函數,遍歷參數arr []並統計符合$express的數量。除了if(...)內的表達式外,其他都已經準備就緒了。字元$express也可以換成其他標識,只要不和函數內其他字元衝突即可。 <BR>當我們需要實例化時,首先透過tmplCount.toString()將函數轉成字串格式,然後將其中的$express替換成我們想要的表達式,最後eval這串字符,得到一個Function類型的變量,一個模板函數的實例就產生了! <P>我們簡單的示範下:<P><STRONG><BR><div class="codetitle"><span>複製程式碼<a style="CURSOR: pointer" data="65929" class="copybut" id="copybut65929" onclick="doCopy('code65929')"><U> 程式碼如下:<div class="codebody" id="code65929"> 程式碼如下:<BR><BR> <BR> /**<BR>     * 函數: createInstance<BR>     * 參數: exp<BR>     *          回傳一個Function,模版tmplCount的例<BR>    */<BR>    function createInstance(exp)<BR>    {<BR>                           .replace ('$express', exp);<BR><BR>        // 防止匿名函數直接eval封包錯誤<br>        var fn = eval('0,' code);<br> <BR>        // 回傳範本實例        return fn;<P>    }<BR> <BR>    // 測試參數<P>    var student = [<BR>        {name: 'Jane' {name: 'Adam', age: 18}<BR>    ];<BR> <BR>    // demo1<BR>    var f1 = createInstance('e.age<16');<BR>    alert(f1(student));   11個 <P>    // demo2<BR>    var f2 = createInstance('e.name!="Jack" && e.age>=14');<BR>    alert(f2(student)); ><P>注意createInstance()的參數中,有個叫e的對象,它是在tmplCount模版中定義的,指代遍歷時的具體元素。傳回的f1,f2就是tmplCount模板的兩個實例。在最終調用的f1,f2函數中,已經內嵌了我們的表達式語句,就像我們事先寫了兩個同樣函數的函數一樣,所以在遍歷的時候直接運行表達式,而不用回調什麼的,效率大幅提升。 <BR> <BR><BR> <BR>其實說穿了,tmplCount的存在只是為了提供這個函數的字串而已,本身從來就不會被呼叫。事實上用字串的形式定義也一樣,只不過用函數書寫比較直觀,方便測試。 <P>值得注意的是,如果腳本後期需要壓縮優化,那麼tmplCount模板絕對不能參與,否則對應的"e."和"$express"都有可能改變。 <img src="/static/imghw/default1.png" data-src="http://files.jb51.net/file_images/article/201304/201304171146157.png" class="lazy" alt=""> <P>JSON基本查詢功能<P> 函數範本的用處和實作介紹完了,再來回頭看之前的JSON查詢語言。我們只要將類似sql的語句,翻譯成js表達式,並且產生一個函數模板實例。對於相同的語句,我們可以進行緩存,避免每次都翻譯。 <P> <STRONG>首先我們實作查詢器的範本:<P><P><STRONG><BR>複製程式碼<div class="codetitle"><span><a style="CURSOR: pointer" data="48175" class="copybut" id="copybut48175" onclick="doCopy('code48175')">複製程式碼<U> 程式碼<div class="codebody" id="code48175"><BR> var __proto = Object.prototype; <P>    //<BR>    // 範本: __tmpl<BR>    // 參數: $C<BR>    // 說明: 記錄並傳回_list物件中符合$C的元素集合< var __tmpl = function(_list) {<BR>        var _ret = [];<BR>        var _i = -1;<BR> <BR>        for(var _k in _list) {            var _e = _list[_k]< proto[_k]) {<P>                if($C)<BR>                    _ret[ _i] = _e;<br>         return _ret;<br> <BR>    }.toString();<BR><BR><BR><BR>然後開始寫Object的select方法:<P><BR><BR><STRONG><BR><div class="codetitle"><> 🎜><span><a style="CURSOR: pointer" data="74878" class="copybut" id="copybut74878" onclick="doCopy('code74878')"> 程式碼如下:<U> //    // select方法實作    //<div class="codebody" id="code74878">  // select方法實作<BR>    //<BR> __proto.select = function(exp) {<BR>        if(!exp)<BR>            return [];<br> <br>        var fn = __cache[exp];<BR> <BR>        try {            if(!fn) {<P>           //解釋表達式                code = __tmpl.replace('$C', code);   到模版<P> <BR>                fn = __cache[exp] = __compile(code);    //實例化函數<BR>   <BR>            return fn(this);                          catch(e) {            return [];<P>       其中__cache表實作了查詢語句的快取。對於重複的查詢,效能可以極大的提升。 <BR><P><BR><BR>複製碼<BR><BR><BR> 代碼如下:<BR><BR>    function 🎜><BR><div class="codetitle">    function 🎜><span><a style="CURSOR: pointer" data="94768" class="copybut" id="copybut94768" onclick="doCopy('code94768')">  0,' arguments[0]);<U>    } __compile之所以單獨寫在一個空函數裡,就是為了eval的時候有個盡可能乾淨的上下文環境。 <div class="codebody" id="code94768">__interpret是整個系統的重中之重,負責將查詢語句翻譯成js語句。它的實現見智見仁,但盡可能簡單,不要過度分析語法。 <BR> <BR>具體程式碼檢視:<BR>jsonselect.rar<BR>出於演示,目前只實現部分基本功能。以後還可以再加上 LIKE,BETWEEN,ORDER BY 等等常用的功能。 <BR> <P>Demo<P><A href="http://xiazai.jb51.net/201304/yuanma/jsonselect.rar" target=_blank><BR>複製程式碼<P><STRONG><BR> 程式碼如下:<div class="codebody" id="code75283"><BR>var heros = [<BR>        // 名============攻=====防=======力量====敏捷== ===智力====<BR>        {name:'冰室女巫', DP:38, AP:1.3, Str:16, Agi:16, Int:21},<BR>     ', DP:39, AP:1.1, Str:17, Agi:16, Int:21},<BR>        {name:'娜迦海妖', DP:51, AP:6.0, Str:21, Agigi: 21, Int:18},<BR>        {name:'賞金獵人', DP:39, AP:4.0, Str:17, Agi:21, Int:16},< ', DP:45, AP:3.1, Str:18, Agi:22, Int:15},<BR>        {name:'光之守衛', DP:38, AP:1.1, Str:16, Agi:15 , Int:22},<BR>        {name:'煉金術士', DP:49, AP:0.6, Str:25, Agi:11,Int:25}<>   <BR><BR><BR><BR><BR><div class="codetitle">複製程式碼<span><a style="CURSOR: pointer" data="60993" class="copybut" id="copybut60993" onclick="doCopy('code60993')"><U> 程式碼如下: 程式碼如下:<div class="codebody" id="code60993"><BR><BR>敏捷都超過20的<BR>    // 結果:娜迦海妖    var match = heros.select('@Str>20 AND @Agi>20');<P> <BR>    // 查詢:「士」結尾的<BR>    // 結果:沉默術士,劇毒術士,煉金術士    var match = heros.select('right(@name,1)="士" ');<P> <BR>    // 查詢:生命值超過500的<BR>    // 結果:煉金術士<BR>    var match = heros.select('100 @Str*19 > 500');<🜎 ><BR></script>
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

golang WebSocket與JSON的結合:實現資料傳輸與解析 golang WebSocket與JSON的結合:實現資料傳輸與解析 Dec 17, 2023 pm 03:06 PM

golangWebSocket與JSON的結合:實現資料傳輸和解析在現代的Web開發中,即時資料傳輸變得越來越重要。 WebSocket是一種用於實現雙向通訊的協議,與傳統的HTTP請求-回應模型不同,WebSocket允許伺服器向客戶端主動推送資料。而JSON(JavaScriptObjectNotation)是一種用於資料交換的輕量級格式,它簡潔易讀

如何在Java中使用@Expose註解從JSON中排除一個欄位? 如何在Java中使用@Expose註解從JSON中排除一個欄位? Sep 16, 2023 pm 09:49 PM

Gson@Expose註解可用於標記欄位是否公開(包含或不包含)以進行序列化或反序列化。 @Expose註解可以採用兩個參數,每個參數都是一個布林值,可以採用值true或false。為了讓GSON對@Expose註解做出反應,我們必須使用GsonBuilder類別建立一個Gson實例,並且需要呼叫excludeFieldsWithoutExposeAnnotation()方法,它將Gson配置為排除所有沒有Expose註解的欄位進行序列化或反序列化。語法publicGsonBuilderexclud

MySQL5.7和MySQL8.0的差別是什麼? MySQL5.7和MySQL8.0的差別是什麼? Feb 19, 2024 am 11:21 AM

MySQL5.7和MySQL8.0是兩個不同的MySQL資料庫版本,它們之間有以下一些主要差異:效能改進:MySQL8.0相對於MySQL5.7有一些效能改進。其中包括更好的查詢優化器、更有效率的查詢執行計劃產生、更好的索引演算法和平行查詢等。這些改進可以提高查詢效能和整體系統效能。 JSON支援:MySQL8.0引入了對JSON資料類型的原生支持,包括JSON資料的儲存、查詢和索引。這使得在MySQL中處理和操作JSON資料變得更加方便和有效率。事務特性:MySQL8.0引進了一些新的事務特性,如原子

PHP 數組轉 JSON 的效能最佳化技巧 PHP 數組轉 JSON 的效能最佳化技巧 May 04, 2024 pm 06:15 PM

PHP數組轉JSON的效能最佳化方法包括:使用JSON擴充和json_encode()函數;新增JSON_UNESCAPED_UNICODE選項以避免字元轉義;使用緩衝區提高循環編碼效能;快取JSON編碼結果;考慮使用第三方JSON編碼庫。

使用golang中的json.MarshalIndent函數將結構體轉換為格式化的JSON字串 使用golang中的json.MarshalIndent函數將結構體轉換為格式化的JSON字串 Nov 18, 2023 pm 01:59 PM

使用golang中的json.MarshalIndent函數將結構體轉換為格式化的JSON字串在使用Golang編寫程式時,我們經常需要將結構體轉換為JSON字串,在這個過程中,json.MarshalIndent函數可以幫助我們實現格式化的輸出。下面我們將詳細介紹如何使用這個函數,並提供具體的程式碼範例。首先,讓我們建立一個包含一些資料的結構體。以下是示

C#開發中如何處理XML和JSON資料格式 C#開發中如何處理XML和JSON資料格式 Oct 09, 2023 pm 06:15 PM

C#開發中如何處理XML和JSON資料格式,需要具體程式碼範例在現代軟體開發中,XML和JSON是廣泛應用的兩種資料格式。 XML(可擴展標記語言)是一種用於儲存和傳輸資料的標記語言,而JSON(JavaScript物件表示)是一種輕量級的資料交換格式。在C#開發中,我們經常需要處理和操作XML和JSON數據,本文將重點放在如何使用C#處理這兩種數據格式,並附上

Pandas使用教學:讀取JSON檔案的快速入門 Pandas使用教學:讀取JSON檔案的快速入門 Jan 13, 2024 am 10:15 AM

快速入門:Pandas讀取JSON檔案的方法,需要具體程式碼範例引言:在資料分析和資料科學領域,Pandas是一個重要的Python庫之一。它提供了豐富的功能和靈活的資料結構,能夠方便地對各種資料進行處理和分析。在實際應用中,我們經常會遇到需要讀取JSON檔案的情況。本文將介紹如何使用Pandas來讀取JSON文件,並附上特定的程式碼範例。一、Pandas的安裝

Jackson庫中註解如何控制JSON序列化和反序列化? Jackson庫中註解如何控制JSON序列化和反序列化? May 06, 2024 pm 10:09 PM

Jackson庫中的註解可控制JSON序列化和反序列化:序列化:@JsonIgnore:忽略屬性@JsonProperty:指定名稱@JsonGetter:使用獲取方法@JsonSetter:使用設定方法反序列化:@JsonIgnoreProperties:忽略屬性@ JsonProperty:指定名稱@JsonCreator:使用建構子@JsonDeserialize:自訂邏輯

See all articles