金沙棋牌官方平台

当前位置:金沙棋牌 > 金沙棋牌官方平台 > 介绍JavaScript的一个微型模版,查询器的方法介绍

介绍JavaScript的一个微型模版,查询器的方法介绍

来源:http://www.logblo.com 作者:金沙棋牌 时间:2019-08-29 15:55

介绍JavaScript的一个微型模版

   这篇文章主要介绍了一个JavaScript微型模版,需要的朋友可以参考下

  我一直在使用一个小工具,并发现它在构建Javascript应用过程中非常实用。它是一个非常简单的模板函数,速度快,支持缓存,并容易使用。我想分享一下使用它的过程中的一些技巧。

  以下是模板函数的代码(你可以从正要出版的Secrets of the JavaScript Ninja一书中得到更精炼的版本):

  ?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

// 简单JavaScript模板引擎

// John Resig - http://ejohn.org/ - MIT Licensed

(function(){

var cache = {};

 

this.tmpl = function tmpl(str, data){

// 判断我们是否已经有这么一个模板,或者我们需要载入模板

// 并保证把结果保存到缓存中。

var fn = !/W/.test(str) ?

cache[str] = cache[str] ||

tmpl(document.getElementById(str).innerHTML) :

 

// 生成一个可重用的函数,用于提供模板生成功能

// (它会被记录到缓存内).

new Function("obj",

"var p=[],print=function(){p.push.apply(p,arguments);};"

 

// 通过with(){}把数据作为本地变量引入

"with(obj){p.push('"

 

// 把模板转换未纯javascript代码

str

.replace(/[rtn]/g, " ")

.split("<%").join("t")

.replace(/((^|%>)[^t]*)'/g, "$1r")

.replace(/t=(.*?)%>/g, "',$1,'")

.split("t").join("');")

.split("%>").join("p.push('")

.split("r").join("\'")

"');}return p.join('');");

 

// 给用户提供一些基本的柯里化功能

return data ? fn( data ) : fn;

};

})();

  你的模板代码看起来将是类似于(这并不是规定的格式,但是我比较喜欢这样):

  ?

1

2

3

4

5

6

7

8

9

10

<script type="text/html" id="item_tmpl">

<div id="<%=id%>" class="<%=(i % 2 == 1 ? " even" : "")%>">

<div class="grid_1 alpha right">

<img class="righted" src="<%=profile_image_url%>"/>

</div>

<div class="grid_6 omega contents">

<p><b><a href="/<%=from_user%>"><%=from_user%></a>:</b> <%=text%></p>

</div>

</div>

</script>

  你也可以内嵌脚本:

  ?

1

2

3

4

5

<script type="text/html" id="user_tmpl">

<% for ( var i = 0; i < users.length; i ) { %>

<li><a href="<%=users[i].url%>"><%=users[i].name%></a></li>

<% } %>

</script>

  提示:把脚本内嵌到你的页面中,并且content-type是未知的(例如在这个例子中,浏览器不知道该如何执行 text/html 脚本),那么浏览器会把它忽略掉 - 同时搜索引擎和屏幕读取也会忽略掉它。这是一个非常好的伪装代码,可以把你的模板嵌入到你的页面中。我喜欢使用快速却又随性的技术,我只需一到两个小模板,就可以得到又轻型和快速应用。

  你可以在脚本中,像这样去使用:

  ?

1

2

var results = document.getElementById("results");

results.innerHTML = tmpl("item_tmpl", dataObject);

  你可以预编译结果,在稍后使用。如果你只使用一个ID作为参数(或者一个模板代码)来调用模板函数,那么它就会返回一个预编译的函数,你就可以在稍后调用:

  ?

1

2

3

4

var show_user = tmpl("item_tmpl"), html = "";

for ( var i = 0; i < users.length; i ) {

html = show_user( users[i] );

}

  这是目前最没办法的办法,解析和转换代码——对这你很可能无爱。不过他只有我中意的一项技术:在字符串中用字符静态搜索和静态替换时,比如split("match").join("replace"),执行速度更好——看起来不直观但可以有效工作在现代浏览器里(下一版FireFox会大幅提高replace(/match/g,"replace")的性能——所以现在这样的长表达式以后不需要的)

  放轻松享受它——我很好奇代码中的突变。即使它很简单,仍然有很多事情可以用它做。

这篇文章主要介绍了一个JavaScript微型模版,需要的朋友可以参考下 我一直在使用一个小工具,并发现它在构建...

介绍JavaScript的一个微型模版,javascript模版

 我一直在使用一个小工具,并发现它在构建Javascript应用过程中非常实用。它是一个非常简单的模板函数,速度快,支持缓存,并容易使用。我想分享一下使用它的过程中的一些技巧。

以下是模板函数的代码(你可以从正要出版的Secrets of the JavaScript Ninja一书中得到更精炼的版本):  

// 简单JavaScript模板引擎
// John Resig - http://ejohn.org/ - MIT Licensed
(function(){
 var cache = {};

 this.tmpl = function tmpl(str, data){
  // 判断我们是否已经有这么一个模板,或者我们需要载入模板
  // 并保证把结果保存到缓存中。
  var fn = !/W/.test(str) ?
   cache[str] = cache[str] ||
    tmpl(document.getElementById(str).innerHTML) :

   // 生成一个可重用的函数,用于提供模板生成功能
   // (它会被记录到缓存内).
   new Function("obj",
    "var p=[],print=function(){p.push.apply(p,arguments);};"  

    // 通过with(){}把数据作为本地变量引入
    "with(obj){p.push('"  

    // 把模板转换未纯javascript代码
    str
     .replace(/[rtn]/g, " ")
     .split("<%").join("t")
     .replace(/((^|%>)[^t]*)'/g, "$1r")
     .replace(/t=(.*?)%>/g, "',$1,'")
     .split("t").join("');")
     .split("%>").join("p.push('")
     .split("r").join("\'")
     "');}return p.join('');");

  // 给用户提供一些基本的柯里化功能
  return data ? fn( data ) : fn;
 };
})();

你的模板代码看起来将是类似于(这并不是规定的格式,但是我比较喜欢这样):

 

<script type="text/html" id="item_tmpl">
 <div id="<%=id%>" class="<%=(i % 2 == 1 ? " even" : "")%>">
  <div class="grid_1 alpha right">
   <img class="righted" src="<%=profile_image_url%>"/>
  </div>
  <div class="grid_6 omega contents">
   <p><b><a href="/<%=from_user%>"><%=from_user%></a>:</b> <%=text%></p>
  </div>
 </div>
</script>

你也可以内嵌脚本:  

<script type="text/html" id="user_tmpl">
 <% for ( var i = 0; i < users.length; i   ) { %>
  <li><a href="<%=users[i].url%>"><%=users[i].name%></a></li>
 <% } %>
</script>

提示:把脚本内嵌到你的页面中,并且content-type是未知的(例如在这个例子中,浏览器不知道该如何执行 text/html 脚本),那么浏览器会把它忽略掉 - 同时搜索引擎和屏幕读取也会忽略掉它。这是一个非常好的伪装代码,可以把你的模板嵌入到你的页面中。我喜欢使用快速却又随性的技术,我只需一到两个小模板,就可以得到又轻型和快速应用。

你可以在脚本中,像这样去使用:  

var results = document.getElementById("results");
results.innerHTML = tmpl("item_tmpl", dataObject);

你可以预编译结果,在稍后使用。如果你只使用一个ID作为参数(或者一个模板代码)来调用模板函数,那么它就会返回一个预编译的函数,你就可以在稍后调用:  

var show_user = tmpl("item_tmpl"), html = "";
for ( var i = 0; i < users.length; i   ) {
 html  = show_user( users[i] );
}

这是目前最没办法的办法,解析和转换代码——对这你很可能无爱。不过他只有我中意的一项技术:在字符串中用字符静态搜索和静态替换时,比如split("match").join("replace"),执行速度更好——看起来不直观但可以有效工作在现代浏览器里(下一版FireFox会大幅提高replace(/match/g,"replace")的性能——所以现在这样的长表达式以后不需要的)

放轻松享受它——我很好奇代码中的突变。即使它很简单,仍然有很多事情可以用它做。

我一直在使用一个小工具,并发现它在构建Javascript应用过程中非常实用。它是一个非常简单的模...

JSON可谓是JavaScript的亮点,它能用优雅简练的代码实现Object和Array的初始化。同样是基于文本的数据定义,它比符号分隔更有语义,比XML更简洁。因此越来越多的JS开发中,使用它作为数据的传输和储存。

JS数组内置了不少有用的方法,方便我们对数据的查询和筛选。例如我们有一堆数据:

复制代码 代码如下:

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},
        {name:'娜迦海妖', DP:51, AP:6.0, Str:21, Agi:21, Int:18},
        {name:'赏金猎人', 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},
        {name:'炼金术士', DP:49, AP:0.6, Str:25, Agi:11, Int:25}
        //...
    ];

