用户操作
[即时聊天] [发私信] [加为好友]
寒冬ID:dead_of_winter
19680次访问,排名6329,好友3人,关注者6人。
from ATC
dead_of_winter的文章
原创 41 篇
翻译 1 篇
转载 13 篇
评论 21 篇
最近评论
dead_of_winter:prototype只是特定时代的东西 几个极其稀有的“高手”把自己的公共代码分享出来给大家用 根本说不上是框架
prototype只用了一行代码 就能让我们这些程序员彻底对它绝望:
RegExp.prototype.match = RegExp.prototype.test;
mackyliu:显然选用框架的人大多数只是应用者,对于许多真正的开发者来说,可能更多的只是选用各个框架里比较优秀的一小段代码而已,prototype的确"污染了"许多对象,但使用者似乎也根本不需要去考虑对象的实质应用处理过程,有好的类来替代一个相对复杂的处理过程,无疑是菜鸟们的一大福音。然而对于我们搞程序的人来说,可能更多的会去关注一个框架的扩展性
dead_of_winter:hoho 不是这样的 QQ上详细说吧:)
BlueDestiny:循环引用是三者之间(或三者以上)的相互引用,只用切断其一就可以了
<html>
<head>
<script language="JScript">

var myGlobalObject;

function SetupLeak()
{
// First……
dead_of_winter:我不怀疑prototype作者的水平 不过它写得实在太随意了 不像是写框架的态度
还有啊 pt该补习下OO基础知识了 Insertion这种东西最好就别出现了- -#
YUI有多好先不说 起码这些基本的地方做得不错
文章分类
收藏
    相册
    贴图
    ACM
    哈尔滨工程大学ACM
    .net framework3.0
    中国科技大学ACM
    俄罗斯乌拉尔大学ACM......
    北京大学ACM
    吉林大学ACM(故障?)
    同济大学ACM
    哈尔滨工业大学ACM
    四川大学ACM
    天津大学ACM
    暨南大学珠海学院ACM
    杭州电子科技大学ACM
    汕头大学ACM
    浙江大学ACM
    CSDN BLOGS
    50米深蓝
    chenhu_doc
    一刀流
    小三
    搜索如风
    程化
    雁南飞
    泡的bbs
    无忧脚本
    资源
    WindowsAPI参考
    wpf(RSS)
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 javascript设计模式交流(四) ——Interpreter Pattern 收藏

    新一篇: JavaScript设计模式交流(三)——Templete Method Pattern  | 旧一篇: 面向对象之惑

    解释器模式听起来高高在上,但它其实应用广泛而且非常实用,javascript是一门解释型语言,它的大多数引擎(Actionscript是一个特例)都是解释器,解释器的实现十分复杂,然而解释器模式并非如此 ,思想上解释器模式借鉴了解释器的实现,但根据需要,也可以用很简单的代码实现。

    在GOF book中这样解释它的意图:给定一个语言,定义它文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

    这听起来十分复杂,但是事实是,语言可以自由设定,所以它的实现可能非常简单。举个例子,假如我用wsad来代表上下左右,那么一个wasd组成的字符串即可表示一条二维空间内的路径,它的每个"句子"即是一个字母,那么实现一个根据wasd序列来显示相应路线的解释器并不困难。更进一步,可以把一个解释器看作是由字符流作为参数的复杂函数,它的复杂程度取决于字符流的格式。

    解释器模式执行速度通常不快(大多数时候非常慢),而且错误调试比较困难(附注:虽然调试比较困难,但事实上它降低了错误的发生可能性),但它的优势是显而易见的,它能有效控制模块之间接口的复杂性,对于那种执行频率不高但代码频率足够高,且多样性很强的功能,解释器是非常适合的模式。此外解释器还有一个不太为人所注意的优势,就是它可以方便地跨语言和跨平台。

    解释器模式在js中有两个最典型的应用json和正则表达式,对js程序员来说,这应该是很熟悉的两种东西。json用于序列化对象型数据,这个js的对象文字量形式在包括C++,Java在内的各种语言中都有实现的类库,在一些ajax应用中,java或者C#中的对象被序列化为json格式,通过相应客户端的http请求传递给客户端的js程序,js几乎不需要任何处理,仅仅使用eval就可以把json格式的数据还原成js对象(因为json恰巧是来自js),这在解释器模式的实现中是很少见的。现在,不仅仅使与js相关的应用,即使在其他语言的应用中,json也是一种很受欢迎的数据交换格式。正则表达式是js的内置对象,它可以说是最著名的解释器模式了,几乎所有语言中都有它的实现,现在它已经几乎是字符串匹配的事实标准。它能处理字符串的各种格式,有效地避免了过于复杂的string对象接口或者大段的字符串分析代码,这对开发效率至关重要。js的实现是一个比较强的版本,相比java和C#等语言,js允许函数参数为它提供了更大的灵活性。

    本文将讨论如何用解释器模式解决问题以及在javascript中运用语言特性实现解释器模式。

    词法分析·状态机的实现

    通常解释器模式需要将所定义的"语言"字符流转换成适合的程序数据结构,再对这个结构进行分析。对于比较简单的情况,转换和分析可以在一步完成。为了很好好的完成这项工作,我们需要实现一个状态机。

    状态机原本不是软件和程序中的术语,在数字逻辑中有限状态机是指输出取决于过去输入部分和当前输入部分的时序逻辑电路。这里甚至无需强调有限状态机,可以简单理解状态机为一个黑箱子,向其中投入指令后即可进行操作和装换状态,它有一个最终状态,当到达最终状态时,即可完成任务。

    词法分析有限状态机任务很简单,从输入字符流中读入一个一个的字符,当辨认出输入的字符能构成一个独立的语法单元(token)时,便将这个token放入待分析的词句流中。

    这里给出一个简单的例子:正斜杠转义的实现。通常字符串转义都是以反斜杠\实现的,假如有一个字符串,现在我们要把正斜杠用作转义符以做一些特殊用途,其他字符原样放置。那么正斜杠/和它后面的字符必须被看成一个整体,其它每个字符都是一个整体。

    这个状态机只有两个状态 第一个状态是读入普通字符状态 第二个状态是读入正斜杠以后的状态 状态图如下

    在js中 充分利用语言特性 将每个状态实现为一个函数 它接受一个状态改变参数 然后返回下一个状态

    <script>

    function state_machine()
    {
        
    this.state=_1;
        
    this.resault=[];
        
    function _1(c){
            
    if(c!='/'){
                
    this.resault.push(c);
                
    return _1;
            } 
    else {
                
    return _2;
            }    
        }
        
    function _2(c){
            
    this.resault.push('/'+c);
            
    return _1;
        }
        
    this.change=function(c){
            
    this.state=this.state(c);
        };
    }
    var sm=new state_machine();
    var queue=("a//sd/jh/ds").split('');

    for(var i=0;i<queue.length;i++)
       sm.change(queue[i]);

    alert(sm.resault);

    </script>

     这是一个标准的状态机处理词法分析的例子,事实上,有些简单的解释器模式,仅仅通过词法分析即可实现,功能可以写在状态改变函数中,而无需对产生的token流进行处理。

     函数式语言特性与状态机模式

    作为函数式语言,js实现解释器模式有非常有趣的方式:以不定个数的参数形式传入函数进行处理,这样可以方便的扩展功能,同时可以使用户更自由的使用解释器提供的接口。

    下面一段代码是一个用于日期对象的格式化的类 它是状态机词法分析的一个稍微复杂的例子,同时它以函数参数的方式为用户提供了扩展功能。

    /*
    DateEx类
    说明:以参数形式继承自Date对象 为Date对象扩展方法
    方法:
        format(formatString,[fun],......)
        参数:
            formatString:格式字符串 将日期转换成所规定的格式字符串
                格式说明:
                    %[x]:
                        [x]代表日期的一个部分
                    %y:年
                    %m:月
                    %d:日
                    %w:星期
                    %h:小时
                    %i:分
                    %s:秒
                    
                    %[num][x]:
                        [num]代表长度 [x]意义同上 如果长度不足则用0补齐 如果长度超出[num]则将高位截断
                        
                    %f[x]:
                        以自定义函数处理%[x]得到的值,自定义函数在参数列表[fun]中给出,参数中[fun]的个数应与%f[x]的数目一致
                   
            
            fun:可选的,处理函数,当格式字符串中有格式符%f出现时,则在fun中取相应的函数处理
    */
    function DateEx(date
    ){
        
    date=date||new Date
    ();
        
    date.format=function(formatString
    )
        {    
            var 
    f
    ;
            var 
    j=0
    ;        
            function 
    fbuilder(n
    ){
                return function(
    v
    ){
                    var 
    s=v.toString
    ();
                    if(
    s.length>=n)return s.slice(s.length-n,s.length
    );
                    if(
    s.length<n)return new Array(n-s.length+1).join(0)+s
    ;
                };            
            }
            var 
    args=arguments
    ;
            var 
    resault=new String
    ();
            var 
    _1=function(c)
    //状态1 是读入格式字符串的状态 
            
    {
                if(
    c!="%")
    //对于非%字符按原样输出 
                
    {
                    
    resault+=c
    ;
                    return 
    _1
    ;
                }
                else
    //读到%时进入状态2 否则延续状态1
                
    {
                    return 
    _2
    ;
                }
            };
            var 
    _2=function(c)
    //状态2 是读入特殊格式字符串的状态
            
    {
                if(
    c.match(/d/)!=null)
    //对于数字 构造相应处理函数 返回状态3
                
    {
                    
    f=fbuilder(Number(c
    ));
                    return 
    _3
    ;
                }
                else if(
    c=="f")
    //对于格式符f 从参数中获取相应处理函数 返回状态3
                
    {
                    
    f=args[++j
    ];
                    return 
    _3
    ;
                }
                else
    //没有特殊格式符 直接进入状态3
                
    {
                    
    f=function(v){return v
    ;}
                    return 
    _3(c
    );
                }
                
                
            };
            var 
    _3=function(c
    )
            {
                if(
    c=="%")
    //格式符% 连续2个%将被转义为一个% 返回状态1
                
    {
                    
    resault+=c
    ;
                    return 
    _1
    ;                
                }
                else if(
    c=="y")
    //格式符y 取出年份 返回状态1
                
    {
                    
    resault+=f(date.getFullYear
    ());
                    
                    return 
    _1
    ;
                }
                else if(
    c=="m")
    //格式符m 取出月份 返回状态1
                
    {
                    
    resault+=f(date.getMonth()+1
    );
                    return 
    _1
    ;
                }
                else if(
    c=="d")
    //格式符d 取出日期 返回状态1
                
    {
                    
    resault+=f(date.getDate
    ());
                    return 
    _1
    ;
                }
                else if(
    c=="w")
    //格式符w 取出星期 返回状态1
                
    {
                    
    resault+=f(date.getDay
    ());
                    return 
    _1
    ;
                }            
                else if(
    c=="h")
    //格式符h 取出小时 返回状态1
                
    {
                    
    resault+=f(date.getHours
    ());
                    return 
    _1
    ;
                }
                else if(
    c=="i")
    //格式符i 取出分 返回状态1
                
    {
                    
    resault+=f(date.getMinutes
    ());
                    return 
    _1
    ;
                }
                else if(
    c=="s")
    //格式符s 取出秒 返回状态1
                
    {
                    
    resault+=f(date.getSeconds
    ());
                    return 
    _1
    ;
                }
                else return 
    _1
    //没有合法格式符 忽略 返回状态1
            
    };        
            var 
    status=_1
    ;
            for(var 
    i=0;i<formatString.length;i
    ++)
            {
                
    status=status(formatString.charAt(i
    ));
            }
            return 
    resault
    ;
        }
        return 
    date
    ;
    }
    var 
    weekdays=
    "日一二三四五六"
    document.write(new DateEx().format("%2y-%2m-%2d 星期%fw %2h:%2i:%2s %%",function(v){return weekdays.charAt(v);}))

    动态语言特性·eval与解释器模式

    js的另一个非常有趣特点是它本身是一门解释型语言,它允许用eval和Function等方式调用其本身的解释器引擎,这样给解释器的实现带来了很大的方便,可以将某段自定义语言(如代数运算或者布尔运算不分)作为一个独立的token用eval直接执行,这种形式的解释器是静态语言无法比拟的

    发表于 @ 2008年03月08日 16:08:00|评论(loading...)|编辑

    新一篇: JavaScript设计模式交流(三)——Templete Method Pattern  | 旧一篇: 面向对象之惑

    评论:没有评论。

    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © 寒冬