javascript中类的定义及其方式(《javascript高级程序设计》学习笔记)


Posted in Javascript onJuly 04, 2011

关于javascript中类的继承可以参考阮一峰的Blog《Javascript继承机制的设计思想》,说的很透。

一、在javascript中实例化遇到的问题:

下面用《javascript高级程序设计》中的例子来做说明,假如现在定义了一个car的对象,它是Object类的实例。像下面这样的:

var oCar=new Object(); 
oCar.color = "red"; 
oCar.doors = 4; 
oCar.mpg = 23; 
oCar.showColor = function () { 
alert(this.color); 
};

现在又需要这样的一个实例,你可能会像这样来定义:
var oCar2 = new Object(); 
oCar2.color = "blue"; 
oCar2.doors = 5; 
oCar2.mpg = 25; 
oCar2.showColor = function () { 
alert(this.color); 
};

这样遇到的问题是每个对象都需要重新定义一次他的字段和方法。很麻烦。

二、类的定义--工厂方式实现:

对上面的例子进行一个包装,利用函数的返回值来做文章:

function createCar() { 
var oTempCar = new Object(); 
oTempCar.color = "red"; 
oTempCar.doors = 4; 
oTempCar.mpg = 23; 
oTempCar.showColor = function () { 
alert(this.color); 
}; 
return oTempCar; 
}

调用方式:

var oCar1 = createCar();
var oCar2 = createCar();

这种方式被称之为工厂方式。工厂方式看起来是省事多了。起码创建一个对象的时候不再需要那么多的行数。因为每个属性(color,doors,mpg)的值都是固定的,还需要再次进行改造,利用参数传递来实现:

function createCar(sColor, iDoors, iMpg) { 
var oTempCar = new Object(); 
oTempCar.color = sColor; 
oTempCar.doors = iDoors; 
oTempCar.mpg = iMpg; 
oTempCar.showColor = function () { 
alert(this.color); 
}; return oTempCar; 
} 
var oCar1 = createCar("red", 4, 23); 
var oCar2 = createCar("red", 4, 23); 
oCar1.showColor(); 
oCar2.showColor();

这样做看似的确可以实现了对象了。实现也很简单,调用也很方便。但是有两个不是很好的地方:

1、从语义上看,在创建对象时没有使用new运算符,似乎不是那么正规(通常创建一个对象都用一个new运算符来实现)。

2、不符合面向对象的特征--封装。在这个例子中,oCar1和oCar2都有自己的showColor方法,并且他们的showColor都是自己的实现。但是事实是他们共享的是同一个函数。

也是有办法解决这个共享函数的问题,利用函数指针来解决。在createCar函数之外再创建一个showColor函数,而oTempCar的showColor方法指向这个showColor函数:

function showColor() { 
alert(this.color); 
} function createCar(sColor, iDoors, iMpg) { 
var oTempCar = new Object(); 
oTempCar.color = sColor; 
oTempCar.doors = iDoors; 
oTempCar.mpg = iMpg; 
oTempCar.showColor = showColor; 
return oTempCar; 
} 
var oCar1 = createCar("red", 4, 23); 
var oCar2 = createCar("red", 4, 23); 
oCar1.showColor(); 
oCar2.showColor();

虽然这样解决了重复创建函数的问题,但这样的话,就使showColor函数看起来不像是对象的方法。

三、类的定义--构造函数方式实现:

function Car(sColor, iDoors, iMpg) { 
//通过构造函数的形式,会为每个对象生成独立的属性和函数 
this.color = sColor; 
this.doors = iDoors; 
this.mpg = iMpg; 
this.showColor = function () { 
alert(this.color); 
}; } 
var oCar1 = new Car("red", 4, 23); 
var oCar2 = new Car("red", 4, 23); 
oCar1.showColor(); 
oCar2.showColor();

在Car类中,this指针代表了Car的一个实例,因此不需要返回值。虽然构造函数方式实现了类的定义,但是和工厂方式一样,他也是为每个实例创建一个单独的方法。虽然可以像工厂函数一样在函数之外再创建一个函数利用指针来解决这个问题,但是这么做的话,在语义上没有意义。

四、类的定义--原型方式实现:

利用对象的prototype属性,把它看成是创建新对象所依赖的原型。用空构造函数来设置类名。然后所有的属性和方法都被直接赋予prototype属性。

function Car() { } 
Car.prototype.color = "red"; 
Car.prototype.doors = 4; 
Car.prototype.mpg = 23; 
Car.prototype.showColor = function () { 
alert(this.color); 
}; 
var oCar1 = new Car(); 
var oCar2 = new Car(); 
alert(oCar1 instanceof Car);//output true这里存在两个问题:

1、构造函数没有参数。使用原型时,不能通过给函数参数传递参数来初始化属性值。

2、在有多个实例时,对其中一个实例的属性的更改会影响到另外一个实例的属性。

测试代码:

var oCar1 = new Car(); 
oCar1.color = "Green"; var oCar2 = new Car(); 
oCar2.color = "Black"; 
alert(oCar1.color); //output Green 
alert(oCar2.color); //output Black 
alert(oCar1.color); //output Black

当然了,也会有办法解决这个问题的。那就是混合的构造函数/原型方式

五、类的实现--混合的构造函数/原型方式实现

这种实现方式是将每个类的实例中共享的属性或者方法妨到原型链中实现,而将不需要共享实现的属性和方法放在构造函数中实现。这中类的实现方式是使用最广泛的方式。

function Car(sColor, iDoors, iMpg) { 
this.color = sColor; 
this.doors = iDoors; 
this.mpg = iMpg; 
this.drivers = new Array("Mike", "Sue"); 
} 
Car.prototype.showColor = function () { 
alert(this.color); 
}; var oCar1 = new Car("red", 4, 23); 
var oCar2 = new Car("blue", 3, 24); 
oCar1.drivers.push("Matt"); 
alert(oCar1.drivers); 
alert(oCar2.drivers);六、类的定义--动态原型方式实现

