ホームページ >ウェブフロントエンド >jsチュートリアル >関数テンプレートを使用したシンプルで効率的な JSON クエリの作成方法の紹介_JavaScript スキル

関数テンプレートを使用したシンプルで効率的な JSON クエリの作成方法の紹介_JavaScript スキル

WBOY
WBOYオリジナル
2016-05-16 17:36:40917ブラウズ

JSON は JavaScript のハイライトとも言え、オブジェクトと配列の初期化をエレガントで簡潔なコードで実装できます。これはテキストベースのデータ定義でもあり、シンボル分離よりも意味論的であり、XML よりも簡潔です。そのため、JS 開発者がデータの送信やストレージとして使用することが増えています。

JS 配列には、データのクエリとフィルタリングを容易にするための便利なメソッドが多数組み込まれています。たとえば、一連のデータがあります:

コードをコピーします コードは次のとおりです:

var heros = [
// 名前============攻撃======防御========強さ====器用さ=====知性====
名前: '氷室の魔女'、DP: 38、AP: 1.3、STR: 16、AGI: 16、int: 21}、 {名前: 'サイレント ウォーロック'、DP: 39、AP: 1.1、STR: 17、Agi:16、Int:21}、
{name:'ナーガ セイレン'、DP:51、AP:6.0、Str:21、Agi:21、Int:18} ,
{名前:'バウンティハンター'、DP:39、AP:4.0、Str:17、Int:21、Int:16}、
18、Agi:22、Int:15}、
{名前:'光の守護者'、DP:38、AP:1.1、Str:16、Agi:15、Int:22}、
{名前:'アルケミスト'、DP:49、AP:0.6、Str :25、Agi:11、Int:25}
防御力が 40 を超え、防御力が 4 未満のヒーローの場合は、Array のフィルター メソッドを使用できます。



コードをコピーします

