天天看点

JavaScript类

  1

JavaScript类

JavaScript类 

  2

JavaScript类

       类是什么?

  3

JavaScript类

    许多刚接触编程的朋友都可能理解不了类,其实类是对我们这个现实世界的模拟,把它说成“类别”或者“类型”可能会更容易理解一些。比如“人”这种动物就是一个类,而具体某一个人就是“人”这个类的一个实例,“人”可以有许多实例(地球人超过六十亿了),但“人”这个类只有一个。你或许会说那男人和女人不也是人么?怎么只能有一个?其实这里要谈到一个继承的东西,后边才讲,请继续看下去。

  4

JavaScript类

       如何建立一个类?

  5

JavaScript类

    在C

++

中是以class来声明一个类的,JavaScript与C

++

不同,它使用了与函数一样的function来声明,这就让许多学Jscript的朋友把类与函数混在一起了,在Jscript中函数与类确实有些混,但使用久了自然而然会理解,这篇文章是针对想进攻面向对象编程的朋友而写,就不打算一下子讨论得太深了。

  6

JavaScript类

    请看下边这个类的定义:

  7

JavaScript类

function

 WuYouUser()

  8

JavaScript类

    {

  9

JavaScript类

this

.Name; 

//

名字

 10

JavaScript类

    }

 11

JavaScript类

    上边的代码定义了一个WuYouUser(无忧用户)类,它有个属性:Name(名字)。Name就是WuYouUser类的一个属性。

 12

JavaScript类

    一个类有固定的属性,但类的实例却有不同的属性值,就像我是属于“人”这个类的,性别是男,而我有一个女同学,她也属于“人”类,但她的性别属性值却为女。

 13

JavaScript类

    那么如何声明某个类的一个实例呢?非常简单:

 14

JavaScript类

var

 Wo 

=

new

 WuYouUser(); 

//

实例一:“我”

 15

JavaScript类

var

 Biyuan 

=

new

 WuYouUser(); 

//

实例二:“碧原”(Biyuan哥,不好意思。。。嘿嘿)

 16

JavaScript类

        类的属性

 17

JavaScript类

    这个Wo(我)就是WuYouUser类的一个实例,它拥有WuYouUser给它的一切:Name属性、Sex属性以及Age属性,我们可以这样子来设置它的属性: 

 18

JavaScript类

    Wo.Name 

=

"

泣红亭

"

 19

JavaScript类

    很简单是不是?试着运行

 20

JavaScript类

    window.document.write(Wo.Name);

 21

JavaScript类

    看看,是不是输出了我的名字:泣红亭?

 22

JavaScript类

    同样设置一下碧原兄的属性

 23

JavaScript类

    Biyuan.Name 

=

"

碧原

"

;

 24

JavaScript类

    运行

 25

JavaScript类

        window.document.write(Biyuan.Name);

 26

JavaScript类

    可以看到输出了

"

碧原

"

,也就说明了Biyuan与Wo同样是WuYouUser类的实例,但却是不同的实体,具有不同的属性值。

 27

JavaScript类

    属性是可以设置默认值的,无忧里都有记录大家各自发了多少贴子,我们也同样给WuYouUser类添加一个发贴数量的属性ArticleCount

 28

JavaScript类

function

 WuYouUser()

 29

JavaScript类

    {

 30

JavaScript类

this

.Name;

//

名字

 31

JavaScript类

this

.ArticleCount 

=

;

 32

JavaScript类

    }

 33

JavaScript类

    一个无忧新用户刚注册完之后他的发贴数量为0,在上边的代码中可以看到直接给属性ArticleCount设置值为0。

 34

JavaScript类

    可以运行一下这样的代码:

 35

JavaScript类

var

 Wo 

=

new

 WuYouUser();

 36

JavaScript类

    window.document.write(Wo.ArticleCount);

 37

JavaScript类

    可以看到输出了0,说明ArticleCount属性被我们成功设置默认值为0

 38

JavaScript类

       类的方法

 39

JavaScript类

    方法这个词不大好理解,我觉得说成行为会更容易理解。一个人具有许多共同的行为,比如睡觉、吃饭、走路等等,现在我们给WuYouUser类添加一个发贴的方法。

 40

JavaScript类