这种方式和混合的构造函数/原型方式相比,提供了一种友好的编程风格(在混合的构造函数/原型方式中,showColor方法的定义是在方法体外实现的,而不是在构造函数的方法体内完成的)。这种类的定义方式使用也很多。
function Car(sColor, iDoors, iMpg) { 
this.color = sColor; 
this.doors = iDoors; 
this.mpg = iMpg; 
this.divers = new Array("Mike", "Sue"); if (typeof Car._initialized == "undefined") { 
Car.prototype.showColor = function () { 
alert(this.color); 
}; 
Car._initialized = true; 
}

七、类的定义--混合工厂方式实现
function Car() { 
var oTempCar = new Object(); 
oTempCar.color = "red"; 
oTempCar.doors = 4; 
oTempCar.mpg = 23; 
oTempCar.showColor = function () { 
alert(this.color); 
}; 
return oTempCar; 
} var car = new Car(); 
car.showColor();

这种方式和工厂方式看起来差不多。由于在Car()构造函数内部调用了new运算符,所以将忽略掉位于构造函数之外的new运算符。在构造函数内部创建的对象被传回变量var。虽然看起来有了new运算符了,比工厂方式有了一些进步,但是这种实现方式也是会出现重复创建方法的问题。因此也不推荐使用这种方式来定义类。
Javascript 相关文章推荐
JS操作JSON要领详细总结
Aug 25 Javascript
Google (Local) Search API的简单使用介绍
Nov 28 Javascript
深入剖析JavaScript中的枚举功能
Mar 06 Javascript
JQuery中属性过滤选择器用法实例分析
May 18 Javascript
Dropzone.js实现文件拖拽上传功能(附源码下载)
Nov 22 Javascript
jQuery模拟下拉框选择对应菜单的内容
Mar 07 Javascript
js仿淘宝商品放大预览功能
Mar 15 Javascript
深入理解vue路由的使用
Mar 24 Javascript
ES6新特性之模块Module用法详解
Apr 01 Javascript
微信小程序 首页制作简单实例
Apr 07 Javascript
javascript中的相等操作符(==与===区别)
Dec 21 Javascript
详解datagrid使用方法(重要)
Nov 06 Javascript
js静态方法与实例方法分析
Jul 04 #Javascript
JavaScript 变量作用域分析
Jul 04 #Javascript
JavaScript XML和string相互转化实现代码
Jul 04 #Javascript
JS对外部文件的加载及对IFRMAME的加载的实现,当加载完成后,指定指向方法(方法回调)
Jul 04 #Javascript
jQuery 对Select的操作备忘记录
Jul 04 #Javascript
javascript开发技术大全 第4章 直接量与字符集
Jul 03 #Javascript
javascript开发技术大全-第3章 js数据类型
Jul 03 #Javascript
You might like
用PHP编程语言开发动态WAP页面
2006/10/09 PHP
php生成EAN_13标准条形码实例
2013/11/13 PHP
Linux下php5.4启动脚本
2014/08/03 PHP
PHP对文件夹递归执行chmod命令的方法
2015/06/19 PHP
PHP基于swoole多进程操作示例
2019/08/12 PHP
PHP使用openssl扩展实现加解密方法示例
2020/02/20 PHP
一个原生的用户等级的进度条
2010/07/03 Javascript
『jQuery』名称冲突使用noConflict方法解决
2013/04/22 Javascript
JavaScript定义类的几种方式总结
2014/01/06 Javascript
JS动态修改图片的URL(src)的方法
2015/04/01 Javascript
jQuery实现鼠标经过弹出提示信息的地图热点效果
2015/08/07 Javascript
实例解析jQuery插件EasyUI最常用的表单验证规则
2015/11/29 Javascript
JS组件中bootstrap multiselect两大组件较量
2016/01/26 Javascript
jQuery扩展+xml实现表单验证功能的方法
2016/12/25 Javascript
jQuery插件autocomplete使用详解
2017/02/04 Javascript
vue router路由嵌套不显示问题的解决方法
2017/06/17 Javascript
React props和state属性的具体使用方法
2018/04/12 Javascript
angularjs实现的购物金额计算工具示例
2018/05/08 Javascript
laydate时间日历插件使用方法详解
2018/11/14 Javascript
解决echarts的多个折现数据出现坐标和值对不上的问题
2018/12/28 Javascript
vue 中固定导航栏的实例代码
2019/11/01 Javascript
echarts实现晶体球面投影的实例教程
2020/10/10 Javascript
[06:33]3.19 DOTA2发布会 海涛、冷冷、2009见证希望
2014/03/21 DOTA
在树莓派2或树莓派B+上安装Python和OpenCV的教程
2015/03/30 Python
Python函数式编程指南(四):生成器详解
2015/06/24 Python
python列表操作之extend和append的区别实例分析
2015/07/28 Python
Python迭代器与生成器基本用法分析
2018/07/26 Python
Python实现的栈、队列、文件目录遍历操作示例
2019/05/06 Python
WiFi云数码相框:Nixplay
2018/07/05 全球购物
新西兰航空中国官网:Air New Zealand China
2018/07/24 全球购物
模具专业推荐信
2013/10/30 职场文书
大学生的网上创业计划书
2013/12/31 职场文书
小学生读书活动总结
2014/06/30 职场文书
党性分析材料格式
2014/12/19 职场文书
深入理解java.lang.String类的不可变性
2021/06/27 Java/Android
《英雄联盟》2022日蚀、月蚀皮肤演示 黑潮亚索曝光
2022/04/13 其他游戏