コードは次のとおりです。 var match = hero.filter(function( e) {
手動でループ判定を記述するのに比べて、フィルター方式は非常に便利です。ただし、関数のコールバックに基づいているため、関数を使用するたびに関数を作成する必要があり、単純なクエリの場合は非常に面倒であり、コールバックの使用効率も大幅に低下します。しかし、これをシンプルにしたい場合は、ある程度のパフォーマンスを犠牲にする必要があります。 これよりも単純なステートメントを使用して、コード拡張の効率を最大限に享受できれば、どれほど完璧でしょう。

まず、上記のコードが次のように記述でき、
クエリ速度が手書きのトラバース判定と同じである場合
を想像してください。

コードをコピーします

コードは次のとおりです:


たとえば、上記の選択内の文字については、「@」を「e.」に、「AND」を「&&」に置き換えるだけで、eval 実装に渡すことができる正当な JS 式になります。 。
したがって、私たちがしなければならないことは、元のステートメントを実行用の js ステートメントに変換することです。また、効率を向上させるために、各走査での判断をコールバックに依存するのではなく、変換された js 式がコンテキスト環境にインライン化されて、実行可能な関数本体が生成されます。
そこで、関数テンプレートが役に立ちます。

関数テンプレートの概要

C にはマクロやクラス テンプレートなどがあり、コンパイル フェーズ中に一部の計算を完了できるようになり、パフォーマンスが大幅に向上します。ランタイムコード。スクリプトは厳密な意味ではコンパイルされませんが、初回実行時に解析されて完全に最適化されます。これが現在の主流ブラウザ間の競争点です。したがって、事前に用意されているテンプレート関数に繰り返し eval コードを埋め込む必要があります。準備が整い、式の計算のみが必要な関数:

コードをコピー

コードは次のとおりです:


/**
* テンプレート: tmplCount
* 関数: arr 配列内の $express に一致する式の数をカウントします
*/
function tmplCount(arr) {
var count = 0;

for(var i = 0; i var e = arr[i];

if($express) {
🎜>上記は、パラメーター arr [] を走査し、$express に一致する数をカウントするテンプレート関数です。 if(...) 内の式を除いて、他のすべての準備は完了です。文字 $express は、関数内の他の文字と競合しない限り、他の識別子に置き換えることもできます。

インスタンスを作成する必要がある場合は、まず tmplCount.toString() を通じて関数を文字列形式に変換し、次に $express を必要な式に置き換え、最後にこの文字列を評価して関数タイプの変数、インスタンスを取得します。のテンプレート関数が生成されました!


簡単なデモを行ってみましょう:


コードをコピーします
コードは次のとおりです:

/** * 関数: createInstance * パラメーター: exp * tmplCount テンプレートの $express を置き換えるために使用される JS 式文字列 * 戻り値:
* 関数、テンプレート tmplCount を返します。
*/
function createInstance(exp)
{
// テンプレート内の式を置き換えます
var code = tmplCount.toString()
.replace ('$express', exp);

// 匿名関数が eval で直接エラーを報告するのを防ぎます
var fn = eval('0,' code);

// テンプレートインスタンスを返します


// テストパラメータ
var Student = [
{名前: 'ジェーン'、年齢: 14}, {名前: 'ジャック'、年齢: 20},

{名前: 'アダム'、年齢: 18}
];

//デモ1

var f1 = createInstance('e.agealert(f1(student));
//demo2
var f2 = createInstance('e.name!="ジャック" && e.age>=14');
alter(f2(student)); //2

createInstance() のパラメータの中には e というオブジェクトがあることに注意してください。これは tmplCount テンプレートで定義されており、トラバーサル中に特定の要素を参照します。返される f1 と f2 は、tmplCount テンプレートの 2 つのインスタンスです。最後に呼び出される f1 関数と f2 関数には、同じ関数を使用して 2 つの関数を事前に作成したのと同じように、式ステートメントがすでに埋め込まれているため、式はコールバックなどを使用せずにトラバーサル中に直接実行され、効率が大幅に向上しました。



実際、率直に言うと、tmplCount はこの関数の文字列を提供するためだけに存在しており、それ自体が呼び出されることはありません。実際、文字列形式での定義は同じですが、関数で記述した方が直感的でテストに便利です。

後でスクリプトで圧縮の最適化が必要な場合は、tmplCount テンプレートを使用しないでください。使用しないと、対応する "e." と "$express" が変更される可能性があることに注意してください。


JSON 基本クエリ関数

関数テンプレートの使用と実装を紹介したので、前の JSON クエリ言語を振り返ってみましょう。 SQL のようなステートメントを JS 式に変換し、関数テンプレートのインスタンスを生成するだけで済みます。同じステートメントについては、毎回の変換を避けるためにキャッシュすることができます。

最初にクエリ テンプレートを実装します。

コードをコピーします

コードは次のとおりです。


var __proto = Object.prototype;

//
// テンプレート: __tmpl
// パラメータ: $C
// 説明: $C に一致する要素のセットを _list オブジェクトに記録して返します
//
var __tmpl = function(_list) {
var _ret = [];
var _i = -1;

for(var _k in _list) {
var _e = _list[_k];

if(_e && _e != __proto[_k]) {
if ($C)

}.toString();

次に、オブジェクトの select メソッドの記述を開始します:



コードをコピー
コードは次のとおりです: // // メソッドの実装を選択
//
var __cache = {};

__proto.select = function(exp) {
If(!exp)
return [];

var fn = __cache[exp];

try { if(!fn) {

var code = __interpret(exp); //式を解釈します

code = __tmpl.replace('$C' , code);テンプレートへ


fn = __cache [exp] = __compile(code);
return fn(this); }
}


__cache テーブルはクエリ ステートメントのキャッシュを実装します。クエリを繰り返すと、パフォーマンスが大幅に向上します。




コードをコピー


コードは次のとおりです。



function __compile() {
return eval(' 0,' argument[0]); } __compile を空の関数内で別に記述する理由は、eval を実行する際のコンテキストをできるだけクリーンにするためです。 __interpret はシステム全体の最優先事項であり、クエリ ステートメントを js ステートメントに変換する役割を果たします。その実装は意見の問題ですが、できるだけ単純にして、構文を過度に分析しないでください。
特定のコードを表示:
jsonselect.rar

デモンストレーションの目的で、現在はいくつかの基本機能のみが実装されています。将来的には、LIKE、BETWEEN、ORDER BY などの一般的に使用される関数を追加することもできます。

デモ


コードをコピー

コードは次のとおりです:

var Heros = [
// 名前 ===================== パワー === アジャイル == === インテリジェンス == ==
{name:'アイスハウスウィッチ'、DP:38、AP:1.3、Str:16、Agi:16、Int:21}、
{name:'サイレントウォーロック'、DP:39、AP :1.1、Str:17、Agi:16、Int:21}、
21, 8}、
{名前:'バウンティハンター'、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、Int:22}、





コードをコピー コードは次のとおりです: // クエリ: 強さ、敏捷性が 20 を超える
// 結果: Naga Siren
var match = heros .select('@Str>20 AND @Agi>20');

// クエリ:
"Scholar" で終わる // 結果: サイレンス ウォーロック、ヴェノマンサー、アルケミスト var match = hero.select('right(@name,1)="Shi" ');


// クエリ: 体力が 500 を超える
// 結果: Alchemist

var match = hero.select('100 @Str*19 > 500');




声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。