用函数模板,写一个简单高效的 JSON 查询器的方法(2)

当我们需要实例化时,首先通过tmplCount.toString()将函数转成字符串格式,然后将其中的$express替换成我们想要的表达式,最后eval这串字符,得到一个Function类型的变量,一个模板函数的实例就产生了!

我们简单的演示下:

复制代码 代码如下:


 /**
     * 函数: createInstance
     * 参数: exp
     *      一段js表达式字符串,用来替换tmplCount模板的$express
     * 返回:
     *      返回一个Function,模版tmplCount的实例
     */
    function createInstance(exp)
    {
        // 替换模板内的表达式
        var code = tmplCount.toString()
                    .replace('$express', exp);

        // 防止匿名函数直接eval报错
        var fn = eval('0,' + code);

// 返回模板实例
        return fn;
    }


    // 测试参数
    var student = [
        {name: 'Jane', age: 14},
        {name: 'Jack', age: 20},
        {name: 'Adam', age: 18}
    ];

// demo1
    var f1 = createInstance('e.age<16');
    alert(f1(student));    //1个

// demo2
    var f2 = createInstance('e.name!="Jack" && e.age>=14');
    alert(f2(student));    //2个


注意createInstance()的参数中,有个叫e的对象,它是在tmplCount模版中定义的,指代遍历时的具体元素。返回的f1,f2就是tmplCount模板的两个实例。最终调用的f1,f2函数中,已经内嵌了我们的表达式语句,就像我们事先写了两个同样功能的函数一样,所以在遍历的时候直接运行表达式,而不用回调什么的,效率大幅提升。

用函数模板,写一个简单高效的 JSON 查询器的方法

其实说白了,tmplCount的存在仅仅是为了提供这个函数的字符串而已,其本身从来不会被调用。事实上用字符串的形式定义也一样,只不过用函数书写比较直观,方便测试。

值得注意的是,如果脚本后期需要压缩优化,那么tmplCount模板绝对不能参与,否则对应的"e."和"$express"都有可能发生变化。

JSON基本查询功能

函数模板的用处和实现介绍完了,再来回头看之前的JSON查询语言。我们只需将类似sql的语句,翻译成js表达式,并且生成一个函数模板实例。对于相同的语句,我们可以进行缓存,避免每次都翻译。

首先我们实现查询器的模板:

复制代码 代码如下:


 var __proto = Object.prototype;

//
    // 模板: __tmpl
    // 参数: $C
    // 说明: 记录并返回_list对象中匹配$C的元素集合
    //
    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)
                    _ret[++_i] = _e;
            }
        }
        return _ret;

}.toString();


然后开始写Object的select方法:

复制代码 代码如下:


 //
    // 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);    //实例化函数
            }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdgxjx.html