JavaScript中继承的实现方法

(转自http://www.cnblogs.com/xieex/archive/2008/01/25/1053342.html

最近看《JavaScript王者归来》中关于实现继承的方法,做了一些小总结:

JavaScript中要实现继承,其实就是实现三层含义:

1、子类的实例可以共享父类的方法;
2、子类可以覆盖父类的方法或者扩展新的方法;
3、子类和父类都是子类实例的“类型”。

JavaScript中,并不直接从语法上支持继承,但是可以通过模拟的方法来实现继承,以下是关于实现继承的几种方法的总结:
1、构造继承法
2、原型继承法
3、实例继承法
4、拷贝继承法

1、构造继承法:
在子类中执行父类的构造函数。

 1 < SCRIPT LANGUAGE = " JavaScript " >
 2    <!--
 3          function  dwn(s)
 4          {
 5                document.write(s+'<br/>');
 6        }

 7
 8          // 定义一个Collection类型
 9          function  Collection(size)
10          {
11                this.size = function(){return size};  //公有方法,可以被继承
12        }

13
14          // 定义一个_Collection类型
15          function  _Collection(_size)
16          {
17                this._size = function(){return _size};  //公有方法,可以被继承
18        }

19
20         Collection.prototype.isEmpty  =   function ()   // 静态方法,不能被继承
21          {
22                return this.size() == 0;
23        }

24
25          // 定义一个ArrayList类型,它“继承”Colleciton类型
26          function  ArrayList()
27          {
28                var m_elements = [];  //私有成员,不能被继承
29                m_elements = Array.apply(m_elements,arguments);
30
31                //ArrayList类型继承Colleciton
32                this.base = Collection;
33                this.base.call(this,m_elements.length);
34
35                this.base = _Collection;                   //可以实现多态继承
36                this.base.call(this,m_elements.length);    
37
38                this.add = function()
39                {
40                        return m_elements.push.apply(m_elements,arguments);        
41                }

42
43                this.toArray = function()
44                {
45                        return m_elements;
46                }

47        }

48
49         ArrayList.prototype.toString  =   function ()
50          {
51                return this.toArray().toString();
52        }

53
54          // 定义一个SortedList类型,它继承ArrayList类型
55          function  SortedList()
56          {
57                //SortedList类型继承ArrayList
58                this.base = ArrayList;
59                this.base.apply(this,arguments);
60
61                this.sort = function()
62                {
63                        var arr = this.toArray();
64                        arr.sort.apply(arr,arguments);
65                }

66        }

67
68          // 构造一个ArrayList
69          var  a  =   new  ArrayList( 1 , 2 , 3 );
70         dwn(a);           // 1,2,3
71         dwn(a.size());    // 3 a从Collection继承了size()方法
72         dwn(a.isEmpty);   // undefined 但是a没有继承到isEmpty()方法
73
74         dwn(a._size());   // 3 可以实现多态继承
75
76          // 构造一个SortedList
77          var  b  =   new  SortedList( 3 , 1 , 2 );
78         dwn(b.toArray());
79         b.add( 4 , 0 );     // b 从ArrayList继承了add()方法
80         dwn(b.toArray());   // b从ArrayList继承了toArray()方法
81         b.sort();       // b自己实现sort()方法
82         dwn(b.toArray());
83         dwn(b);
84         dwn(b.size());    // b从Collection继承了size()方法
85    // -->
86    < / SCRIPT>

 


 

2、原型继承法:
JavaScript是一种基于原型的语言。
要了解什么是“原型继承法”,先了解一下prototype的特性:prototype的最大特性是能够让对象实例共享原型对象的属性,因此如果把某个对象作为一个类型的原型,那么我们说这个类型的所有实例都一这个对象为原型。这个时候,实际上这个对象的类型也可以作为那些以这个对象为原型的实例的类型。
假如:Point类的对象作为Point2D类型的原型(Point2D.prototype = new Point(2)),那么说Point2D的所有实例都是以Point类的对象为原型。此时,实际上Point类就可以作为Point2D类型的对象的类型(相当于Point2D类型“继承”了Point类型)。
见例:

 1    < SCRIPT LANGUAGE = " JavaScript " >
 2    <!--
 3          function  dwn(s)
 4          {
 5                document.write(s+"<br/>");
 6        }

 7
 8          function  Point(dimension)   // 定义一个Point类
 9          {
10                this.dimension = dimension;
11        }

12
13         Point.prototype.distance  =   function ()  // 静态方法,可以被继承
14          {
15                return this.dimension*2;
16        }

17
18          function  Point2D(x,y)     // 定义一个Point2D类
19          {
20                this.x = x;
21                this.y = y;
22        }

23
24         Point2D.prototype  =   new  Point( 2 );    // 运行“原型继承法”使Point2D继承Point
25
26          function  Point3D(x,y,z)    // 定义Point3D类
27          {
28                this.x = x;
29                this.y = y;
30                this.z = z;
31        }

32
33         Point3D.prototype  =   new  Point( 3 );    // Point3D继承Point类
34
35          var  p2  =   new  Point2D( 1 , 2 );   // 构造一个Point2D对象
36
37          var  p3  =   new  Point3D( 1 , 2 , 3 );  // 构造一个Point3D对象
38
39         dwn(p2.dimension);             // 2
40         dwn(p3.dimension);             // 3
41         dwn(p2.distance());            // 4 可以继承静态方法
42         dwn(p3.distance());            // 6 可以继承静态方法
43
44         dwn(p2  instanceof  Point2D);    // p2是Point2D对象
45         dwn(p2  instanceof  Point);      // Point2D继承Point,p2是Point对象
46
47         dwn(p3  instanceof  Point3D);    // p3是Point3D对象
48         dwn(p3  instanceof  Point);      // Point3D继承Point,p3是Point对象
49
50    // -->
51    < / SCRIPT>

 

 

 3、实例继承法
   构造继承法和原型继承法各有各的缺点,如:
   构造继承法没有办法继承类型的静态方法,因此它无法很好的继承JavaScript的核心对象。
   原型继承法虽然可以继承静态方法,但是依然无法很好地继承核心对象中的不可枚举方法。
   其中,javascript核心对象包括: 
   Array  表述数组。  
   Boolean  表述布尔值。 
   Date  表述日期。 
   Function  指定了一个可编译为函数的字符串 JavaScript 代码。 
   Math  提供了基本的数学常量和函数;如其 PI 属性包含了π的值。 
   Number  表述实数数值。 
   Object  包含了由所有 JavaScript 对象共享的基本功能。 
   RegExp  表述了一个正则表达式;同时包含了由所有正则表达式对象的共享的静态属性。 
   String  表述了一个 JavaScript 字符串。
 (1)构造继承法的局限性:

 1    < SCRIPT LANGUAGE = " JavaScript " >
 2    <!--
 3          function  MyDate()
 4          {
 5                this.base = Date;
 6                this.base.apply(this,arguments);
 7        }

 8
 9          var  date  =   new  MyDate();
10         alert(date.toGMTSring());    // 对象不支持此方法或属性
11          // 核心对象(Date)的某些方法不能被构造继承,原因是核心对象并不像我们自定义的一般对象那样在构造函数里进行赋值或初始化操作。
12    // --> 


(2)原型继承的局限性

 

 

 

 

 

 1    < SCRIPT LANGUAGE = " JavaScript " >
 2    <!--
 3          function  MyDate()
 4          {
 5
 6        }

 7         MyDate.prototype  =   new  Date();
 8          var  date  =   new  MyDate();
 9         alert(date.toGMTSring());     // '[object]不是日期对象'
10    // -->
11    < / SCRIPT>

以上说明了“构造继承法”和“原型继承法”的局限性(局限之一:不能很好的继承核心对象),下面介绍如何用实例继承法来继承核心对象。

 

在介绍之前首先了解以下关于构造函数:
构造函数通常没有返回值,它们只是初始化由this值传递进来的对象,并且什么也不返回。如果函数有返回值,被返回的对象就成了new表达式的值。

 

 1    < SCRIPT LANGUAGE = " JavaScript " >
 2    <!--
 3          function  dwn(s)
 4          {
 5                document.write(s+'<br/>');
 6        }

 7          function  MyDate()
 8          {
 9                var instance = new Date();   //instance是一个新创建的日期对象
10                instance.printDate = function()  //对日期对象instance扩展printDate()方法
11                {
12                        dwn(instance.toLocaleString());
13                }

14                return instance;   //将instance作为构造函数的返回值返回
15        }

16
17          var  date  =   new  MyDate();
18         dwn(date.toGMTString());
19         date.printDate();    
20         dwn(date  instanceof  MyDate);   // false
21         dwn(date  instanceof  Date);     // true
22          // 对象的构造函数将会是实际构造的对象的构造函数(new Date()),而不是类型本身的构造函数(new MyDate())
23    // -->
24    < / SCRIPT>

 4、拷贝继承法

 

 

 拷贝继承法是通过对象属性的拷贝来实现继承。

 1    < script language = " JavaScript " >
 2          function  Point(dimension)
 3          {
 4                this.dimension = dimension;
 5        }

 6
 7          var  Point2D  =   function (x,y)
 8          {
 9                this.x = x;
10                this.y = y;
11        }

12
13     Point2D.extend  =   function ()
14          {
15            var p = new Point(2);
16            for(var each in p)   //将对象的属性进行一对一的复制。
17            {
18                 //this[each] = p[each];
19                 this.prototype[each] = p[each];
20            }

21        }

22     Point2D.extend();
23          // alert(Point2D.dimension);
24         alert(Point2D.prototype.dimension);
25    < / script>

5、几种继承方式的比较 
 

比较项

构造继承

原型继承

实例继承

拷贝继承

静态属性继承

N

Y

Y

Y

内置(核心)对象继承

N

部分

Y

Y

多参多重继承

Y

N

Y

N

执行效率

多继承

Y

N

N

Y

instanceof

false

true

false

false

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值