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 相关文章推荐
Script的加载方法小结
Jan 12 Javascript
js展开闭合效果演示代码
Jul 24 Javascript
jQuery实现tab选项卡效果的方法
Jul 08 Javascript
js如何判断输入字符串长度
Dec 16 Javascript
JavaScript函数表达式详解及实例
May 05 Javascript
React-native桥接Android原生开发详解
Jan 17 Javascript
在Vue中使用Compass的方法
Mar 02 Javascript
解决vuejs 使用value in list 循环遍历数组出现警告的问题
Sep 26 Javascript
Vue.Draggable拖拽功能的配置使用方法
Jul 29 Javascript
Vue之封装公用变量以及实现方式
Jul 31 Javascript
纯js+css实现在线时钟
Aug 18 Javascript
微信小程序实现录音Record功能
May 09 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
对Session和Cookie的区分与解释
2007/03/16 PHP
php笔记之:初探PHPcms模块开发介绍
2013/04/26 PHP
PHP中使用memcache存储session的三种配置方法
2014/04/05 PHP
php文件压缩之PHPZip类用法实例
2015/06/18 PHP
PHP中通过trigger_error触发PHP错误示例
2015/06/23 PHP
PHP信号处理机制的操作代码讲解
2019/04/19 PHP
php array_chunk()函数用法与注意事项
2019/07/12 PHP
use jscript Create a SQL Server database
2007/06/16 Javascript
Javascript UrlDecode函数代码
2010/01/09 Javascript
基于Jquery的标签智能验证实现代码
2010/12/27 Javascript
js 链式延迟执行DOME
2012/01/04 Javascript
node.js中的http.createClient方法使用说明
2014/12/15 Javascript
个人网站留言页面(前端jQuery编写、后台php读写MySQL)
2016/05/03 Javascript
React Native自定义控件底部抽屉菜单的示例
2018/02/08 Javascript
在Node.js下运用MQTT协议实现即时通讯及离线推送的方法
2019/01/24 Javascript
jQuery实现图片随机切换、抽奖功能(实例代码)
2019/10/23 jQuery
解决vue.js提交数组时出现数组下标的问题
2019/11/05 Javascript
js中apply和call的理解与使用方法
2019/11/27 Javascript
逐行分析鸿蒙系统的 JavaScript 框架(推荐)
2020/09/17 Javascript
vue keep-alive实现多组件嵌套中个别组件存活不销毁的操作
2020/10/30 Javascript
[01:55]2014DOTA2国际邀请赛 BBC正赛第一天总结
2014/07/10 DOTA
python生成验证码图片代码分享
2016/01/28 Python
python爬虫之BeautifulSoup 使用select方法详解
2017/10/23 Python
详解python调用cmd命令三种方法
2019/07/08 Python
基于Python安装pyecharts所遇的问题及解决方法
2019/08/12 Python
在Python中获取操作系统的进程信息
2019/08/27 Python
python进程池实现的多进程文件夹copy器完整示例
2019/11/27 Python
美国最好的保健品打折网店:Swanson
2017/08/04 全球购物
Nike爱尔兰官方网站:Nike.com (IE)
2018/03/12 全球购物
怎样比较两个类型为String的字符串
2016/08/17 面试题
Shell脚本如何向终端输出信息
2014/04/25 面试题
毕业生求职自荐书范文
2014/03/27 职场文书
机关会计岗位职责
2014/04/08 职场文书
演讲稿的格式及范文
2014/08/22 职场文书
安全生产月宣传标语
2014/10/06 职场文书
祝福语集锦:送给毕业同学祝福语
2019/11/21 职场文书