2008-03-15
JavaScript与Rhino
声明:任何使用该文档内容必须经过作者的同意。
声明:请点击广告,支持作者原创。
1 概述
ECMAScirpt是个基于对象的语言,目的是在宿主环境中进行计算和维护可计算的对象。Script是编程语言,用来维护,定制和已经存在的系统的机制。在这样系统中,已经通过用户界面提供了有用的功能,而script是一种机制,用来暴露该功能,并且能够编程控制,那么已经存在的系统就称为宿主环境(host environment)。Script语言目的是让专业和非专业人员能够使用,因此语言没有那么严格。1.1 WebScripting
浏览器提供了ECMAScript的宿主环境,用来C/S计算,提供了窗口、菜单、对话框、文本区、链接、框架,历史,cookie,输入/输出等对象。宿主环境提供一种手段来将脚步代码跟事件联系起来,如焦点改变,页面和图片装载,卸载,错误和退出,选择,窗体提交和鼠标动作。脚本代码是在html代码中,而显示页是文本和图片的综合体。1.2 LanguageOverview
ECMAScript是基于对象的:由对象提供基本语言和宿主机制。ECMAScript程序是一组通信对象的集合。ECMAScript的Object是properties的无序集合,每个properties可以多个attribute。Properties是容器,可以拥有其他对象,primitive values和methods。Primitive value是下面内置类型之一:Undefined,Null,Boolean,Number和String。Object是内置类型Object,而method是通过property关联的function。ECMAScript定义一组内置对象。内置对象包括Global,Object,Function,Array,String,Boolean,Number,Math,Date,RegExp和各种Error对象。ECMAScript定义了内置的操作符。
1.3 Object
ECMAScript没有class的概念,因此构造一个对象的时候不是像java一样构造对象,也没有单独的构造体方法。
Constructor是Method的一种。
ECMAScript支持prototype-based的继承。
在java中,继承是扩展原有的方法。但JavaScript中,方法只是对象的其中一个属性,例如: squart:function(){return true}.因此,如果要扩展squart属性的话,如何扩展呢?javascript应该没有提供扩展原来方法的功能,没有super.squart,只能够重新定义。在java中,继承是通过extends Object来实现的。但javascript却没有extends的概念。Javascript中对象是由一组属性构成。属性可以基本类型,也可以是Function类型。
1.4 定义
1.4.1 Constructor
构造体,构造体当然是Function对象了,目的是创建和初始化对象。
每个constructor都有相关的prototype对象,用来实现继承和共享对象。
这表明javascript的构造体不同于java中的表示。Java中的构造体表示是:Public Point(){
}
javascript的构造体更像是Delphi中的表示:procedure construct(){
}
因为每个对象都有构造体,最基本的构造体就称为prototype。1.4.2 Prototype
每样的东西都要原来的最基本的样子。例如,所有的java的类都扩展Object,那么Object类里面的所有的东西都是其最基本的样子。
Prototype是一个对象,用来实现结构,状态和行为的继承。
当constructor创建一个对象,该对象就隐含了引用构造体相关的原型。
构造体关联原型用程序constructor.prototype表示。添加到原型中的属性是共享的。
Prototype类似java中的基本类Object。Constructor.prototype相当于super.constructor。
1.4.3 NativeObject
独立于宿主环境的对象就是本地对象。
1.4.4 Built-inObject
内置对象,由ECMA规范定义的对象。
在ECMAScript中attribute的定义是下面几种:readonly,dontenum,dontdelete,internal。相当于java中的修饰符。1.4.5 Object
注意ECMAScript规范对Object的定义,不同于其他语言:
Object – an unordered collection of properties。每个property由name,value和一组attributes构成。在其他语言系统中,例如Delphi,它明确定义一个组件是由property/event/method构成的。在java中,没有单独定义event。它把event和method放在一起。Delphi是直接面向GUI的,而java不是。每个对象必须实现prototype和class属性,和get/put/canPut/hasProperty/delete/defaultValue方法。[[prototype]]property的值必须是object或者null。而prototype链必须有有限的长度,也就是从某个对象开始,递归访问prototype属性,最终会访问到null值。1.4.6 内在方法
下面方法并非是javascript的语言中定义,而仅仅是表述而已。
■ object.get(propertyName)
(1) 如果object没有propertyName,跳到4。
(2) 读取property对应的propertyValue。
(3) 返回结果2。
(4) 如果object的prototype为null,返回undefined。
(5) 调用prototype的get(propertyName)。
(6) 返回结果5。
■ object.put(propertName,propertyValue)
(1) 调用canPut(propertyName)
(2) 如果1返回false,返回。
(3) 如果object没有propertyName,跳到6。
(4) 设置property的值为propertyValue,其attribute没有改变。
(5) 返回。
(6) 创建一个名称为propertyName的property,并且设置值为propertyValue,设置empty attribute。
(7) 返回。
■ canPut(propertName)
■ hasProperty(propertyName)
■ delete(propertyName)
■ defaultValue
1.4.7 Reference类型
1.5 Execution Contexts执行上下文
1.5.1 Function Objects函数对象
有两种类型的Function Objects:
◆ 编程函数由js文件中定义,通过FunctionDeclaration或者FunctionExpression或者使用内置的Function对象作为构造体。
即:
function xxx(){
return true;
}
function (){ return true;}
new Function(“”,”return true”);
◆ 内置函数,如parseInt和Math.exp等,由语言解析器提供。
1.5.2 可执行代码的类型
有3种类型:
2 Rhino
Rhino是javascript的解析引擎。
2.1 ContextFactory
◆ 提供singleton的方式获取ContextFactory。
◆ 包含了一个事件监听接口。
◆ 包含对事件监听器的添加和删除管理。
◆ 提供了Context.enter/exit的方法。
◆ 提供几个protected方法,用来扩展ContextFactory。MakeContext()/hasFeature()/observeInstructionCount()/onContextCreated/onContextReleased
◆ 定义一个变量sealed,如果设置sealed为true的话,则不能添加删除事件监听器。
2.2 Context
◆ 提供Context的几个静态方法:获取当前的Context,enter/exit的方法。
◆ 提供seal/unseal操作,每个seal都有key。
◆ 提供languageVersion语言版本、实现版本、Locale、ErrorReporter和相关的report的便利方法。
◆ 提供PropertyChangeListener的事件管理。
◆ 提供Call的静态方法。
◆ 提供initStandObjects()的静态方法。
◆ 提供evaluateString/evaluateReader解析方法。
◆ 提供compileString/compileReader/compileFunction编译方法。
◆ 提供decompileScript/decompileFunction/decompileFunctionBody反编译方法。
◆ 提供newObject/newArray创建方法。
◆ 提供将对象转变为基本类型的方法toBoolean/toNumber/toString/toObject
◆ 提供编译优化等级,最大解析堆栈深度,安全控制器,InstructionObserverThreshold等的读取和设置。
◆ 提供key-value存放到ThreadLocal的添加删除保存方法getThreadLocal/putThreadLocal/removeThreadLocal。
2.3 ScriptRuntime
2.4 initStandardObjects(Context cx, ScriptableObject scope, boolean sealed)
如果scope为空,就新建一个NativeObject来作为全局对象。如果设置了scope了,则用其来作为全局对象。
然后就将其存放在关联表中,用LIBRARY_SCOPE_KEY作为关键字,用新建的NativeObject作为值,存放在新建的NativeObject中。
2.5 ScriptableObject
Javascript对象的基本类。
◆ 定义了四种属性(attribute):empty/readonly/dontenum/permanent.
◆ 对attribute提供了get/set的方法。Attribute是用常量定义的。
◆ 对property提供了has/get/put/delete的方法,property由propertyName和propertyValue构成的。
◆ ScriptableObject的构造体由parentscope和prototype构成,提供了get/set父亲scope和prototype的方法。
◆ 提供getDefaultValue()方法。
◆ 提供defineClass静态方法:defineClass是将java编写的类转变为javascript对象。不过编写java类要遵循一定的规则。其规则为:
▲ 函数要用jsFunction_、jsStaticFunction_表示.
▲ Get/set要用jsGet_、jsSet_表示。
▲ 构造体要用jsConstructor表示。
◆ 提供defineProperty静态方法:将propertyName,propertyValue和attributes设置到javascript对象中。提供多种定义property的方法:
可以根据propertyName/propertyValue/attributes设置。
可以根据 propertyName/JavaClass/attributes设置。
可以根据propertyName/delegateTo/getter/setter/attributes设置。
函数是Javascript对象中的一个特殊的propertyName,defineFunctionPoperties就是根据functionName/function/attributes保存到property中的。
Property在ScriptableObject中是由Slot类表示的,每个slot包含propertyID/propertyName/propertyValue/attributes。很明显,property是用List来管理的。◆ 提供获取prototype的静态方法:getObjectPrototype/getFunctionPrototype/getClassPrototype.
◆ 提供获取顶层scope的方法getTopLevelScope。
◆ 提供下面静态方法:读取propertyValue,hasProperty,putProperty,deleteProperty的静态方法。
◆ 提供callMethod静态方法,callMethod要求输入javascript对象的方法名称和参数。实现原理是查找javascript对象的方法名对应的函数。然后进行fun.call来执行,得到函数执行的结果。
◆ associateValue(key,val


评论