JAVA EVERY DAY

DAY DAY UP , STUDY HARD

常用链接

统计

积分与排名

developerWorks Sites

Java

JBlog

OpenSource

最新评论

Prototype学习之初始化和继承

从 prototype.js 深入学习 javascript 的面向对象特性

1.怎样构造(初始化)对象?

js 代码
 
  1. var  Prototype = {   
  2.   Version: '1.5.0_rc1',   
  3.   ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)',   
  4.   
  5.   emptyFunction:  function () {},   
  6.   K:  function (x) { return  x}   
  7. }   

就这样,初始化了一个对象(名字就叫 Prototype),以及对象的四个成员: Version, ScriptFragment, emptyFunction, K

我们也来试试:

js 代码
 
  1. var  bbs = {   
  2.  name: 'JavaEye',   
  3.  version: '2.0',   
  4.  describe:  "做最棒的软件开发交流区" ,   
  5.  sayHello:  function () { alert( "hello, i'm javaeye! " ) }   
  6. }  

于是你可以这样使用: bbs.name 或 bbs.sayHello()

看到吗? sayHello 是一个方法哦,不要惊慌,"一切都是对象",所以它和 name 是一样的,只不过初始化,或定义的语法不一样。想起 js 中的正则表达式中的那两个杆杆了吗? 可爱吧!

方法是对象,所以它可以被当作参数传递,或者作为方法的返回值。

所以 Prototype 中有一个 Version 属性,还有一个匹配 script 的正则式字符串, 一个空方法emptyFunction,还有一个方法 K, 它仅仅返回参数。

没问题吧,继续!

2. 构造函数?

先让我们写段代码吧(中学时,我语文极差(大学没语文了),我想写代码让你们明白我心里真实的想法):

js 代码
 
  1. var  Person =  function (name) {  // 这里 Person 是一个方法   
  2.   this .name = name;   
  3. }   
  4. var  bencode =  new  Persion( "bencode" );   // 这里像Java吧!   
  5. alert(bencode.name);  

先看结果:
从 alert(bencode.name); 可以知道,bencode是对象, 而 name 就是 bencode 的属性, 它被正确地初始化为 "bencode"

所以 var bencode = new Persion("bencode"); 就是构造了一个新的对象,Person() 相当于构造函数

所以 new 这个关键字, 就是构造一个新的对象,并且在这个对象上调用相应的方法,并将这个对象返回。

按上面说: 方法 如果用在 在 new 后面,就相当于成了构造函数了。

话又说回来了, 如果 var bencode = new Persion("bencode") 是 构造了一个对象,像Java, 那么 Person 是不是类呢?
可是 Person 不是方法吗? 可是方法不也是对象吗? 类也是对象?

一切皆对象?

本来无一物!

好了,看 prototype.js吧

js 代码
 
  1. var  Class = {   
  2.   create:  function () {   
  3.      return   function () {   
  4.        this .initialize.apply( this , arguments);   
  5.     }   
  6.   }   
  7. }  

初始化一个 Class 对象, 它有一个成员,是一个方法, 这个方法返因另一个方法(方法是对象,所以可以作为参数或者返回值)

所以如果我们这么做:

js 代码
 
  1. var  A = Class.create();  // 此时 A 是一个方法,方法体,下面解释   
  2. var  a =  new  A(...);   // 对方法使用 new 操作符,就是构造一个新的对象,然后在这个对象上调用这个方法( 现在是 A)   

上面分析说? A相当于类, 哈哈 Class.create();  // 终于名副其实
var a = new A(...);  // 也是相当地直观, 就是构造一个新的对象,类型 是A

new 操作符构造了对象,并调用了 方法, 这个方法到底做了什么呢? 也就是上面没有分析的东东,看看先:

js 代码
 
  1. var  Class = {   
  2.   create:  function () {   
  3.      return   function () {   // 见[1]   
  4.        this .initialize.apply( this , arguments);   // 见[2]   
  5.     }   
  6.   }    
  7. }  

[1]. new 操作符,就会在新产生的对象上调用这个方法
[2]. 哦? 这里就是调用 this 对象上的 initialize方法, 并传递 arguments
  换句话说,就是把构造的任务委托给 initialize 方法
  initialize? 哪里来? 见下面,类的扩展(继承)
 
3. prototype?

看段老代码:

js 代码
 
  1. var  Person =  function (name) {   
  2.   this .name = name;   
  3. }   
  4. var  bencode =  new  Person( "bencode" );  

bencode不是一个自闭的人,他应该可以向javaeye介绍一下自己。
像这样:

js 代码
  1. bencode.sayHello();   


 
假如不能实现以上功能的话, 上面的 new,上面所有的东东都等于垃圾。

所以。需要给 Person 类加"实例方法"

题外话: 静态方法如何添加? 看上面的 Class.create, 仅仅是一个对象的成员而已

好, 再来一段 (为了完整性,上面的几句话,再抄一次)

js 代码
 
  1. var  Person =  function (name) {   
  2.   this .name = name;   
  3. }   
  4. Person.prototype = {   // protype 是啥?   
  5.  sayHello:  function () {   
  6.   alert( "hi, javaeye, I'm "  +  this .name);   
  7.  }   
  8. }   
  9. var  bencode =  new  Person( "bencode" );   
  10. bencode.sayHello();  

运行代码,通过!

prototype是啥? 请暂时忘记 Prototype(prototype.js) 这个库,名字一样而已!

让我们再从结果上去分析(第一次我们用这种方法分析而得出了 new 的作用),

