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 相关文章推荐
jquery 学习笔记 传智博客佟老师附详细注释
Sep 12 Javascript
基于JQuery实现的图片自动进行缩放和裁剪处理
Jan 31 Javascript
JavaScript 事件对象介绍
Apr 13 Javascript
AngularJS基础学习笔记之表达式
May 10 Javascript
jQuery实现气球弹出框式的侧边导航菜单效果
Sep 22 Javascript
浅谈Jquery中Ajax异步请求中的async参数的作用
Jun 06 Javascript
简单实现AngularJS轮播图效果
Apr 10 Javascript
微信小程序图片宽100%显示并且不变形
Jun 21 Javascript
JavaScript中使用import 和require打包后实现原理分析
Mar 07 Javascript
Angular PWA使用的Demo示例
Jan 31 Javascript
vue 使用axios 数据请求第三方插件的使用教程详解
Jul 05 Javascript
微信小程序iOS下拉白屏晃动问题解决方案
Oct 12 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
PHP4实际应用经验篇(8)
2006/10/09 PHP
介绍php设计模式中的工厂模式
2008/06/12 PHP
php中关于普通表单多文件上传的处理方法
2011/03/25 PHP
解决cPanel无法安装php5.2.17
2014/06/22 PHP
php生成百度sitemap站点地图类函数实例
2014/10/17 PHP
PHP连接MSSQL方法汇总
2016/02/05 PHP
Yii2 队列 shmilyzxt/yii2-queue 简单概述
2017/08/02 PHP
laravel实现Auth认证,登录、注册后的页面回跳方法
2019/09/30 PHP
laravel实现图片上传预览,及编辑时可更换图片,并实时变化的例子
2019/11/14 PHP
关于JavaScript中原型继承中的一点思考
2012/07/25 Javascript
js获取url参数代码实例分享(JS操作URL)
2013/12/13 Javascript
JS获取单击按钮单元格所在行的信息
2014/06/17 Javascript
node.js中的path.resolve方法使用说明
2014/12/08 Javascript
SuperSlide标签切换、焦点图多种组合插件
2015/03/14 Javascript
jQuery 判断是否包含在数组中Array[]的方法
2016/08/03 Javascript
ES6中Math对象的部分扩展
2017/02/20 Javascript
jQuery Jsonp跨域模拟搜索引擎
2017/06/17 jQuery
深入浅析js原型链和vue构造函数
2018/10/25 Javascript
微信小程序如何再次获取用户授权的方法
2019/05/10 Javascript
vue.js实现只能输入数字的输入框
2019/10/19 Javascript
JS实现纵向轮播图(初级版)
2020/01/18 Javascript
vue2.0 解决抽取公用js的问题
2020/07/31 Javascript
[02:08]我的刀塔不可能这么可爱 胡晓桃_1
2014/06/20 DOTA
Python探索之修改Python搜索路径
2017/10/25 Python
对python 命令的-u参数详解
2018/12/03 Python
Python占用的内存优化教程
2019/07/28 Python
解析python的局部变量和全局变量
2019/08/15 Python
Pytorch中index_select() 函数的实现理解
2019/11/19 Python
手动安装python3.6的操作过程详解
2020/01/13 Python
本科毕业自我鉴定
2014/03/20 职场文书
党员民主评议个人总结
2014/10/20 职场文书
2015年计划生育责任书
2015/05/08 职场文书
素质教育学习心得体会
2016/01/19 职场文书
python3操作redis实现List列表实例
2021/08/04 Python
Python中super().__init__()测试以及理解
2021/12/06 Python
win10频率超出范围怎么办?win10老显示超出工作频率范围的解决方法
2022/07/07 数码科技