用AJAX开发智能Web应用程序之高级篇(1)

ajax|web|程序|高级

一、AJAX语言——对象面向的JavaScript

由定义来看,JavaScript是典型的AJAX语言。不同于Java,JavaScript并不强调OO风格的编码。然而,令人吃惊的是JavaScript居然全面支持所有的OO语言的主要属性:封装、继承和多态性。Douglas Crockford甚至称JavaScript是"世界上最易被误解的编程语言"。让我们回顾一下JavaScript的面向对象的地方吧。

数据类型

在Java中,一个类定义了一个数据和它的相关行为的组合。尽管JavaScript保留了class关键字,但是它不支持与常规OOP语言一样的语义。

这听起来可能觉得奇怪,但是在JavaScript中,对象是用函数来定义的。事实上,通过在下面的示例中定义一个函数,你就定义了一个简单的空类Calculator:

function Calculator() {}

一个新的实例的创建与在Java中相同-使用new操作符:

var myCalculator = new Calculator();

上面这个函数不仅定义一个类,而且还担当了一个构造器。在此,操作符new实现了这一魔术-实例化一个类Calculator的对象并且返回一个对象参考而不是只调用该函数。

创建这样的空类是没错,但在实际中并没有多大用处。下面,我们准备使用一个Java-脚本原型结构来填充类定义。JavaScript使用原型当作创建对象的模板。所有的原型属性和方法被参考引用地复制到一个类的每个对象中,所以它们都具有相同的值。你可以改变一个对象中的原型属性的值,并且该新值会覆盖从原型中复制过来的缺省值,但是这仅对于在一个实例中。下列语句将把一个新属性添加到Calculator对象的原型上:

Calculator.prototype._prop = 0;

既然JavaScript并没有提供一个方法来从句法上表示一个类定义,那么我们将使用with语句来标记该类的定义边界。这也将使得示例代码更为短小,因为该with语句被允许在一个指定的对象上执行一系列的语句而不需要限制属性。

function Calculator() {};

with (Calculator) {

 prototype._prop = 0;

 prototype.setProp = function(p) {_prop = p};

 prototype.getProp = function() {return _prop};

}

到目前为止,我们定义了并且初始化了公共变量_prop,并且为它提供了getter和setter方法。

需要定义一个静态变量?你可以把静态变量当作是为类所拥有的一个变量。因为在JavaScript中的类用函数对象来描述,所以我们只需要把一个新属性添加到该函数上:

Calculator.iCount=0;

现在,既然这个iCount变量是一个Calculator对象的属性,那么它将会被类Calculator的所有实例所共享。

function Calculator() {Calculator.iCount++;};

上面的代码计算类Calculator的所有实例的个数。

封装

通过使用如上面所定义的"Calculator",我们可以存取所有的"class"数据;然而,这增加了派生类中命名冲突的危险性。我们明显地需要封装以把对象看作自包含的实体。

数据封装的一种标准语言机制是使用私有变量。并且一个常用的仿效一个私有变量的JavaScript技术是在构造器中定义一个局部变量;这样以来,该局部变量的存取只能经由getter和setter来实现-它们是该构造器中的内部函数。在下列实例中,_prop变量在Calculator函数中定义并且在函数范围外不可见。其中有两个匿名的内部函数(分别被赋予setProp和getProp属性)让我们存取"私有"变量。另外,请注意,这里this的使用-十分相似于在Java中的用法:

function Calculator() {

 var _prop = 0;

 this.setProp = function (p){_prop = p};

 this.getProp = function() {return _prop};

};

常常被忽视的是在JavaScript中作如此封装所付出的代价。须知,这种代价可能是巨大的,因为内部函数对象对于该"class"的每一个实例被不断地重复创建。

因此,既然基于原型构建对象速度更快并且消费更少些的内存,那么我们在最强调性能的场所特别支持使用公共的变量。请注意,你可以使用命名惯例来避免名称冲突-例如,在公共的变量的前面加上该类名。继承

乍看之下,JavaScript缺乏对类层次的支持,这很相似于面向对象语言的程序员对于现代语言的期盼。然而,尽管JavaScript句法没有象Java一样支持类继承,但是我们仍然能够在JavaScript中实现继承-通过把已定义类的一个实例拷贝到其派生类的原型当中。

在我们提供举例之前,我们需要介绍一个constructor属性。JavaScript保证每一个原型中包含constructor-它拥有到该构造器函数的一个参考。换句话说,Calculator.prototype.constructor包含一个到Calculator()的参考。

现在,下面的代码显示了怎样从基类Calculator派生类ArithmeticCalculator。其中,"第一行"取得类Calculator的所有的属性,而"第二行"把原型constructor的值恢复成ArithmeticCalculator:

function ArithmeticCalculator() { };

with (ArithmeticCalculator) {

 ArithmeticCalculator .prototype = new Calculator();//第一行

 prototype.constructor = ArithmeticCalculator;//第二行

}

