JavaScript 定义类,定义属性,定义方法的几种方式详解及分析

JavaScript 定义类,定义属性,定义方法的几种方式详解及分析

提起面向对象我们就能想到类,对象,封装,继承,多态。在《

javaScript

高级程序设计》

(人民邮电出版社,曹力、张欣译。英文名字是:

Professional JavaScript for Web

Developers

)这本书中描述的还算比较详细。我们看看

JavaScript

中定义类的各种方法。

1.工厂方式

javaScript

中创建自己的类和对象,

我们应该是必须掌握的,我们都知道javaScript中对象的属性可以在对象创建后动态定义,比如下面的代码:

// 定义 var oCar = new Object(); oCar.color = "red"; oCar.doors = 4; oCar.showColor = function() { alert(this.color); } //调用 oCar.showColor();

我们很容易使用

oCar

对象,但是我们创就是想创建多个

Car

实例。我们可以使用一个

函数来封装上面的代码来实现:

// 定义 function createCar() { var oCar = new Object(); oCar.color = "red"; oCar.doors = 4; oCar.showColor = function() { alert(this.color); } return oCar; } // 调用 var ocar1 = createCar(); var ocar2 = createCar(); ocar1.color = "black"; ocar1.showColor(); ocar2.showColor();

顺便说一下,

javaScript

对象默认成员属性都是

public

的。

这种方式我们称为工厂方式,

我们创造了能创建并返回特定类型的对象的工厂。

这样做有点意思了,但是在面向对象中我们经常使用创建对象的方法是:

Car car=new Car();

使用

new

关键字已经深入人心,

因此我们使用上面的方法去定义总感觉别扭,

并且每次

调用时都去创建新的属性以及函数,

功能上也不实际。

下来我们看看构造函数的形式定义类。

2

.构造函数

这种方式看起来有点象工厂函数。具体表现如下:

// 定义 function Car(color, doors) { this.color = color; this.doors = doors; this.showColor = function() { alert(this.color); }; } // 调用 var car1 = new Car("red", 4); var car2 = new Car("blue", 4); car1.showColor(); car2.showColor();

看起来效果很明显,

有差别了吧。

感觉有点意思了。

在构造函数内部创造对象使用

this

键字,使用

new

运算符创建对象感觉非常亲切。但是也有点问题:每次

new

对象时都会

创建所有的属性,

包括函数的创建,

也就是说多个对象完全独立,

我们定义类的目的就是为

了共享方法以及数据,

但是

car1

对象与

car2

对象都是各自独立的属性与函数,

最起码我们

应该共享方法。这就是原形方式的优势所在。

3

.原型方式

利用对象的

prototype

属性,可把它看出创建新对象所依赖的原型。方法如下:

// 定义 function Car() { }; Car.prototype.color = "red"; Car.prototype.doors = 4; Car.prototype.drivers = new Array("Tom", "Jerry"); Car.prototype.showColor = function() { alert(this.color); } // 调用: var car1 = new Car(); var car2 = new Car(); car1.showColor(); car2.showColor(); alert(car1.drivers); car1.drivers.push("stephen"); alert(car1.drivers); // 结果: Tom,Jerry,stephen alert(car2.drivers); // 结果: Tom,Jerry,stephen // 可以用 json 方式简化 prototype 的定义 : Car.prototype = { color: "red", doors: 4, drivers: ["Tom", "Jerry",'safdad'], showColor: function() { alert(this.color); } 首先这段代码的构造函数, 其中没有任何代码, 接下来通过对象的 prototype 属性添加属 性定义 Car 对象的属性。这种方法很好,但是问题是 Car 的对象指向的是 Array 指针, Car 的两个对象都指向同一个 Array 数组, 其中一个对象 car1 改变属性对象的引用 (数组 Array ) 时,另一个对象 car2 也同时改变,这是不允许的。 同时该问题也表现在原型不能带任何初始化参数,导致构造函数无法正常初始化。这需 要另一种方式来解决:那就是混合的构造函数 / 原型模式。 4. 混合的构造函数 / 原型模式 联合使用构造函数和原型方式,定义类就非常方便。 // 定义 function Car(color,doors) { this.color=color; this.doors=doors; this.drivers=new Array("Tom","Jerry"); } Car.prototype.showColor=function(){ alert(this.color); } // 调用: var car1=new Car('red',4); var car2=new Car('blue',4); car1.showColor(); car2.showColor(); alert(car1.drivers); car1.drivers.push("stephen"); alert(car1.drivers); // 结果: Tom,Jerry,stephen alert(car2.drivers); // 结果: Tom,Jerry alert(car1 instanceof Car);

该方法是把属性放在内部定义,

把方法放在外边利用

prototype

进行定义。

解决了第三种

方法的问题。

这种方法其实应该来说非常友好了,但是比起

java

的语法来,应该有一些不和谐,感觉

比较凌乱,对

C++

来说,我们就没有那么麻烦的感觉了,可是开发

C++

的研发人员一般情

况下很少涉及

javaScript

,而对

J2EE

的研发人员来说,这种方式总有一些别扭。总感觉不

是友好的封装,

其实只不过是视觉上封装效果不是很好而已,

要想达到视觉封装效果而又能

达到这种方法的效果的也可以,个人认为其实比较麻烦。那就是动态原型法。

5.

动态原型

对于习惯使用其他语言的开发者来说,使用混合的构造函数

/

原型方式感觉不那么和谐。毕

竟,定义类时,大多数面向对象语言都对属性和方法进行了视觉上的封装。考虑下面的

C#

类:

class Car //class

{

public string color = “red”;

public int doors = 4;

public int mpg = 23;

public Car(string color, int doors, int mpg) //constructor

{

this.color = color;

this.doors = doors;

this.mpg = mpg;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值