function

 WuYouUser()

 41

JavaScript类

    {

 42

JavaScript类

this

.Name;

 43

JavaScript类

this

.ArticleCount 

=

;

 44

JavaScript类

this

.NewArticle 

=

function

()

 45

JavaScript类

        {

 46

JavaScript类

/*

 47

JavaScript类

            *

 48

JavaScript类

            *    具体如何发贴我们大家都知道,不就是打打字,加加图片再按一下保存之类的按钮么?

 49

JavaScript类

            *    关于具体如何发贴的代码没有必要在这里写出来,我们要了解的仅仅是方法的定义与使用

 50

JavaScript类

            *    我们在这里实现一个最简单的功能,也是很重要的功能:给我们的发贴数量加上1!

 51

JavaScript类

            *    注意:恐龙等级就是这样加出来的,因此呀……大家狂发贴吧。。。

 52

JavaScript类

*/

 53

JavaScript类

this

.ArticleCount

++

;

 54

JavaScript类

        }

 55

JavaScript类

    }

 56

JavaScript类

    既然定义好了这个方法,我们来试试效果如何:

 57

JavaScript类

var

 Wo 

=

new

 WuYouUser();

 58

JavaScript类

    Wo.NewArticle();

 59

JavaScript类

    document.write(Wo.ArticleCount);

 60

JavaScript类

    可以看到输出了1,说明我们发贴成功了!真是有历史纪念意义的一刻,离恐龙等级又近一步了。

 61

JavaScript类

      静态属性

 62

JavaScript类

    静态属性又称公共属性,它不属于某个类的实例,而是直接属于某个类。

 63

JavaScript类

    比如说无忧用户有一个属性:注册用户的数量,它是属于整个无忧用户的,而不是属于泣红亭或者谁的

 64

JavaScript类

    静态属性的声明方法是:

 65

JavaScript类

    类名.prototype.属性名 

=

 属性值;

 66

JavaScript类

    比如给WuYouUser类定义一个注册用户的数量Count:

 67

JavaScript类

    WuYouUser.prototype.Count 

=

;

 68

JavaScript类

    那么如何读取它呢?有两种方法:

 69

JavaScript类

1

. 直接用 WuYouUser.prototype.Count

 70

JavaScript类

2

. 使用Wo.Count

 71

JavaScript类

    这两者没有区别,都是得到0

 72

JavaScript类

    虽然读取方法可以有两种,但在改变它的时候却得特别小心了,请看下边代码

 73

JavaScript类

var

 Biyuan 

=

new

 WuYouUser();

 74

JavaScript类

    WuYouUser.prototype.Count

++

;

 75

JavaScript类

    document.write(Wo.Count);

 76

JavaScript类

    document.write(Biyuan.Count);

 77

JavaScript类

    你会发现两者的Count属性都是1,也就是说WuYouUser.prototype.Count改变了会影响到各个实例的相应属性,其实原理就是Wo、Biyuan的Count属性与WuYouUser.prototype.Count根本就是同一个!

 78

JavaScript类

    现在来看另外一段代码:

 79

JavaScript类

var

 Biyuan 

=

new

 WuYouUser();

 80

JavaScript类

    Biyuan.Count

++

//

特别注意一下这里,这是直接改变Biyuan的Count属性

 81

JavaScript类

    document.write(Biyuan.Count); 

//

 输出 1

 82

JavaScript类

    document.write(WuYouUser.prototype.Count); 

//

输出 0

 83

JavaScript类

    document.write(Wo.Count); 

//

同样输出0,为什么?

 84

JavaScript类

    可以看到如果直接修改实例的静态属性值,那么会出现其它实例甚至类的静态属性与它不同步了?这是因为直接修改的时候,该实例会生成一个属于该实例的属性Count,这个时候Biyuan.Count不再与WuYouUser.prototype.Count是同一个了,也不与Wo.Count是同一个,这个Count属性是属于Biyuan自己所有的,以后改变了它也只是影响它自己而已。

 85

JavaScript类

    因此如果不是特别的需要,建议不管在读取还是赋值的时候,都统一使用WuYouUser.prototype.Count这样的方式,以做到万无一失!

 86

JavaScript类

       静态方法

 87