就算上面的实例看起来象一个合成体而不象是继承,但是JavaScript引擎还是清楚这个原型链的。特别是,instanceof操作符会正确地适用于基类和派生类。假定你创建类ArithmeticCalculator的一个新实例:

var c = new ArithmeticCalculator;

表达式c instanceof Calculator和c instanceof ArithmeticCalculator都会成立。

注意,在上面示例中的基类的constructor是在初始化ArithmeticCalculator原型时被调用的,而在创建派生类的实例时是不被调用的。这可能会带来不想要的负面影响,而且为了实现初始化你应该考虑创建一个独立的函数。由于该构造器并不是一个成员函数,所以它无法通过this参考引用调用。我们将需要一个能调用超类的"Calculator"成员函数:

function Calculator(ops) { ...};

with (Calculator) { prototype.Calculator=Calculator;}

现在,我们可以写一个继承类-它显式地调用基类的构造器:

function ArithmeticCalculator(ops) { this.Calculator(ops);};

with (ArithmeticCalculator) {

 ArithmeticCalculator .prototype = new Calculator;

 prototype.constructor = ArithmeticCalculator;

 prototype.ArithmeticCalculator = ArithmeticCalculator;

}

多态性

JavaScript是一种非类型化的语言-在此,一切都是对象。因此,如果有两个类A和B,它们都定义一个foo(),那么JavaScript将允许在A和B的实例上多态地调用foo()-即使不存在层次关系(虽然是可实现的)。从这一角度来看,JavaScript提供一个比Java更宽的多态性。这种灵活性,象往常一样,也要付出代价。在这种情况中,代价是把类型检查工作代理到应用程序代码。具体地说,如果需要检查一个参考确实指向一个所希望的基类,那么这可以通过instanceof操作符来实现。

另一方面,JavaScript并不检查函数调用中的参数-这可以防止用一样的命名和不同的参数来定义多态函数(并且让编译器选择正确的签名)。代之的是,JavaScript提供了一个Java 5风格的函数范围内的argument对象-它允许你根据参数的类型和数量的不同而实现一个不同的行为。

二、 示例展示

本文所附源码列表1实现了一个计算器-它可以计算以一个逆向波兰式标志的表达式。该示例展示了本文中所介绍的主要技术并且也介绍了一些独特的JavaScript特性的用法,例如在一个动态函数调用中以一个数组元素的方式访问对象属性。

为了使列表1工作,我们需要另外准备一些代码-它们用于实例化该计算器对象并且调用evaluate方法:

var e = new ArithmeticCalcuator([2,2,5,"add","mul"]);

alert(e.evaluate());

三、 AJAX组件授权

所有的AJAX组件授权方案在今天被逻辑地分成两组。具体地说,第一组用于与基于HTML的UI定义的无缝集成。第二组把HTML当作一个UI定义语言以支持某种XML。在本文中,我们从第一组中来展示一种方法-虽然它存在于浏览器之中却是类似于JSP标签。这些浏览器特定的组件授权扩展在IE情形下称作元素行为,而在最近版本的Firefox,Mozilla和Netscape 8情形下称作可扩展的绑定。

四、 定制标签

Internet Explorer,从版本5.5开始,支持定制的客户端HTML元素的JavaScript授权。不象JSP标签,这些对象并没有在服务器端被预处理到HTML中。而是,它们成为一标准HTML对象模型的合法扩展,并且包括构造控件在内的一切事情,都是动态地发生在客户端的。同样,基于Gecko-引擎的浏览器能够用一个可重用功能动态地装饰任何现有的HTML元素。

因此,我们有可能用具有HTML语法的方法、事件和属性来构建一个具有丰富的UI组件的库。这样的组件可以被自由地混合于标准HTML中。内部地,这些组件将会与应用程序服务器进行通讯-以AJAX风格。换句话说,你有可能(并且相对简单地)构建自己的AJAX对象模型。

这种IE风味的方法被称为HTC或HTML组件;其Gecko版本被称为XBL-可扩展的绑定语言(eXtensible Bindings Language)。为了实现本文目的,我们集中于讨论IE。

[1] [2]  下一页

时间: 2024-09-10 14:30:50

用AJAX开发智能Web应用程序之高级篇(1)的相关文章

用AJAX开发智能Web应用程序之高级篇(2)

ajax|web|程序|高级 •标准HTML复选框不支持"校验"事件以允许取消一个GUI行为,而这种要求可能存在于某些应用程序中. 现在,让我们看一个正在构建的该控件的用法示例,它的用法可能如下情形: <checkbox id="cbx_1" value="N" labelonleft="true" label="Show Details:" onValue="Y" offValu

用AJAX开发智能Web应用程序之高级篇

