逸逸记事
逸逸记事

我的分类(专题)

首页(175)
儿子(9)
SIP技术(9)
Web2.0(12)
摄影和DVD(8)
软件开发随笔(18)
名古屋打工生活(11)
微软技术开发(47)
Java技术(12)
加拿大移民生活(20)
生活点滴(6)
第一份工作--上海贝尔(18)
完成项目(13)
回国后的生活(0)


最新日志
独行者
终于知道什么叫外包了
人生悲哀之事
水晶报表中显示动态图片
水晶报表中的简单参数设置
怀念下小黑
dotnet中的数据连接Timeout
老板的思路
又买房了
交通事故

最新回复
回复:独行者
回复:怀念下小黑
回复:老板的思路
回复:mjSip学习笔记
回复:老板的思路
回复:dotnet中的数据连接Timeo
回复:mjSip学习笔记
回复:交通事故
回复:交通事故
回复:又买房了

留言板

签写新留言

您好,很希望问您一个关于jain-sip
生活经历就是最大的财富,羡哦~
java的Web开发问题
回复:疑问
IT还不如妓女呢,呵呵
myjavaserver的空间
求助
您的子域名已开通

统计
blog名称:人在旅途
日志总数:175
评论数量:505
留言数量:13
访问次数:1659309
建立时间:2005年12月7日

链接

 

生命是过客,人在旅途。奶奶是信基督教的,没啥文化,却养育了四子二女,还带过九个孙辈。老人家对生命的看法就是“人都是客人,迟早要回去的。”就以《人在旅途》来纪念她。

 

«July 2025»
12345
6789101112
13141516171819
20212223242526
2728293031

公告
  本人上传的源程序中可能引用或使用了第三方的库或程序,也可能是修改了第三方的例程甚至是源程序.所以本人上传的源程序禁止在以单纯学习为目的的任何以外场合使用,不然如果引起任何版权问题,本人不负任何责任.




     本站首页    管理页面    写新日志    退出
调整中...
[Web2.0]如何在JavaScript中定义CLASS
人在旅途 发表于 2006/6/6 18:10:13