JavaScript类

    与静态属性相似,它也有个另称:公共方法,同样属于类本身的。

 88

JavaScript类

    静态方法的定义方式是:

 89

JavaScript类

    类名.方法名 

=

function

(参数1,参数2

JavaScript类

参数n) 

 90

JavaScript类

    {

 91

JavaScript类

//

方法代码

 92

JavaScript类

    }

 93

JavaScript类

    我们现在就来定义一个无忧用户类的注册新用户静态方法:

 94

JavaScript类

    WuYouUser.prototype.AddOne 

=

function

()

 95

JavaScript类

    {

 96

JavaScript类

//

*** 同样具体代码不写出来,给静态属性Count增加1,表示注册用户数量又多一个

 97

JavaScript类

        WuYouUser.prototype.Count

++

;

 98

JavaScript类

    }

 99

JavaScript类

    现在我们来看看如何用它,同样有两种方法:

100

JavaScript类

1

.直接使用WuYouUser.prototype.AddOne()

101

JavaScript类

2

.使用某实例的AddOne()

102

JavaScript类

103

JavaScript类

    这两种方法没有什么不同:

104

JavaScript类

105

JavaScript类

var

 Wo 

=

new

 WuYouUser();

106

JavaScript类

var

 Biyuan 

=

new

 WuYouUser();

107

JavaScript类

    document.write(WuYouUser.prototype.Count); 

//

108

JavaScript类

109

JavaScript类

    Wo.AddOne();

110

JavaScript类

    document.write(WuYouUser.prototype.Count); 

//

 1

111

JavaScript类

    document.write(Wo.Count); 

//

 1

112

JavaScript类

    document.write(Biyuan.Count); 

//

 1

113

JavaScript类

114

JavaScript类

    WuYouUser.prototype.AddOne();

115

JavaScript类

    document.write(WuYouUser.prototype.Count); 

//

 2

116

JavaScript类

    document.write(Wo.Count); 

//

 2

117

JavaScript类

    document.write(Biyuan.Count); 

//

 2

118

JavaScript类

119

JavaScript类

    可以看出不管是使用Wo.AddOne()还是WuYouUser.prototype.AddOne()效果都是一样的,都是给WuYouUser.prototype.Count加上1

120

JavaScript类

121

JavaScript类

    现在再看一段代码:

122

JavaScript类

function

 NewClass() 

//

由于上边的WuYouUser类不合适当这个例子的代码,我声明了一个新类NewClass

123

JavaScript类

    {

124

JavaScript类

this

.Name 

=

"

泣红亭

"

//

这里默认值为我的名字

125

JavaScript类

    }

126

JavaScript类

127

JavaScript类

    NewClass.prototype.ChangeName 

=

function

(NewName)

128

JavaScript类

    {

129

JavaScript类

this

.Name 

=

 NewName;

130

JavaScript类

    }

131

JavaScript类

132

JavaScript类

var

 Wo 

=

new

 NewClass();

133

JavaScript类

    Wo.ChangeName(

"

郑运涛

"

); 

//

我的真名

134

JavaScript类

135

JavaScript类

    可以看到Wo.Name确实已经变成了

"

郑运涛

"

,这个方法似乎是可以用的,但里边是不是内有天机呢?

136

JavaScript类

    再看下边的代码,类的定义以及ChangeName的定义我们照样,但改变一下下边的代码:

137

JavaScript类

138

JavaScript类

    NewClass.prototype.ChangeName(

"

郑运涛

"

);

139

JavaScript类

    document.write(NewClass.Name); 

//

undefined,即未定义

140

JavaScript类

    document.write(NewClass.prototype.Name); 

//

郑运涛

141

JavaScript类

var

 Wo 

=

new

 NewClass();

142

JavaScript类

    document.write(Wo.Name); 

//

泣红亭

143

JavaScript类

144

JavaScript类

    可以看到我们并没有定义NewClass.prototype.Name这个静态属性,但编译器给我们自己加了一个。

145

JavaScript类

    可是再看下边输出Wo.Name,它并不是为

"

郑运涛

"

,而是原来的默认值

"

泣红亭

"

,说明了什么?

146

JavaScript类

    其实很简单,看一下NewClass的定义里已经有Name这个属性,因此Wo也有自己的Name属性,它跟NewClass.prototype.Name并不是同一个的,因此就还是那样子。

147

JavaScript类

148

JavaScript类

    那为什么前一个例子运行了Wo.ChangeName(

"

郑运涛

"

)却能够实现改变Wo.Name属性呢?其实在这里跟改变Wo.Count的值是同一个道理,编译器自动给Wo增加了一个方法ChangeName,这个方法代码与NewClass.prototype.ChangeName一样,但Wo.ChangeName是Wo这个实例所特有的,而非NewClass.prototype.ChangeName!

149

JavaScript类

150

JavaScript类

    分析可知道在静态方法里尽量不要使用this这样的关键字来引用实例本身的属性,除非你有特别的目的,而且能够清楚地明白这里边的运行机制!

151

JavaScript类

152

JavaScript类

    如果真的需要在静态方法里使用this,可以直接把this当作参数传进去:

153

JavaScript类

154

JavaScript类

    NewClass.ChangeName 

=

function

(This,NewName) 

//

注意这里是This,不是this

155

JavaScript类

    {

156

JavaScript类

        This.Name 

=

 NewName;

157

JavaScript类

    }

158

JavaScript类

      构造函数

159

JavaScript类

    一个类在初始化的时候其实也是一个函数的执行过程,这个函数就是构造函数,我们看一下下边的代码:

160

JavaScript类

161

JavaScript类

function

 WuYouUser()

162

JavaScript类

    {

163

JavaScript类

this

.Name 

=

"

泣红亭

"

//

默认定义为泣红亭

164

JavaScript类

        alert(

this

.Name);

165

JavaScript类

    }

166

JavaScript类

var

 Wo 

=

new

 WuYouUser();

//

可以看到出现一个窗口显示泣红亭三个字

167

JavaScript类

168

JavaScript类

    可以看出类的定义不仅仅是定义了它的属性与方法,还同时可以加入一些代码,而这些代码就是该类的构造函数的代码,在实例声明过程中被执行!

169

JavaScript类

    其实说起来,类的属性与类的方法都是在构造函数里执行定义的,看下边的代码:

170

JavaScript类

171

JavaScript类

function

 WuYouUser()

172

JavaScript类

    {

173

JavaScript类

this

.Name 

=

"

泣红亭

"

;

174

JavaScript类

return

;

175

JavaScript类

this

.Sex 

=

"

"

;

176

JavaScript类

    }

177

JavaScript类

var

 Wo 

=

new

 WuYouUser();

178

JavaScript类

    document.write(Wo.Name); 

//

泣红亭

179

JavaScript类

    document.write(Wo.Sex); 

//

undefined,即未定义

180

JavaScript类

181

JavaScript类

    看得出什么?Sex属性是在return;之后的,而WuYouUser类的构造函数遇到return即停止运行,换句话说this.Sex 

=

"

"

;这一行是没有被执行,即Sex属性根本没有被定义!

182

JavaScript类

183

JavaScript类

    构造函数可以有参数,参数值在声明实例的时候被传入:

184

JavaScript类

function

 WuYouUser(Name)

185

JavaScript类

    {

186

JavaScript类

this

.Name 

=

 Name;

187

JavaScript类

    }

188

JavaScript类

var

 Wo 

=

new

 WuYouUser(

"

泣红亭

"

);

189

JavaScript类

    document.write(Wo.Name); 

//

泣红亭

190

JavaScript类

191

JavaScript类

    构造函数不需要返回值,但如果你设置了返回值,可以把它当成一个函数来使用。

192

JavaScript类

function

 Sum(a, b)

193

JavaScript类

    {

194

JavaScript类

this

.a 

=

 a;

195

JavaScript类

this

.b 

=

 b;

196

JavaScript类

return

this

.a 

+

this

.b;

197

JavaScript类

    }

198

JavaScript类

    document.write(Sum(

12

23

)); 

//

输出的是12与23的和35

199

JavaScript类

var

 Obj 

=

new

 Sum(

12

,

23

);

200

JavaScript类

    document.write(Obj.a) 

//

 12

201

JavaScript类

    document.write(Obj.b) 

//

 23

202

JavaScript类

203

JavaScript类

    感觉挺奇妙,对吧?我写这文章写着写着也觉得挺奇妙的,呵呵!