我们在思考:
 要想 bencode.sayHello() 正常运行
 bencode 是一个对象, 这是我们已经知道的
 sayHello() 应该是 bencode 这个对象的方法才可以
 
 可是bencode 这个对象是 new 操作符产生的, 而 new 此时作用于 Person 这个 "类"
 那么, 哦? 那么有两种可能:
 1. new 产生的那个新对象是不是就是 Person.prototype
 2. Person.prototype 中的成员 将会被 new 操作符添加到 新产生的对象中

再看:

js 代码
 
  1. Person.prototype = {   
  2.  sayHello:  function () {   
  3.   alert( "hi, javaeye, I'm "  +  this .name);  // 这里有this   
  4.  }   
  5. }  

this.name, 这里的 this 指什么?所以第一个可能讲不通呀

回忆起这段:

js 代码
 
  1. var  Person =  function (name) {   
  2.   this .name = name;   
  3. }  

如果这里的 this 代表着新产生的对象的话。
那么第二种情况就讲得通了, new 将会把 Person.prototype 这个对象的成员放到 这个新对象中。 与当前行为相符。

所以: Person 的 prototype 对象中的 成员, 将会被添加到 新产生的对象 中(我是这样理解的)
(不知道 Js解释器是不是开源的, 有空我得去看看,怎么实现的。)

嘿,默认的 prototype 就是 Object 哦!

4. 扩展?继承?

什么是扩展?啥是继承? ! 我从爸爸那得到了什么?
想不通!

还是实际点:

有一个类A, 它有一个 sayHello方法

js 代码
 
  1. var  A =  function () {   
  2. }   
  3.   
  4. A.prototype = {   
  5.  sayHello:  function () {   
  6.   alert( "sayHello A" )   
  7.  }   
  8. }   

我想构造一个 B 类,让他继承 A 对象, 这句话太抽象。

其实我们可能想这样:

js 代码
 
  1. var  b =  new  B();   
  2. b.sayHello();   // 调用 A 的 sayHello   

这应该是继承的第一层含义(重用)

怎么办到呢?

var B = function() { // 这里是有一个B类了
}

怎么样添加"实例方法"?  快点想起 prototype!!!

B.prototype = A.prototype

这样行了吗? 恭喜, 运行通过!

让我们整合一次

js 代码
 
  1. var  A =  function () {   
  2. }   
  3. A.prototype = {   
  4.  sayHello:  function () {   
  5.   alert( "sayHello A" );   
  6.  }   
  7. }   
  8.   
  9. var  B =  function () {   
  10. }   
  11. B.prototype = A.prototype;   
  12.   
  13. var  b =  new  B();   
  14. b.sayHello();    

可是如果 B 是这样呢?

js 代码
 
  1. var  B =  function () {   
  2. }   
  3. B.prototype = {   
  4.  sayHi:  function () {   
  5.   alert( "sayHi B" );   
  6.  }   
  7. }  

我们是不是应该将 A.prototype 中的内容添加到 B.prototype 对象中,而不是代替它呢? 当然。

这样才能"扩展"

题外话?多态在哪里? 嘿嘿

好了,足够多了, 那prototype.js 是怎么样"扩展"的呢?

js 代码
 
  1. Object.extend =  function (destination, source) {   
  2.    for  ( var  property  in  source) {   
  3.     destination[property] = source[property];   
  4.   }   
  5.    return  destination;   
  6. }  

这个只是简单地把 source 的成员, 添加到 destination 对象中嘛, 哪里看得出扩展?

如果我这样呢?

js 代码
 
  1. var  A =  function () {   
  2. }   
  3. A.prototype = {   
  4.  sayHello:  function () {   
  5.   alert( "sayHello A" )   
  6.  }   
  7. }   
  8.   
  9. var  B =  function () {   
  10. }   
  11. Object.extend(B.prototype, A.prototype);  // 先添加父类(A)成员   
  12. Object.extend(B.prototype, {  // 再添加B类成员, 如果是同名,则覆盖,行为符合 "多态"   
  13.  sayHi:  function () {   
  14.   alert( "sayHi B" );   
  15.  }   
  16. });   

回忆刚才的 Class.create():

js 代码
 
  1. var  Person = Class.create();   
  2. var  bencode =  new  Person( "bencode" );  

刚才说过, 调用 new 时, 将会创建一个新对象,并且调用 Person 方法, Person 方法会委托给 "新产生对象"的 initialize方法

怎么样给新产生对象添加 initialize 方法? 哈哈,轻松

js 代码
 
  1. Object.extend(Person.prototype, {   
  2.  initialize:  function () {   
  3.    this .name = name;   
  4.  }  //,   
  5.   // 下面可以添加其他实例方法。   
  6. });  


所以, 我们使用 prototype 创建类一般格式是这样的:

js 代码
 
  1. var  ClassName = Class.create();   
  2. Object.extend(ClassName.prototype, {   
  3.  initialize:  function (...) {  // 这就相当于构造函数   
  4.  }   
  5.   //...   
  6. });  

如果我们要继承一个类,只要:

js 代码
 
  1. var  ClassName = Class.create();   
  2. Object.extend(ClassName.prototype, SuperClassName.prototype);   
  3. Object.extend(ClassName.prototype, {   
  4.  initialize:  function (...) {   
  5.  }   
  6.   //...   
  7. });  

面向对象部分基本上就这样。

posted on 2007-03-20 13:20 没有鱼的水 阅读(552) 评论(1)  编辑  收藏 所属分类: AJAX

评论

# re: Prototype学习之初始化和继承 2008-10-07 15:11 hq

多谢  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航: