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文件缓存的代码
Apr 09 Javascript
有关js的变量作用域和this指针的讨论
Dec 16 Javascript
Jquery图形报表插件 jqplot简介及参数详解
Oct 10 Javascript
浅析Javascript使用include/require
Nov 13 Javascript
js字符串转换成数字与数字转换成字符串的实现方法
Jan 08 Javascript
浅谈JavaScript中的Math.atan()方法的使用
Jun 14 Javascript
每天一篇javascript学习小结(Array数组)
Nov 11 Javascript
使用jQuery在移动页面上添加按钮和给按钮添加图标
Dec 04 Javascript
工厂模式在JS中的实践
Jan 18 Javascript
webpack将js打包后的map文件详解
Feb 22 Javascript
Vue使用v-viewer实现图片预览
Oct 21 Javascript
angular4实现带搜索的下拉框
Mar 25 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+mysql数据库实现无限分类的方法
2014/12/12 PHP
Thinkphp整合微信支付功能
2016/12/14 PHP
thinkPHP3.2使用RBAC实现权限管理的实现
2019/08/27 PHP
php生成微信红包数组的方法
2019/09/05 PHP
PHP单元测试配置与使用方法详解
2019/12/27 PHP
JavaScript为对象原型prototype添加属性的两种方式
2010/08/01 Javascript
JQuery FlexiGrid的asp.net完美解决方案 dotNetFlexGrid-.Net原生的异步表格控件
2010/09/12 Javascript
常用jQuery选择器总结
2014/07/11 Javascript
Easyui Treegrid改变默认图标的方法
2016/04/29 Javascript
javascript类型系统——undefined和null全面了解
2016/07/13 Javascript
Js apply方法详解
2017/02/16 Javascript
简单谈谈关于Angular Cli打包的事
2017/09/05 Javascript
JSON是什么?有哪些优点?JSON和XML的区别?
2019/04/29 Javascript
JavaScript实现五子棋游戏的方法详解
2019/07/08 Javascript
如何基于javascript实现贪吃蛇游戏
2020/02/09 Javascript
在Webpack中用url-loader处理图片和字体的问题
2020/04/28 Javascript
[03:16]DOTA2完美大师赛主赛事首日集锦
2017/11/23 DOTA
python实现带验证码网站的自动登陆实现代码
2015/01/12 Python
Python中的tuple元组详细介绍
2015/02/02 Python
使用python遍历指定城市的一周气温
2017/03/31 Python
浅谈对yield的初步理解
2017/05/29 Python
python版大富翁源代码分享
2018/11/19 Python
Python List cmp()知识点总结
2019/02/18 Python
深入学习python多线程与GIL
2019/08/26 Python
Python socket处理client连接过程解析
2020/03/18 Python
Python ORM框架Peewee用法详解
2020/04/29 Python
pytorch中的weight-initilzation用法
2020/06/24 Python
澳大利亚运动鞋零售商:The Athlete’s Foot
2018/11/04 全球购物
意大利奢侈品零售商:ilDuomo Novara
2019/09/11 全球购物
自荐信如何“自荐”
2013/10/24 职场文书
升旗仪式主持词
2014/03/19 职场文书
优秀的个人求职信范文
2014/05/09 职场文书
泸县召开党的群众路线教育实践活动总结大会新闻稿
2014/10/21 职场文书
毕业实习证明(4篇)
2014/10/28 职场文书
停课通知书
2015/04/24 职场文书
PostgreSQL并行计算算法及参数强制并行度设置方法
2022/04/06 PostgreSQL