javascript面向?qū)ο蠹夹g(shù)基礎(chǔ)(五)
本文轉(zhuǎn)載于javaeye(http://www.javaeye.com/wiki/Object_Oriented_JavaScript/1279-javascript-object-oriented-technology-one),只進(jìn)行了重新排版以便收藏。
文中所有英文語句(程序語句除外),都引自<<javascript-the definitive guide,5th edition>>。
------------------------------------------------------------------------------------
類變量/類方法/實(shí)例變量/實(shí)例方法
先補(bǔ)充一下以前寫過的方法:
在javascript中,所有的方法都有一個(gè)call方法和apply方法。這兩個(gè)方法可以模擬對象調(diào)用方法。它的第一個(gè)參數(shù)是對象,后面的參數(shù)表示對象調(diào)用這個(gè)方法時(shí)的參數(shù)(ECMAScript specifies two methods that are defined for all functions, call() and apply(). These methods allow you to invoke a function as if it were a method of some other object. The first argument to both call() and apply() is the object on which the function is to be invoked; this argument becomes the value of the this keyword within the body of the function. Any remaining arguments to call() are the values that are passed to the function that is invoked)。比如我們定義了一個(gè)方法f(),然后調(diào)用下面的語句:
f.call(o, 1, 2);
作用就相當(dāng)于
o.m = f;
o.m(1,2);
delete o.m;
舉個(gè)例子:
---------------------------------
prototype屬性的應(yīng)用:
下面這個(gè)例子是根據(jù)原書改過來的.
假設(shè)我們定義了一個(gè)Circle類,有一個(gè)radius屬性和area方法,實(shí)現(xiàn)如下:
假設(shè)我們定義了100個(gè)Circle類的實(shí)例對象,那么每個(gè)實(shí)例對象都有一個(gè)radius屬性和area方法。實(shí)際上,除了radius屬性,每個(gè)Circle類的實(shí)例對象的area方法都是一樣,這樣的話,我們就可以把a(bǔ)rea方法抽出來定義在Circle類的prototype屬性中,這樣所有的實(shí)例對象就可以調(diào)用這個(gè)方法,從而節(jié)省空間。
現(xiàn)在,讓我們用prototype屬性來模擬一下類的繼承:首先定義一個(gè)Circle類作為父類,然后定義子類PositionCircle。
文中所有英文語句(程序語句除外),都引自<<javascript-the definitive guide,5th edition>>。
------------------------------------------------------------------------------------
類變量/類方法/實(shí)例變量/實(shí)例方法
先補(bǔ)充一下以前寫過的方法:
在javascript中,所有的方法都有一個(gè)call方法和apply方法。這兩個(gè)方法可以模擬對象調(diào)用方法。它的第一個(gè)參數(shù)是對象,后面的參數(shù)表示對象調(diào)用這個(gè)方法時(shí)的參數(shù)(ECMAScript specifies two methods that are defined for all functions, call() and apply(). These methods allow you to invoke a function as if it were a method of some other object. The first argument to both call() and apply() is the object on which the function is to be invoked; this argument becomes the value of the this keyword within the body of the function. Any remaining arguments to call() are the values that are passed to the function that is invoked)。比如我們定義了一個(gè)方法f(),然后調(diào)用下面的語句:
f.call(o, 1, 2);
作用就相當(dāng)于
o.m = f;
o.m(1,2);
delete o.m;
舉個(gè)例子:
1
function Person(name,age) { //定義方法
2
this.name = name;
3
this.age = age;
4
}
5
var o = new Object(); //空對象
6
alert(o.name + "_" + o.age); //undefined_undefined
7
8
Person.call(o,"sdcyst",18); //相當(dāng)于調(diào)用:o.Person("sdcyst",18)
9
alert(o.name + "_" + o.age); //sdcyst_18
10
11
Person.apply(o,["name",89]);//apply方法作用同call,不同之處在于傳遞參數(shù)的形式是用數(shù)組來傳遞
12
alert(o.name + "_" + o.age); //name_89

2

3

4

5

6

7

8

9

10

11

12

---------------------------------
實(shí)例變量和實(shí)例方法都是通過實(shí)例對象加"."操作符然后跟上屬性名或方法名來訪問的,但是我們也可以為類來設(shè)置方法或變量,
這樣就可以直接用類名加"."操作符然后跟上屬性名或方法名來訪問。定義類屬性和類方法很簡單:
1
Person.counter = 0; //定義類變量,創(chuàng)建的Person實(shí)例的個(gè)數(shù)
2
function Person(name,age) {
3
this.name = name;
4
this.age = age;
5
Person.counter++; //沒創(chuàng)建一個(gè)實(shí)例,類變量counter加1
6
};
7
8
Person.whoIsOlder = function(p1,p2) { //類方法,判斷誰的年齡較大
9
if(p1.age > p2.age) {
10
return p1;
11
} else {
12
return p2;
13
}
14
}
15
16
var p1 = new Person("p1",18);
17
var p2 = new Person("p2",22);
18
19
alert("現(xiàn)在有 " + Person.counter + "個(gè)人"); //現(xiàn)在有2個(gè)人
20
var p = Person.whoIsOlder(p1,p2);
21
alert(p.name + "的年齡較大"); //p2的年齡較大

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

prototype屬性的應(yīng)用:
下面這個(gè)例子是根據(jù)原書改過來的.
假設(shè)我們定義了一個(gè)Circle類,有一個(gè)radius屬性和area方法,實(shí)現(xiàn)如下:
1
function Circle(radius) {
2
this.radius = radius;
3
this.area = function() {
4
return 3.14 * this.radius * this.radius;
5
}
6
}
7
var c = new Circle(1);
8
alert(c.area()); //3.14

2

3

4

5

6

7

8

假設(shè)我們定義了100個(gè)Circle類的實(shí)例對象,那么每個(gè)實(shí)例對象都有一個(gè)radius屬性和area方法。實(shí)際上,除了radius屬性,每個(gè)Circle類的實(shí)例對象的area方法都是一樣,這樣的話,我們就可以把a(bǔ)rea方法抽出來定義在Circle類的prototype屬性中,這樣所有的實(shí)例對象就可以調(diào)用這個(gè)方法,從而節(jié)省空間。
1
function Circle(radius) {
2
this.radius = radius;
3
}
4
Circle.prototype.area = function() {
5
return 3.14 * this.radius * this.radius;
6
}
7
var c = new Circle(1);
8
alert(c.area()); //3.14

2

3

4

5

6

7

8

現(xiàn)在,讓我們用prototype屬性來模擬一下類的繼承:首先定義一個(gè)Circle類作為父類,然后定義子類PositionCircle。
1
function Circle(radius) { //定義父類Circle
2
this.radius = radius;
3
}
4
Circle.prototype.area = function() { //定義父類的方法area計(jì)算面積
5
return this.radius * this.radius * 3.14;
6
}
7
8
function PositionCircle(x,y,radius) { //定義類PositionCircle
9
this.x = x; //屬性橫坐標(biāo)
10
this.y = y; //屬性縱坐標(biāo)
11
Circle.call(this,radius); //調(diào)用父類的方法,相當(dāng)于調(diào)用this.Circle(radius),設(shè)置PositionCircle類的
12
//radius屬性
13
}
14
PositionCircle.prototype = new Circle(); //設(shè)置PositionCircle的父類為Circle類
15
16
var pc = new PositionCircle(1,2,1);
17
alert(pc.area()); //3.14
18
//PositionCircle類的area方法繼承自Circle類,而Circle類的
19
//area方法又繼承自它的prototype屬性對應(yīng)的prototype對象
20
alert(pc.radius); //1 PositionCircle類的radius屬性繼承自Circle類
21
22
/*
23
注意:在前面我們設(shè)置PositionCircle類的prototype屬性指向了一個(gè)Circle對象,
24
因此pc的prototype屬性繼承了Circle對象的prototype屬性,而Circle對象的constructor屬
25
性(即Circle對象對應(yīng)的prototype對象的constructor屬性)是指向Circle的,所以此處彈出
26
的是Circ.
27
*/
28
alert(pc.constructor); //Circle
29
30
/*為此,我們在設(shè)計(jì)好了類的繼承關(guān)系后,還要設(shè)置子類的constructor屬性,否則它會指向父類
31
的constructor屬性
32
*/
33
PositionCircle.prototype.constructor = PositionCircle
34
alert(pc.constructor); //PositionCircle

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

posted on 2009-10-20 11:34 Brian 閱讀(224) 評論(0) 編輯 收藏 所屬分類: JScript