理解关键点: 1.使用function的定义来定义CLASS; 2.prototype是继承的关键. 本文转自这里 Introduction The Base Class Adding a Method Creating a Subclass Calling the Base Constructor One More Subclass The Code Introduction The following is a discussion of a technique I've used over the years to simulate the feeling of Object-Oriented Programming in languages like C# and Java. The keyword here is "simulation". This is not necessarily equivalent to what you would encounter in those languages. JavaScript is a very expressive language and, as a result, there are a wide variety of techniques you can employ to build re-usable and extensible code. What I describe here is by no means the final answer on that subject. As a side note, this article will use OOP terminology common to Java and C#; however, this vernacular is technically incorrect when discussing JavaScript in general. So, if you find it offensive to mix that terminology with JS then close this page now! For the rest of you, keep in mind that I am merely presenting an idiom or, dare I say, a design pattern. I tend to build libraries, so this particular style of JS coding fits my needs well. Others will argue that it is absurd to write JS in this way. So, if you do decide to use this approach or even to roll your own OOP JS, be prepared for debates much like the tab vs. whitespace argument. OK, enough ranting. Let's jump in! NOTE: This tutorial has been updated. If you're looking for the original Inheritance tutorial, you can find that here, with warts and all. The Base Class The first thing we need is a base "class" that can create instances via the "new" operator. The identifier following the "new" operator is the object constructor and any JavaScript function can serve in this capacity. For instance, the following code creates a Person function and then instantiates a new Person object.function Person(first, last) { this.first = first; this.last = last; } var person = new Person("John", "Dough"); The "new" operator will invoke your constructor passing in the specified parameters. A special variable named "this" will exist within the scope of the constructor. "This" points to the current object instance (sometimes referred to as the activation object) with which you are working. Using "this" you can add and modify properties on the instance being created by the constructor. We now have our base "class": Person. Adding a Method Typically you'll want to add methods to your class to manipulate instances of that class. For example, it is often useful to create a "toString" method so you can display the content of your object in an "alert". The following adds such a method to our base class implementation.Person.prototype.toString = function() { return this.first + " " + this.last; } alert( person ); // displays "John Dough" This demonstrates one of the unique qualities of the JavaScript language and that is the concept of prototypes. In a nutshell, all JS objects have a private prototype property. I say "private" because this property is not directly visible or accessible from the object itself. When the runtime performs a lookup on a property, it first looks at the instance to see if that property is defined there. If it is not defined there, the runtime looks for the property on the object's private prototype. Prototypes can have their own private prototype, so the search can keep working its way up the prototype chain. This continues until either the property is located or we reach a null private prototype, in which case, the property is not defined. When we call "new", the runtime creates a new object instance which is passed into the constructor as discussed earlier. However, it also assigns the constructor's prototype property (the publicly accessible one) to the new instance's private prototype. By defining properties on the constructor's prototype, like Person.prototype.toString above, we are creating properties that will be in the private prototype chain of each new instance. These become, in effect, instance methods. Creating a Subclass Let's say we like the Person object, but we need more information when that person acts as an employee. It's time for a subclass of Person which we define below.KevLinDev.extend = function(subClass, baseClass) { function inheritance() {} inheritance.prototype = baseClass.prototype; subClass.prototype = new inheritance(); subClass.prototype.constructor = subClass; subClass.baseConstructor = baseClass; subClass.superClass = baseClass.prototype; } extend(Employee, Parent); function Employee(first, last, id) { // initialize properties here } We begin by creating a convenience function to setup our inheritance chain. We need the subClass.prototype property to be equivalent to baseClass.prototype. (Remember, when we call "new" that prototype property will be copied to the new instance's private prototype, thus hooking up its inheritance chain.) However, we can't allow both the subClass.prototype and the baseClass.prototype to point to the same prototype object. That would mean adding methods to one class would add it to the other. That's fine if we add to the base class, but the base class would also "inherit" methods we added to the subClass. We need a way disconnect the two prototypes while still allowing the subClass to refer to the baseClass. Once again, the prototype chain comes to the rescue. We start by defining a nested function called "inheritance". Next, we point its prototype to the baseClass prototype. This means that any "new" instances of "inheritance" will have their private prototype pointing to that base class' public prototype. Finally, we create a new instance of "inheritance" and assign that to the subClass prototype. Now when we create a new instance of subClass, the instance's private prototype will point to the "inheritance" instance. The "inheritance" instance's private prototype points to the base class' public prototype. This means that changes to baseClass.prototype will propagate to subclass instances through the inheritance chain and since we created a new object for the subclass' prototype property, we can add to subClass.prototype without affecting the base class prototype. Whenever you create a new object instance in JavaScript, the instance's local "constructor" property points to the function (constructor) that was invoked to create the instance. I often compare an instance's constructor property against a function to test the "type" of an object instance. Calling "new inheritance()" points subClass.prototype.constructor to the nested "inheritance" function which would break my tests. I fix this by updating the constructor property to point to my subClass constructor. The final two lines are used as convenience properties when invoking ancestor constructors and methods. These will be demonstrated in the next section. Calling the Base Constructor We've defined our new subClass, but we still need to initialize it properly when calling "new". Ideally, we should never have to place code from Person into our subclass, Employee. We need a way to pass "first" and "last" into Person while letting the Employee constructor handle the "id" argument. The following code shows how this is done.function Employee(first, last, id) { Employee.baseConstructor.call(this, first, last); this.id = id; } Admittedly, this is a bit ugly. However, we simply invoke the super constructor via "call". This calls the base class constructor as if it were a method of the first parameter, "this". The remaining parameters are passed in as arguments to the function being invoked. So, in this case, the base class constructor, Person, will perform any processing on "first" and "last" and the Employee constructor will handle "id". One More Subclass I've found that its easy to build a JS OOP idiom to support one level of inheritance that fails with two more more levels of inheritiance. Lets create one more subclass just to make sure our logic is generalizing properly. Our next subclass, Manager, will extend Employee by adding a "department" property. The new subclass is defined below.extend(Manager, Employee); function Manager(first, last, id, department) { Manager.baseConstructor.call(this, first, last, id); this.department = department; } Nothing new here. This code looks practically identical to our Employee definition and running the sample code below shows that our inheritance is working properly. The Code You can download the "extend" method and a sample test file here: inheritance.zip. The results of that test can be seen on example.htm(very simple). I've also included the sample JS code inline on this page. Additionally, this code shows the idiom used to invoke overridden base methods from sub-class (see the toString methods)./** * inheritance * * @author Kevin Lindsey * @version 1.0 * * copyright 2006, Kevin Lindsey * */ // namespace placeholder KevLinDev = {}; /** * A function used to extend one class with another * * @param {Object} subClass * The inheriting class, or subclass * @param {Object} baseClass * The class from which to inherit */ KevLinDev.extend = function(subClass, baseClass) { function inheritance() {} inheritance.prototype = baseClass.prototype; subClass.prototype = new inheritance(); subClass.prototype.constructor = subClass; subClass.baseConstructor = baseClass; subClass.superClass = baseClass.prototype; } /* * Person class */ /** * Person constructor * * @param {String} first * The person's first name * @param {String} last * The person's last name */ function Person(first, last) { this.first = first; this.last = last; } /** * Create a string representation of this object * * @return {String} A string representation of this object */ Person.prototype.toString = function() { return this.first + " " + this.last; }; /* * Employee class */ // subclass Person KevLinDev.extend(Employee, Person); /** * Employee constructor * * @param {String} first * The employee's first name * @param {String} last * The employee's last name * @param {Number} id * The employee's number */ function Employee(first, last, id) { Employee.baseConstructor.call(this, first, last); this.id = id; } /** * Create a string representation of this object * * @return {String} A string representation of this object */ Employee.prototype.toString = function() { return Employee.superClass.toString.call(this) + ": " + this.id; }; /* * Manager */ // subclass Employee KevLinDev.extend(Manager, Employee); /** * Manager constructor * * @param {String} first * The manager's first name * @param {String} last * The manager's last name * @param {Number} id * The manager's employee number * @param {String} department * This manager's department */ function Manager(first, last, id, department) { Manager.baseConstructor.call(this, first, last, id); this.department = department; } /** * Create a string representation of this object * * @return {String} A string representation of this object */ Manager.prototype.toString = function() { return Manager.superClass.toString.call(this) + ": " + this.department; };

阅读全文(4317) | 回复(0) | 编辑 | 精华


发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)

站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.039 second(s), page refreshed 144759490 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号