204

JavaScript类

205

JavaScript类

    但强烈建议不要把一个类当成一个函数来使用!如果你需要的是一个函数,请直接写成函数而不要写成类,以免搞混了。

206

JavaScript类

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::继承:::::::::::::::::::::::::::::::::::::::::::::::::::

207

JavaScript类

    继承这个词在面向对象的编程里是非常重要的,虽然JavaScript并不是真正面向对象的语言,而是跟VB一样是基于对象的语言,它同样提供了继承机制。

208

JavaScript类

    文章开头时谈到了男人与女人,这也同样是两个不同的类,但却具有相同的一些属性以及方法,而这些相同的特性是来自“人”这个类的,换句话说男人与女人继承了“人”的所有特性!但是男人与女人却有其不同的地方,编程语言里的继承也一样,一个类A继承了另一个类B,那么类B就是类A的父类,类A就是类B的派生类,也称为子类。比如男人就是人的派生类,而人就是男人的父类。最高一级的类称为基类,想象一下就可以明白,男人继承自人,男孩继承自男人,人就是男孩的基类,男人就是男孩的父类。 

209

JavaScript类

>>>>>>>>>>>>>>>>>>>>

210

JavaScript类

    题外:多重继承

211

JavaScript类

212

JavaScript类

    这里再涉及一个多重继承的话题,但如果你仅仅是学JavaScript的话就没有必要看下去,因为JavaScript不提供多重继承,准确一点说没有一种简单而标准的方法来实现多重继承(其实是有办法实现的,只不过麻烦了一点,而且确实没有必要)。

213

JavaScript类

214

JavaScript类

    在C

++

中是有多重继承的概念的,这里是讨论JavaScript,因此不打算讲,只是说说它的一点点思想以供参考。

215

JavaScript类

216

JavaScript类

    在上边男孩的继承问题中,男孩其实不仅仅是继承自男人,还继承自孩子(有男孩子,也有女孩子)这个类,因此,它同时继承了两个类:男人与男孩,这就是所谓的多重继承。

217

JavaScript类

218

JavaScript类

    好,这个问题打住,我们还是回归主题。

219

JavaScript类

>>>>>>>>>>>>>>>>>>>>

220

JavaScript类

221

JavaScript类

    先看第一个类的定义:

222

JavaScript类

223

JavaScript类

function

 A()

224

JavaScript类

    {

225

JavaScript类

this

.Name 

=

"

泣红亭

"

;

226

JavaScript类

        alert(

this

.Name);

227

JavaScript类

    }

228

JavaScript类

229

JavaScript类

    这个类定义了一个属性Name,默认值为

"

泣红亭

"

230

JavaScript类

231

JavaScript类

    现在看第二个类的定义:

232

JavaScript类

233

JavaScript类

function

 B()

234

JavaScript类

    {

235

JavaScript类

this

.Sex 

=

"

"

;

236

JavaScript类

        alert(

this

.Sex);

237

JavaScript类

    }

238

JavaScript类

239

JavaScript类

    定义了一个属性Sex,默认值为

"

"

240

JavaScript类

241

JavaScript类

    继承的方式就是 子类.prototype 

=

new

 父类();    

242

JavaScript类

    现在我们来让B类继承A类:

243

JavaScript类

244

JavaScript类

    B.prototype 

=

new

 A();

245

JavaScript类

246

JavaScript类

247

JavaScript类

248

JavaScript类

    运行这一段代码:

249

JavaScript类

250

JavaScript类

var

 Obj 

=

new

 B(); 

//

首先打开警告窗口显示"泣红亭",再显示"男"

251

JavaScript类

252

JavaScript类

    可以从上边的结果看出B类继承了A类,拥有了A类的属性Name,并且执行了A类的构造函数,而且A类的构造函数在B类的构造函数执行之前执行。因此我们利用这个可以实现重写父类的方法以及重设置父类某属性的默认值:

253

JavaScript类

254

JavaScript类

function

 A()

255

JavaScript类

    {

256

JavaScript类

this

.Name 

=

"

泣红亭

"

;

257

JavaScript类

this

.Show 

=

function

()

258

JavaScript类

        {

259

JavaScript类

            alert(

"

这是A类的Show方法

"

);

260

JavaScript类

        }

261

JavaScript类

        alert(

this

.Name);

262

JavaScript类

    }