要查询攻击大于40并且防御小于4的英雄,我们可以用Array的filter方法:

复制代码 代码如下:

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

返回得到一个数组,包括符合条件的2个结果。

相比手工去写循环判断,filter方法为我们提供了很大的方便。但它是基于函数回调的,所以每次使用必须写一个function,对于简单的查询很是累赘,而且使用回调效率也大大降低。但这是也没有办法的,想简单必然要牺牲一定性能。 如果能使用比这更简单的语句,并且完全拥有代码展开时效率,该有是多么完美的事。

先来想象下,要是能将上面的代码写成这样,并且查询速度和手写的遍历判断一样:

复制代码 代码如下:

    var match = heros.select('@DP>40 AND @AP<4');

看上去有点像SQL,连语法都换了?这样岂不是要写一个词法分析,语义解释等等等等一大堆的脚本引擎的功能了,没个几千上万行代码都搞不定,而且效率肯定更糟了。。。如果想到那么复杂,那么你还没深刻的理解脚本的精髓。但凡是脚本语言,都有运行时动态解释代码的接口,例如vbs的execute();js的eval(),new Function(),甚至创建一个<script>动态写入代码。

显然,要是能将另一种语言,翻译成js代码,那么就可直接交给宿主来执行了!

例如上面select中的字符,我们简单的将"@"替换成"e.", "AND"替换成"&&",于是就成了一个合法的js表达式,完全可以交给eval来执行。

