`
javasee
  • 浏览: 961213 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

为脚本语言平反-JavaScript篇(3)

阅读更多

http://blog.csdn.net/aimingoo/archive/2009/09/08/4532496.aspx

(书接上回,继续!)

五、这个DSL框架有什么问题?

=============

有什么问题吗?有一点,并不严重。比如说,我们在Env中声明了一些属性和方法。对于Env这个对象

我们要在calc()方法中访问max/min属性,应该写成“this.max/this.min”,这一则是不方便,另外,在用户的dsl代码中还不得不考虑“当前this是谁”的问题。这是问题之一。

第二个,我们传入了一个evaluator(),相当于脚本执行器,那么我们能不能在dsl()代码中也使用这个执行器呢?也就是说,我们的dsl不单是“domain-specific language”,也可以是一个“domain-script language”的。

第三个问题,我们是不是需要一个类似在JavaScript中的window对象的东西,以便能引用到执行环境的全局。

这三个问题都应该是在DSL()层面解决的。简单说来,第二、三个问题,实质是在初始化环境environment,使之具有某些在dsl代码中能访问到的性质。所以很容易处理:

同理的,用户可以在上面这里对environment加入更多性质,这些都是可以在用户的dsl(…)中访问到的。以上面为例,当用户传入的执行器evaluator是一个具名函数的时候,则该函数名会成为dsl(…)环境中的可用的执行函数(类似于exec, execScript或eval等)。例如:

注意在dsl()访问到的myeval()方法,其实不是用户原始的myeval(),而是上述dsl变量的一个引用。这个,从DSL()函数的实现中可以看到。

接下来,就是上面三个问题中的第一个,亦即是在calc()方法从必须使用this.max/this.min的问题。事实上,这是因为声明calc方法的时候,该函数位于Env变量所在的全局闭包里面。这样,它就默认只能访问到全局的变量、标识符。所以,解决这个问题的方法,仍然和前面一样:改变它的闭包位置——使用Scope()函数。如下:

现在有了一个新的、完善的DSL()。使用方法与前面是一致的。比如:

最后,留意一下当调用DSL()的时候,我们标出了”Env”这个全局变量。注意的是,我们直接使用了这个对象。那么它与使用Unique(Env)有什么不同呢?答案是,直接使用Env时,在dsl(…)中的代码可以直接修改到Env中的成员,而如果使用Unique(Env),则dsl(…)中的代码只会修改到Env的一个副本。这样一来,我们就有机会为不同的dsl语言提供各各独立的环境了——这有点象沙箱。

六、变量泄漏?

========

在JavaScript语言中有一个“根深蒂固”的问题,就是“当在函数内访问一个不存在的变量时,引擎会试图在全局变量环境中打找该变量”。这通常是很多很多烂系统的根源。对于我们上面的dsl语言来说,系统其实只给出了五个标识符:max/calc/show/system/myeval。其中的后面两个,是DSL()函数在“语言引擎层面”提供的,其它的则是Env环境变量提供的。“变量泄漏”带来的直接问题是,对于上面的这个例子,dsl(…)中除了能访问这五个标识符之外,还能访问全局的window/String/Number/Math/RegExp/NaN等等预定义对象和属性。而这,可能根本就不是我们的dsl语言需要的。

这怎么办呢?

由于Unique()得到了Env环境对象的一个副本,而且在dsl(…)中无法通过这个副本来修改原始的Env的成员,也不能delete它。所以如果我们在Env的属性中加入这些“受保护的标识符”,那么dsl(…)就只能访问到Env的这些属性,而不会访问到全局里面的了。下面的代码简单地实现这一效果:

七、evaluator/parser是不是太简单了?

=================

当然。我们在evaluator, parser中基本什么也没有做,当然是相当简单的。如果你要做一个完整的DSL,那么你得花一些工夫来做语法解析,并实现在语法树的基础上的代码执行、运行环境的维护等等。我QoBean的DSL()中,主要是提供了一个运行你的代码的基础语言环境,有点象是——嗯——沙箱。

当然,除了沙箱的基本功能之外。DSL()通过environment来维护给用户代码的一组基本标识符(或称为保留字),并保证用户在不同的environment之间不会相互影响。

除了上述的基本描述之外,我们最后再关注一下evaluator和parser的实现。对于下面的代码:

实际上的效果是dsl()将红色显示部分的函数作为一个一个参数source,传入myparser()和myeval()。parser通过Block()取出这个函数代码的body部分,然后交给myeval()中的eval()函数执行。也就是说,我们在DSL()中调用Weave()的效果就是,将myparser()和myeval()并在一起,变成了:

而dsl()最终执行的就是上面这个匿名函数。更进一步,在environment上也会有一个名为’myeval’的方法,指向这个匿名函数。

但是,首先这里就有一个不小的问题:’source’在这里也是一个标识符。在eval(…)中执行时,代码是可以感知到这个标识符的——而对于dsl(…)中的用户代码,source可能是另外需要的一个标识符,所以这里我们要想办法屏蔽掉对这个变量名的依赖。这其实处理起来很简单:

你应该注意到,我们用arguments[0]就可以简单地绕过一个入口参数名的使用了。这个,很简单,也很实用。

接下来,我们总不能要求用户每次执行dsl(…)时都要传入一个函数吧?我们最终声明的用户的DSL可能是相当怪异的、完全不符合JS的语法的,根本就不能写到一个函数中去,又该怎么办呢?这个问题,显然的——首先的——他该是parser的问题。因此我们也就简单地讲一下扩充myparser()的方法。比如说,我们想实现下面的效果:

  1. 当dsl(…)传入一个字符串时,让myeval()直接执行该字符串;
  2. 当dsl(…)传入一个函数,但函数体内是完整的整块注释时,让myeval()执行这个注释块。

例如如下的调用:
=========

现在我们需要进一步完善我们的myparser(),提供一个基本的模式来支持这种设计。简单的方法如下:

当然,由于代码的语法规则改变了,所以myeval()的设计也应该发生相应的变化了。而这些,就应该是DSL语言设计者的工作,而不是QoBean在DSL()框架上要考虑的事情了。

八、终结:DSL,关键不在用什么语言实现,而在于为什么Domain设计什么样的语言

=============

我们用Javascript,只写了不到了10行代码,就实现了一个DSL()的通用框架,但是,我们却没有做出对任何一个真实的Domain有意义的DSL。对于Ruby、Python、Erlang还是Scala,或者更原始的LISP或更新的F#这些基础语言,对他们的选择更多的只是喜好或者出于某些局部的优异与方便的考虑,与我们“设计一个DSL”是没有多大的关系的。一个DSL的设计,在于对领域的、领域相关业务的分析与抽象。在这些分析、抽象的基础上,进行语法设计、语义定义,最终才表现为“怎样的一个语言”。当我们看到这个“表现”的时候,整个DSL的设计都已经结束了——我们接下来只需要构建基本运行库(runtime library),以及其上的应用逻辑就好了。所以,大多数看到某个DSL的人,只是它的实现者和使用者,而不是它的设计者。多数人只是埋头于使用,或者激情于评说,而忘了看看“一个具体DSL的背景”。

例如,难道DOS批处理不是一个DSL吗?10行的JavaScript难道不就是一个完整的DSL framework吗?如果是,那么我们还有必要讨论“什么是DSL”,以及“怎样的DSL开发环境更好”的问题吗?我们是不是看看“我们在什么Domain”,以及“这个Domain如何描述、如何结构化和如何逻辑驱动之”,这些问题是不是才是更关键的?


上面两个示例中都有一个相同的dsl代码片断——这是一种假想的、完全不符合javascript的规范的新语言。示例1是通过一个字符串传给dsl()的,示例2仍然是通过一个函数,但函数体内是从/*..*/的一个注释块。

分享到:
评论

相关推荐

    photoshop-cc-javascript-ref-2019.pdf

    1. **JavaScript在Photoshop中的应用**:JavaScript是一种广泛使用的脚本语言,它在Photoshop中允许用户通过编写脚本来自动化重复任务,创建自定义工作流程,以及扩展Photoshop的功能。这包括调整图像参数、处理图层...

    Photoshop-CS6-JavaScript.zip

    3. **Photoshop API**:Adobe提供了丰富的API,允许开发者通过JavaScript访问Photoshop的功能。例如,你可以用JavaScript来创建、修改或保存文档,调整图像属性,处理图层,或者实现批量处理任务。 4. **事件处理**...

    网页javascript脚本语言提取器

    JavaScript是一种广泛应用于网页开发的脚本语言,它允许在用户浏览器上动态地更新内容,实现交互性和动画效果。"网页JavaScript脚本语言提取器"是一个工具,专门设计用于从网页中抓取并分析JavaScript代码,这在进行...

    javascript脚本语言课件

    JavaScript脚本语言是一种广泛应用于网页和网络应用中的编程语言,主要负责实现客户端的交互性和动态效果。本课程针对JavaScript的基础知识进行深入讲解,包括语法、流程控制语句、函数以及数据验证方法,旨在帮助...

    WEB中javascript脚本语言

    JavaScript是一种广泛使用的脚本语言,主要用于Web前端开发,可以实现动态效果、交互功能等。JavaScript与HTML和CSS一起构成了现代Web开发的基础。 #### 二、基本示例 1. **生成文本** ```html ...

    大学毕业设计---javascript脚本病毒的编写与防范方法研究.doc

    大学毕业设计---javascript脚本病毒的编写与防范方法研究.doc

    JavaScript应用实例-脚本商店界面-增加点击事件.js

    JavaScript应用实例-脚本商店界面-增加点击事件.js

    廖雪峰-JavaScript教程-PDF版

    JavaScript作为世界上最流行的脚本语言之一,在Web开发领域占据着举足轻重的地位。无论是个人开发者还是大型企业,都离不开JavaScript的支持。本教程旨在帮助初学者快速掌握JavaScript的基础知识,同时也适合有一定...

    奔梦向前-表白代码脚本-2020-04-28-1.zip

    奔梦向前:学编程其实很简单,html、css、JavaScript、html5、css3、vue、Canvas实现网页特效页面、新手入门学习、了解网页动画的制作、代码实现网页动态画面-表白代码脚本-2020-04-28-1。

    CGI脚本入门学习--HTML格式

    你应该用什么编程语言? 你的服务器设置正确吗? 如果你的服务器不是UNIX系统呢? 解剖CGI脚本 输出头部 输出数据部 带阐述的脚本 传递其他信息给脚本 创建特殊的脚本输出 以装载另一个文本响应 无响应 ...

    JavaScript

    JavaScript基本数据结构 3-JavaScript程序构成 4-基于对象的JavaScript语言 5-在JavaScript中创建新对象 6-JavaScript对象系统的使用 7-JavaScript窗口及输入输出 8-用JavaScript脚本实现Web页面...

    浅谈关于JavaScript脚本语言的学习.pdf

    3. 基于对象和事件驱动:JavaScript脚本语言自身提供了对象,如Math对象、String对象、Date对象等等,还可以使用浏览器对象,如window对象、document对象等,不需要创建类就直接可以使用或通过创建一个新对象来设置...

    如何在C++程序中嵌入JavaScript脚本语言.pdf

    如何在C++程序中嵌入JavaScript脚本语言.pdf

    javaScript-javascript-初级到高级-笔记PDF

    113.javaScript:它和标签语言都属于描述性的语言,用于和html结合从而强化网页数据的展现,虽然语法和结构上和java类似,但实际上它是和java完全不同的一门语言,它只是函数式的语言,其实从字面意思看,它就是java...

    javascript课件-javascript初步

    JavaScript是一种轻量级的、基于对象和事件驱动的脚本语言,主要应用于Web页面中,为用户提供交互式体验。它由Netscape公司开发,起初名为Live Script,后来改名为JavaScript,以利用当时流行的Java语言的知名度。...

    第四章 VBSCRIPT脚本语言简介

    【VBScript脚本语言简介】 VBScript(Visual Basic Script Edition)是一种轻量级的脚本语言,主要用于Web开发,特别是ASP(Active Server Pages)环境中。它不能独立运行,必须嵌入到HTML文档中,由浏览器或服务器...

    javascript-learning-Javascript学习

    JavaScript是一种高级的、动态的、基于对象的脚本语言,主要用于客户端的脚本编程。它可以使网页更加interactive和动态。其次,选择合适的学习资源。有很多在线资源可以学习JavaScript,例如视频教程、博客、书籍等...

    javascript脚本语言

    `language`属性和`type`属性用于指定脚本语言类型,尽管现在大多数浏览器默认识别`<script>`标签中的JavaScript,但为了兼容性,这两个属性仍然会被使用。 **5.2 JavaScript语言基础** JavaScript的基础包括变量、...

    javascript经典特效---在线考试脚本(一).rar

    在线考试脚本是一种基于网页的交互式测试系统,它利用JavaScript等前端技术实现用户界面的动态交互和数据处理。在本案例中,"javascript经典特效---在线考试脚本(一)"是一个专门探讨如何使用JavaScript来构建这样的...

    C# 动态解析 javascript 脚本引擎源码

    而JavaScript则是Web开发中的主要脚本语言,它在浏览器环境中运行,为网页添加交互性。本主题涉及的是如何在C#中动态解析和执行JavaScript代码,这通常通过使用脚本引擎来实现。 一个常见的C#脚本引擎是Microsoft的...

Global site tag (gtag.js) - Google Analytics