ajax|web|程序|高级 下载本文源代码 一. 引言 在第一部分中,我们讨论了AJAX基础--建立从脚本到服务器的通讯的能力,这正是使HTML页面具有动态能力的原因所在.然而,这就意味着我们已准备好抛弃我们自己版本的Yahoo邮件吗?不,还没有.原因在于:AJAX是一个混合的祝福.一方面,它使我们能够在Web上创建丰富的桌面级的应用程序:另一方面,如果我们把"翻页面式"的Web应用程序与客户端/服务器或Swing版本的程序进行比较,那么会看到其开发实践并不很相同.我们将需要习惯于这

用AJAX开发智能Web应用程序之基础篇

一. 什么是AJAX? 这个名字代表了异步javascript+XMLHTTPRequest,并且意味着你可以在基于浏览器的javascript和服务器之间建立套接字通讯.其实AJAX并不是一种新技术,而是已经成功地用于现代浏览器中的若干成功技术的可能性组合.所有的AJAX应用程序实现了一种"丰富的"UI--这是通过javascript操作HTML文档对象模型并且经由XMLHttpRequest实现的精确定位的数据检索来实现的.典型的示例AJAX应用程序是Google Labs(htt

用AJAX开发智能Web应用程序之基础篇(1)

ajax|web|程序 一. 什么是AJAX? 这个名字代表了异步JavaScript+XMLHTTPRequest,并且意味着你可以在基于浏览器的JavaScript和服务器之间建立套接字通讯.其实AJAX并不是一种新技术,而是已经成功地用于现代浏览器中的若干成功技术的可能性组合. 所有的AJAX应用程序实现了一种"丰富的"UI--这是通过JavaScript操作HTML文档对象模型并且经由XMLHttpRequest实现的精确定位的数据检索来实现的.典型的示例AJAX应用程序是Go

使用AJAX技术开发新一代Web应用程序(2)

ajax|web|程序 开发新一代Web应用程序(2)-ajax与php web开发">图2 一个独立桌面应用程序的图解架构. 该应用程序运行于其自身的进程之中-在其内数据模型和程序逻辑彼此清晰可见.在同一台计算机上运行的该应用程序的第二个实例除了经由文件系统之外无法存取第一个实例的数据模型.典型地,全部程序状态存储在单个的文件中-当该应用程序运行时它被锁定以阻止任何信息的同步交换. 图3 客户端/服务器系统和n层架构图解. 该服务器提供一个客户可以用之进行交互的可共享的数据模型.客户端仍

使用AJAX技术开发新一代Web应用程序(4)

ajax|web|程序 由于网络潜力的不可预测性,这种可察觉的错误来来去去,并且测试应用程序的响应性也可能变得更为困难.因此,网络潜力是真实世界应用程序具有可怜的交互性的最通常的原因.四.异步客户端 在实际中,我们必须尽量使UI响应独立于网络活动.幸好,一段固定时间的响应经常就足够了,只要它是及时的.让我们再次看一下实际中的问题.我的早上例程的主要任务之一是唤醒我的孩子们上学.我可以站在他们上面戳他们直到他们起床并穿上衣服,但这是一相当花费时间的方式,留下很长的一段时间我几乎无事可做(图8).

使用AJAX技术开发新一代Web应用程序(3)

ajax|web|程序 这并不是在诋毁Amazon,在非常有限的限定内它工作得相当优秀.但是与工作表相比,它所依赖的交互模型毫无疑问相当有限. 那么,为什么在现代web应用程序中存在这么多的限制呢?目前,存在很多技术上的原因.因此,现在让我们作进一步分析.三.网络的潜力 互联网时代的伟大就在于世界各地所有的计算机互相联系,就象在一个非常大的计算资源之中.远程和本地过程调用变得很难区分,并且发行者已经不再清醒地了解它们在哪些物理机器上工作.  不幸的是,远程和本地过程调用是根本不相同的技术. 在网

使用AJAX技术开发新一代Web应用程序

ajax|web|程序 一.引言 一个理想的用户接口对用户最好是不可见的-仅在用户需要时提供选择,否则并不干涉他们的工作而让其专注于手头的工作.然而,这并不是一件容易的事情.如今,我们变得习惯于通过并不十分令人满意的UI进行日常工作,直到有人向我们展示一种更好的方法. 现在,我们才逐渐认识到我们当前的方法在做这些事情时是多么吃力. 由于用于显示文档内容的基本web浏览器技术又被推进一步进而超出以前它们所能及的范围,所以,如今的互联网正在经历着这样的实现. Ajax(异步JavaScript+XM

使用AJAX技术开发新一代Web应用程序(5)

ajax|web|程序 这种客户端方式已经根深蒂固于过去十多年间的每天的商业互联网之中.友好的WYSIWYG web创作工具把我们的站点可视化为一个页面集合.服务器端web框架把这种页面间的转换建模为状态转换图.经典web应用程序,在页面刷新时,与不可避免的缺乏响应紧密结合,不可能容易地求助于异步处理器解决方案. 但是Amazon基于其网站已经取得了商业上的成功.当然,经典web应用程序不可能象那样不可用?为了理解为什么web页面可以适合于Amazon而不适用于每个人,我们应该考虑一下使用模式的