所以我们要做的,就是将原始语句翻译成js语句来执行。并且为了提高效率,将翻译好的js表达式内联到一个上下文环境,生成一个可执行的函数体,而不是每次遍历中都依靠回调来判断。

于是,函数模版就要派上用场了。

**函数模版简介

**在C 里面,有宏和类模版这么个东西,可以让一些计算在编译阶段就完成了,大幅提升了运行时代码的性能。脚本虽然没有严格意义上的编译,但在第一次执行的时候会解析并充分的优化,这是目前主流浏览器相互竞争点。所以,我们要将重复eval的代码,镶嵌到事先提供的样板函数里:一个准备就绪,就差表达式计算的函数:

复制代码 代码如下:

 /**
     * 模版: tmplCount
     * 功能: 统计arr数组中符合$express表达式的数量
     */
    function tmplCount(arr) {
        var count = 0;

        for(var i = 0; i < arr.length; i ) {
            var e = arr[i];

            if($express) {
                count ;
            }
        }
        return count;
    }

上面就是一个模板函数,遍历参数arr[]并统计符合$express的数量。除了if(...)内的表达式外,其他都已经准备就绪了。字符$express也可以换成其他标识,只要不和函数内其他字符冲突即可。

当我们需要实例化时,首先通过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函数中,已经内嵌了我们的表达式语句,就像我们事先写了两个同样功能的函数一样,所以在遍历的时候直接运行表达式,而不用回调什么的,效率大幅提升。

图片 1

其实说白了,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);    //实例化函数
            }

            return fn(this);                            //查询当前对象
        }
        catch(e) {
            return [];
        }
    }

其中__cache表实现了查询语句的缓存。对于重复的查询,性能可以极大的提升。

复制代码 代码如下:

    function __compile() {
        return eval('0,' arguments[0]);
    }

 __compile之所以单独写在一个空函数里,就是为了eval的时候有个尽可能干净的上下文环境。

__interpret是整个系统的重中之重,负责将查询语句翻译成js语句。它的实现见智见仁,但尽可能简单,不要过度分析语法。

具体代码查看:jsonselect.rar 出于演示,目前只实现部分基本功能。以后还可以加上 LIKE,BETWEEN,ORDER BY 等等常用的功能。

Demo

复制代码 代码如下:

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},
        {name:'娜迦海妖', DP:51, AP:6.0, Str:21, Agi:21, Int:18},
        {name:'赏金猎人', 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},
        {name:'炼金术士', DP:49, AP:0.6, Str:25, Agi:11, Int:25}
        //...
    ];

复制代码 代码如下:

 // 查询:力量,敏捷 都超过20的
    // 结果:娜迦海妖
    var match = heros.select('@Str>20 AND @Agi>20');

    // 查询:“士”结尾的
    // 结果:沉默术士,剧毒术士,炼金术士
    var match = heros.select('right(@name,1)="士" ');

    // 查询:生命值 超过500的
    // 结果:炼金术士
    var match = heros.select('100 @Str*19 > 500');

您可能感兴趣的文章:

  • js 把字符串当函数执行的方法
  • javascript定义函数的方法
  • javascript中使用replaceAll()函数实现字符替换的方法
  • javascript的函数、创建对象、封装、属性和方法、继承
  • 解决火狐浏览器下JS setTimeout函数不兼容失效不执行的方法
  • js函数调用常用方法详解
  • Javascript 判断是否存在函数的方法
  • jquery与js函数冲突的两种解决方法
  • 多种方法实现当jsp页面完全加载完成后执行一个js函数
  • 一个非常全面的javascript URL解析函数和分段URL解析方法
  • JavaScript函数的4种调用方法详解
  • javascript trim函数在IE下不能用的解决方法
  • JavaScript的各种常见函数定义方法
  • PHP使用json_encode函数时不转义中文的解决方法
  • js中匿名函数的创建与调用方法分析
  • js使用split函数按照多个字符对字符串进行分割的方法
  • JS中获取函数调用链所有参数的方法
  • JavaScript子窗口调用父窗口变量和函数的方法
  • 日常收集整理的JavaScript常用函数方法

本文由金沙棋牌发布于金沙棋牌官方平台,转载请注明出处:介绍JavaScript的一个微型模版,查询器的方法介绍

关键词:

上一篇:js的简单教程

下一篇:没有了