提起面向对象我们就能想到类,对象,封装,继承,多态。在《javaScript高级程序设计》(人民邮电出版社,曹力、张欣译。英文名字是:Professional JavaScript for Web Developers)这本书中描述的还算比较详细。我们看看JavaScript中定义类的各种方法。
1.工厂方式
javaScript中创建自己的类和对象,我们应该是必须掌握的,我们都知道javaScript中对象的属性可以在对象创建后动态定义,比如下面的代码:
<script type="text/javascript">
//定义
var oCar = new Object();
oCar.color = "red";
oCar.doors = 4;
oCar.showColor = function() {
alert(this.color);
}
//调用
oCar.showColor();
</script>
我们很容易使用oCar对象,但是我们创就是想创建多个Car实例。我们可以使用一个函数来封装上面的代码来实现:
<script type="text/javascript">
//定义
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();
</script>
顺便说一下,javaScript对象默认成员属性都是public 的。这种方式我们称为工厂方式,我们创造了能创建并返回特定类型的对象的工厂。
这样做有点意思了,但是在面向对象中我们经常使用创建对象的方法是:
Car car=new Car();
使用new 关键字已经深入人心,因此我们使用上面的方法去定义总感觉别扭,并且每次调用时都去创建新的属性以及函数,功能上也不实际。下来我们看看构造函数的形式定义类。
2.构造函数
这种方式看起来有点象工厂函数。具体表现如下:
<script type="text/javascript">
//定义
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();
</script>
看起来效果很明显,有差别了吧。感觉有点意思了。在构造函数内部创造对象使用this 关键字,使用new 运算符创建对象感觉非常亲切。但是也有点问题:每次new 对象时都会创建所有的属性,包括函数的创建,也就是说多个对象完全独立,我们定义类的目的就是为了共享方法以及数据,但是car1对象与car2对象都是各自独立的属性与函数,最起码我们应该共享方法。这就是原形方式的优势所在。
3.原型方式
利用对象的prototype属性,可把它看出创建新对象所依赖的原型。方法如下:
<script type="text/javascript">
//定义
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);
}
}</script>
首先这段代码的构造函数,其中没有任何代码,接下来通过对象的prototype属性添加属性定义Car对象的属性。这种方法很好,但是问题是Car的对象指向的是Array指针,Car的两个对象都指向同一个Array数组,其中一个对象car1改变属性对象的引用(数组Array)时,另一个对象car2也同时改变,这是不允许的。
同时该问题也表现在原型不能带任何初始化参数,导致构造函数无法正常初始化。这需要另一种方式来解决:那就是混合的构造函数/原型模式。
4. 混合的构造函数/原型模式
联合使用构造函数和原型方式,定义类就非常方便。
<script type="text/javascript">
//定义
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);
</script>
该方法是把属性放在内部定义,把方法放在外边利用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;
}
public void showColor() //method
{
Console.WriteLine(this.color);
}
}
C#很好的打包了Car类的所有属性和方法,因此看见这段代码就知道它要实现什么功能,它定义了一个对象的信息。批评混合的构造函数/原型方式的人认为,在构造函数内存找属性,在其外部找方法的做法不合逻辑。因此,他们设计了动态原型方法,以提供更友好的编码风格。
动态原型方法的基本想法与混合的构造函数/原型方式相同,即在构造函数内定义非函数属性,而函数属性则利用原型属性定义。唯一的区别是赋予对象方法的位置。下面是用动态原型方法重写的Car类:
<script type="text/javascript">
//定义
function Car() {
this.color = "red";
this.doors = 4;
this.drivers = new Array("Tom", "Jerry");
if (typeof Car._initialized == "undefined") {
Car.prototype.showColor = function() {
alert(this.color);
}
//............
}
//最后定义
Car._initialized = true;
}
</script>
直到检查typeof Car._initialized是否等于"undefined"之前,这个构造函数都未发生变化。这行代码是动态原型方法中最重要的部分。如果这个值未定义,构造函数将用原型方式继续定义对象的方法,然后把Car._initialized设置为true。如果这个值定义了(它的值为true时,typeof的值为Boolean),那么就不再创建该方法。简而言之,该方法使用标志(_initialized)来判断是否已给原型赋予了任何方法。该方法只创建并赋值一次,为取悦传统的OOP开发者,这段代码看起来更像其他语言中的类定义了。
6 混合工厂方式
这种方式通常是在不能应用前一种方式时的变通方法。它的目的是创建假构造函数,只返回另一种对象的新实例。这段代码看来与工厂函数非常相似:
function Car() {
var oTempCar = new Object();
oTempCar.color="red";
oTempCar.doors=4;
oTempCar.mpg=23;
oTempCar.showColor = function() {
alert(this.color);
}
return oTempCar;
}
与经典方式不同,这种方式使用new运算符,使它看起来像真正的构造函数:
var oCar = new Car();
由于在Car()构造函数内部调用了new运算符,所以将忽略第二个new运算符(位于构造函数之外)。在构造函数内部创建的对象被传递回变量var。这种方式在对象方法的内部管理方面与经典方式有着相同的问题。强烈建议:除非万不得已(请参阅第15章),还是避免使用这种方式。
总结:(采用哪种方式)
目前使用最广泛的是混合的构造函数/原型方式。此外,动态原型方法也很流行,在功能上与构造函数/原型方式等价。可以采用这两种方式中的任何一种。不过不要单独使用经典的构造函数或原型方式,因为这样会给代码引入问题。
//ps
//static class (1:function)
var CarCollection = new function() {
var _carCollection = new Array(); //global,private
this.Add = function(objCar) {
alert('Add');
}
this.Get = function(carid) {
alert('Get');
}
}
//static class (2:json)
var Car = {
color: 'red',
doors: 4,
showColor: function() { alert(this.color); }
}
Car.showColor();
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/avon520/archive/2009/01/17/3819751.aspx
分享到:
相关推荐
JavaScript定义类的几种方式包括工厂方式、构造函数和原型方式,每种方法都有其特点和适用场景,接下来我们将详细探讨。 工厂方式是最早期的面向对象编程在JavaScript中的实践之一。使用工厂方式定义类,本质上就是...
以下是四种常用的 JavaScript 类定义方法: 1. **工厂函数方式**: 工厂函数是一种创建对象的方法,它通过函数返回一个具有特定属性和方法的对象。在提供的示例中,`createCar` 就是一个工厂函数,它接收参数,...
Javascript对象定义的几种方式
JavaScript实现浮点数转十六进制字符的过程涉及到了浮点数的表示、IEEE 754标准、二进制与十六进制的转换等多个知识点。由于JavaScript直接使用浮点数转十六进制的功能实现并不直接,因此需要借助其他方法来实现。...
在JavaScript中定义类和对象的方法大致可以分为两类,一种是使用函数方式定义,另一种是先实例化Object类的方式定义。下面详细介绍这两种方法的实现和使用。 首先,函数方式定义类是最直观和常用的方法,它基于函数...
JavaScript中定义类或函数,主要有以下几种方式: 1. 工厂方式 工厂方式是JavaScript中创建对象的一种模式,它通过一个工厂函数来封装创建对象的代码。通过工厂函数,我们可以创建多个具有相同属性和方法的对象实例...
在JavaScript中,尽管它...总的来说,JavaScript中的类定义是一个涉及构造函数、原型链以及ES6新语法的重要概念。通过理解这些知识点,开发者可以更好地实现面向对象编程,创建可复用的组件,并实现复杂的继承和封装。
2. **JavaScript类的继承**:JavaScript支持原型链实现的继承,通过原型对象可以实现类之间的继承关系。通过Object.create方法或修改构造函数的prototype,可以让一个类继承另一个类的属性和方法。 3. **模块化设计...
总结一下,这个例子展示了JavaScript中模拟类的常见做法,包括如何定义公有成员、私有成员和特权方法。私有成员通过闭包实现,而特权方法则提供了一种在保持私有性的同时可以从类的外部访问私有成员的方式。通过原型...
总结起来,RequireJS为我们提供了一种优雅的方式来组织和加载JavaScript代码,而结合类的定义和继承,我们可以构建复杂的面向对象应用程序。在实际项目中,我们还可以利用RequireJS的优化工具进行代码压缩和合并,...
在JavaScript中,定义类是构建面向对象程序的基本方式之一。本文主要汇总了在JavaScript中定义类的多种方法,并对每种方法进行了详细讲解和代码示例。 首先,我们介绍了工厂方式。工厂方式是最简单的创建对象的方法...
本文将详细解释三种在JavaScript中定义类的方法:构造函数法、Object.create()法以及极简主义法。 1. 构造函数法 构造函数法是最常见的模拟类的方式,通过使用函数作为类的模板。构造函数通常以大写字母开头,表示...
- **静态方法**:使用`static`关键字可以定义类的静态方法,这些方法不依赖于类的实例,而是直接在类本身上调用。 ```javascript class Person { static getClassName() { return this.name; } } console.log...
JavaScript开发的Web流程定义工具是用于创建和管理业务流程的应用程序,它允许用户通过图形化界面来设计、编辑和执行工作流程。这种工具通常被企业用作自动化业务流程管理(BPM)的一部分,以提高效率和协作。在本文...
下面我们将详细介绍如何在JavaScript中定义类或对象,并逐步展示其优势。 #### 二、定义对象的基本方法 ##### 2.1 使用函数创建对象 在JavaScript中,可以通过定义一个函数来创建对象。以下是一个简单的例子,...
类定义了一类事物公共的行为和方法;而实例则是类的一个具体实现。 我们还知道,面向对象编程有三个重要的概念 - 封装、继承和多态。 但是在JavaScript的世界中,所有的这一切特性似乎都不存在。 因为JavaScript...