作者没有看过netscape的文档,也没有看过ECMAScript(ECMA-262)规范,仅仅看msdn是不能真正懂得javascript的。 > 面向对象的JavaScript编程 JavaScript虽然可以认为是一个对象语言,但是与大家熟悉的c++,java不同。主要的区别在于:
很多人都仅仅玩弄js技巧,其实是半瓶水的表现。在浏览器中过分卖弄js,却不懂得写noscript标签,这是典型的还没有明白web之道的表现。DHTML这种厂商对抗的东西已经没有什么好说的了,大家自己去看DOM标准吧。顺带说一下,netscape有js的guide和reference,建议真正想深入js的人至少要去看一遍,msdn上对js语言的解说虽然一个版本比一个版本多了,但是始终是不如创造语言的公司说得清楚。或者推荐大家看奥莱理的《js权威指南》,我随手翻过,是有史以来最好的js书之一。 > Javascript不是一个支持面向对象的语言,更加算不上一个开发平台,但是Javascript提供了一个非常强大的基于prototype的面向对象调用功能,你可以在你自己需要的地方使用他们。因此,如何使用对象?本文尽可能从Javascript面向对象实现原理出发,解析清楚它的工作模型。在了解这些模型之后,你可以在自己的脚本库中编写一些实现代码,然后在其他地方调用。 作者这里说的对的,js本身是脚本语言,而且是依赖于host的语言(根据ecma规范的说法),因此很多人关于js如何如何的说法都是错误的,因为他们说的是dhtml或者dom,总之是浏览器环境,而不是js语言的特性。ms的dhtml可以用于js和vbs,DOM是语言独立的。js本身是单纯的语言,虽然主要以浏览器环境为设计目标,但并不影响他在其它环境中发挥作用。例如可以作为服务器端脚本,比如asp(虽然多数用vbs),或者jsp的一种脚本语言(注意js不是jsp,jsp通常使用java作为脚本语言,但是也可以用其他脚本语言)。“基于prototype的面向对象调用功能”这句话就有问题了。prototype不是调用功能,而是语言的机制。而且“面向对象”的提法也不完全准确。从术语使用上讲,面向对象一般指c++,java,smalltalk等,js只被叫做“基于对象”的,当然我觉得这也不是很重要。 > Javascript的语法和C++很接近,不过在类实现中没有使用关键字Class,实现继承的时候也没有采用传统的Public或者Implement等等所谓的关键字来标示类的实现。这样的情况下,可能有就有人会问,如何编写Javascript的Class,如何实现继承。我开始也是百思不得其解,后来看了MSDN,才知道采用了prototype来实现,包括继承和重载,也可以通过这个关键字来实现。 js的语法是c一路的(java,c#也是)。不仅是没有关键字class那样,严格来说,js没有类的(当然也没有继承一说了)。但是通俗来说,可以认为,js中有类似“类”的东西。顺带说c++不是“完全”的对象语言,因为缺乏“类对象”,呵呵(不过这是语言的不同设计,未必是缺点)。至于imp,那是接口了,许多语言没有明显接口而用多重继承、虚类、抽象方法来模拟,比如c++。prototype并不只是一个关键字,而是js的特质之一。如何继承,虽然你可以从msdn摸索,不过是事倍功半,还是再劝你直接看netscape的guide,或者mozilla上也有。 > Javascript的函数很奇怪,每个都是默认实现了Optional的,即参数都可以可选的,function a(var1,var2,var3),在调用的过程中a(),a(value1),a(value1,value2)等等的调用都是正确的,至少在即使编译部分可以完整通过,至于其它,只是和函数的实现逻辑比较相关了。 这没有什么奇怪的,只是js的许多特性(动态类型,没有同名函数……)的结果。补充一个,在function之内,可以用arguments像数组一样操作参数。 > 以下就JS对于类的实现、继承、重载详细介绍其实现方式。 应该这样说,js没有类,但是js中,一切都是对象,包括函数。因此类可以通过做一个构造函数(注意,构造函数是来构造对象而不是构造类的)来模拟。 > 对于类的属性,可以通过两种方式实现 先纠正用词,这里不是调用而是赋值。 > 这两种方式从目标来看是一致的,按照我个人的观点来看,区别的只是在于实现方式,通过this.propertyName的方式来创建,Jscript自动创建了property或者method的入口,不过从程序的角度而言,还是使用prototype的关键字实现比较灵活。 这两种方法效果基本一致,但是还是有比较重要的区别,即前者是在构造函数里赋值,后者则是从外部通过原型对象赋值。如果有比较复杂的“类层次”,你就会发现两者的不同,还有顺序问题了 :) 后者是更灵活,不过要知道js是完全动态的语言,你甚至可以动态改变constructor,呵呵。 > 另外Javascript也可以和我们C++中那种嵌套声明的方法来声明,C++实现的方法如下 顺带说一下,作者过分使用了object.prototype.prop = value 的方法,这其实并不好。因为这破坏了“类”的结构。除了直接赋值原型对象来模拟继承,如无必要,不应使用。 > 如上的代码大致演示了Javascript类中属性和方法的实现,另外有一点比较困惑,整个class中都是public的,没有关键字private之类的可以控制某些方法是否隐藏,那么在我们编写代码实现的规范中,我看国外一些程序员都是使用_functionName这样子为函数命的方法来区分,但是在调用过程中实际还可以调用的。 public之类的,只是为了增加语言的可靠性,对于脚本语言来说,并不是必须。 > 实现了属性和方法,剩下的就是Event的实现了,我查找了许多资料,包括整个MSDN关于JScript的参考,都没有看到一个很好的模型关于事件实现的,后来参考了一些站点编写HTA(HTML Component,有空我会写一些相关的文章)的实现,借助于比较扭曲(我个人认为)的方法可以大致的实现基于事件驱动的功能。大致的思路是这样子的: 这一部分不作评论,自己去看DOM 2的事件模型。 > 2。继承。 关于vbs我只说一句:vbs是M$牌的垃圾。 > 上述代码实现了NewTimer类,从Timer继承,Javascript没有使用“:”或者java的public那样类似的关键字,只是通过newclassname.prototype=new baseclass这样的方法来完成,同时NewTimer实现了getSystemDate的方法,在NewTimer的初始化函数中,我使用了this.base=Timer,是为了引用父类的实现,不过在对于父类其他实现函数的调用,到现在我没有找到一个确定的方法,是否通过this.base.start()那样来调用还是其他的,如果有谁比较清楚的,麻烦告诉我,另外在netscape的站点上,我查到有一个特殊的"__proto__"的属性好像是对于父类的直接引用,不过具体的我也没有尝试过,在msdn中也没有看到对于__proto__的支持。 之所以不是像其他语言那样继承,那是因为这根本不是“真正”的继承,因为js根本没有“真正”的类,呵呵。prototype的实质就是对原型对象的一个引用。至于调用“父类”方法,其实很简单,在调用了“父类”的构造函数之后直接调用就是了。至于为什么用this.base=parent,其实想明白一件事情就很简单了。parent实际上并不是类,而是构造函数。在“子类”构造函数内部,当时还没有原型存在(prototype是外部动态赋值的,不是静态信息)。所以必须手动的获取“父类”构造函数,运行一下。 也许有人要问,那既然子类直接运行父类构造函数,干吗还要原型?把所有东西写在构造函数不就结了?嘿嘿,想想作者的“第二种方法”。prototype有个特性,给原型增加一个属性(包括方法),所有继承这个原型的对象都会自动添加这个属性。因此,如果你要用这个特性,还是需要原型的。至少你可以用instanceOf操作符来判断变量的类型。 __proto__可以被检测和回溯,从而形成一个原型链,这在比较复杂的“类结构”里是有用的,你可以用它来写自己的instanceOf。不过这不是ecma规范要求的,也应该仅仅在语言内部使用(你真的需要在子类里去动态改变父类?)。 > 3。重载 这个无奈只是作者杞人忧天 :) > Javascript中所有的对象都是从Object继承下来的,object提供了toString()的方法,也就是说如果调用alert(objInstance)这样的过程,实际上是调用了alert(objInstance.toString())的方法,如果没有编写实现,object默认的toString()都是"object object"这样子的,在许多地方需要重载这个函数的,比如Timer,如果我们希望var ins=new Timer(5);alert(ins)调用得到的是interval的值5,那么就需要重新编写toString()方法了 除了toString,你也可以重写valueOf用来给你的对象返回一个原生类型的值,呵呵。 > 长篇累牍的说了一堆废话,终于说玩了大致的想法,其实语言只是一个实现工具,重要的在于设计的思想,不妨可以考虑一下,在BITI内部开发一个OpenSource的Project,如果是基于javascript的模型来建立开发平台库,我希望有人可以参与。通过javascript建立一系列基于Web UI的控件,目前我在开发过程中也是立足于上述的想法。另外,附上我去年写的类似HotMail的按钮那样的class源程序,暂时还没有使用Image Preload,希望有人可以帮我修改一下,如果需要可以运行的版本,给我发送Email:liuruhong@263.net。另外有空我会写基于Javascript的组件编程和多媒体编程部分,再下来就是XML方面了,希望大家共同进步。 语言是工具,有不同的应用目标。设计思想当然可以共通,特别是对象语言。你大可以用js快速开发一个原型(一般意义上的原型,不是前面的技术术语),然后用java, c++作最终成品。至于用js写webUI,我要稍微泼一点点冷水,不必太过在意。webUI的问题主要不在于js,而在于浏览器本身和其他技术标准。比如mozilla的UI用XUL语言来写的。而且许多人认为XBL和HTC(都是用js来封装web控件)等不是很好的方向(虽然我一度挺喜欢这两种技术),因为没有很好的正交分解,把样式、js等都混淆了。未来的方向还是要靠w3c这个标准化组织给出。所以用js也不必写很复杂的类结构(毕竟脚本语言是要给人们轻松的),更多精力花在DOM和兼容性上吧。 最后说一下,netscape还在继续开发js 2.0(好几年了),ecma也跟着同时作edition 4(M$就不清楚其动向,而且其jscript还没有完全实现edition 3),这个版本里好像加入了class,public等关键字,可能会有很大的变化。有兴趣的人可以去看:http://www.mozilla.org/js/language/js20/index.html
作者Blog:
http://blog.csdn.net/hax/
相关文章
|
|