263

JavaScript类

264

JavaScript类

function

 B()

265

JavaScript类

    {

266

JavaScript类

this

.Name 

=

"

郑运涛

"

;

267

JavaScript类

this

.Show 

=

function

()

268

JavaScript类

        {

269

JavaScript类

            alert(

"

这是B类的Show方法

"

);

270

JavaScript类

        }

271

JavaScript类

        alert(

this

.Name);

272

JavaScript类

    }

273

JavaScript类

274

JavaScript类

var

 Obj 

=

new

 B();

275

JavaScript类

    Obj.Show();

276

JavaScript类

277

JavaScript类

    结果出现了三次警告窗口,第一个内容为泣红亭,是执行A类的构造函数里的alert(

this

.Name),那时候Name属性值还为

"

泣红亭

"

,因为B类的构造函数还没执行,第二次内容为

"

郑运涛

"

,这是B类里的alert(

this

.Name),因为B类的构造函数里给Name重赋值为

"

郑运涛

"

。最后是调用了Obj.Show(),执行了不是A类的Show方法里的Show(显示

"

这是A类的Show方法

"

),而是执行了B类的Show(显示

"

这是B类的Show方法

"

),很明显Show方法被重写了。

278

JavaScript类

279

JavaScript类

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

280

JavaScript类

类作为一个对象时的属性与方法(不知道如何简洁地表达,因此用了这么长的题目)

281

JavaScript类

282

JavaScript类

    不知道在这里谈这个话题是否有点混人耳目,但又觉得不谈这篇文章就不算完整,因为文章目的就是要让人搞清楚类的方方面面。

283

JavaScript类

284

JavaScript类

    看了这一小节的题目,或许你会觉得奇怪,类就是类,怎么会“作为一个对象”呢?在JavaScript里,一切都是对象,包括类!对象可以有属性,可以有方法,类也同样可以有,但这个非常容易跟前边说到的静态属性与静态方法搞混了,因此要仔细看清楚两者的分别!

285

JavaScript类

286

JavaScript类

    定义一个类:

287

JavaScript类

function

 WuYouUser()

288

JavaScript类

    {

289

JavaScript类

this

.Name 

=

"

泣红亭

"

;

290

JavaScript类

    }

291

JavaScript类

292

JavaScript类

    定义类作为一个对象时的属性:

293

JavaScript类

294

JavaScript类

    WuYouUser.Url 

=

"

http://www.51js.com

"

//

静态属性的定义是:WuYouUser.prototype.Url = "http://www.51js.com";

295

JavaScript类

var

 Wo 

=

new

 WuYouUser();

296

JavaScript类

    document.write(WuYouUser.Url); 

//

http://www.51js.com

297

JavaScript类

    document.write(Wo.Url); 

//

undefined,即未定义!注意这里的未定义

298

JavaScript类

299

JavaScript类

    从这里可以看出Url这个属性是WuYouUser自个所有,改变了它与其它类以及它的子类完全无关!

300

JavaScript类

301

JavaScript类

    引用类的属性只有一个办法,就是类名.属性名,改变它也一样。

302

JavaScript类

303

JavaScript类

    定义类作为一个对象时的方法:

304

JavaScript类

305

JavaScript类

    WuYouUser.ChangeUrl 

=

function

()

306

JavaScript类

    {

307

JavaScript类

this

.Url 

=

"

http://51js.com

"

;

308

JavaScript类

    }

309

JavaScript类

310

JavaScript类

    你或许会觉得奇怪,这里的this是什么?因为ChangeUrl这个方法是属于对象WuYouUser的,因此this指的就是WuYouUser本身!

311

JavaScript类

312

JavaScript类

    可以运行下边的代码试试:

313

JavaScript类

314

JavaScript类

    document.write(WuYouUser.Url); 

315

JavaScript类

    WuYouUser.ChangeUrl();

316

JavaScript类

    document.write(WuYouUser.Url);     

317

JavaScript类

    明显ChangeUrl直接修改了WuYouUser.Url的值,因此后边才能输出http:

//

51js.com

318

JavaScript类

319

JavaScript类

继续阅读