JS中类或对象的定义说明


Posted in Javascript onMarch 10, 2014

我们知道,JS是面向对象的。谈到面向对象,就不可避免的要涉及类的概念。一般像c#,java这些强类型语言都有固定的定义类的语法。而JS的不同之处在于它能使用各种方法实现自己的类和对象。一般的实现有以下几种方式:

1.工厂方式
工厂方式是指创建一个返回特定对象类型的工厂函数,示例代码如下:

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("blue",3,25);
oCar1.showColor();
oCar2.showColor();

这种方式每次调用它的工厂函数,都会创建一个新对象。可问题在于每次生成一个新对象,都要创建新函数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("blue",3,25);
oCar1.showColor();
oCar2.showColor();

这样就不需要为每一个对象都创建自己的showColor函数,而只是创建指向这个函数的指针.这从功能上解决了问题,但是该函数却不像对象的方法。于是,引出了构造函数的方式。

2.构造函数方式
构造函数与工厂函数很相似,示例代码如下:

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("blue",3,25);

在构造函数中,内部无创建对象,而是使用this关键字。使用new运算符调用构造函数时,在执行第一行代码之前先创建一个对象,只有用this才能访问这个对象。但是这会遇到什么问题呢,很显然,它的每个对象也都会创建自己的showColor函数版本。为解决这个问题,引出了以下的原型方式.

3.原型方式
该方式利用了对象的prototype属性,可把它看成创建新对象所依赖的原型。这里,用空构造函数来设置类名。然后把所有的方法和属性都直接赋予prototype属性。如下:

function Car()
{}
Car.prototype.color="red";
Car.prototype.doors=4;
Car.prototype.mpg=23;
Car.prototype.drivers=new Array("Mike","Sue");
Car.prototype.showColor=function()
{
   alert(this.color);
}

原型方式只能直接赋值,而不能通过给构造函数传递参数初始化属性的值。在用这种方式时,会遇到两个问题,不知道大家注意到没有。第一问题是采用这种方式必须创建每个对象后才能改变属性的默认值。而不能在创建每个对象时都会直接有自己所需要的属性值。这点很讨厌。第二个问题在于属性所指的是对象的时候。函数共享不会出现任何问题,但是对象共享却会出现问题。因为每个实例一般都要实现自己的对象。

如下面:

var oCar1=new Car();
var oCar2=new Car();
oCar1.drivers.push("Matt");
alert(oCar1.drivers);//输出 "Mike,Sue,Matt"
alert(oCar2.drivers);//输出"Mike,Sue,Matt"

因此drivers属性只是指向对象的指针,所以所有的实例事实上共享同一个对象。由于出现这这些问题,我们引出了下面的联合使用构造函数和原型方式。

4.混合的构造函数/原型方式
这种方式的思想是用构造函数定义对象的所有非函数属性(包括普通属性和指向对象的属性),用原型方式定义对象的函数属性(方法)。结果使得所有的函数都只被创建一次,而每个对象都有自己的对象属性实例。示例代码如下:

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,25);
oCar1.drivers.push("Matt");
alert(oCar1.drivers);//输出 "Mike,Sue,Matt"
alert(oCar2.drivers);//输出 "Mike,Sue"

由实例代码可知,这种方式同时解决了上一种方式的两个问题。不过,采用这种方式,仍有些开发者觉得不够完美。

5.动态原型方式
我们可知,大多数面向对象语言都对属性和方法进行了视觉上的封装。而上述方式的showColor方法却定义在了类的外面。因此,他们设计了动态原型方法。这种方式的基本思想和混合的构造函数/原型方式相同,唯一不同之处在于对象方法的位置。如下所示:

function Car(sColor,iDoors,iMpg)
{
   this.color=sColor;
   this.doors=iDoors;
   this.mpg=iMpg;
   this.drivers=new Array("Mike","Sue");
   if(typeof Car._initialized=="undefined")
  {
     Car.prototype.showColor=function()
     {
        alert(this.color);
     }
  }
  Car._initialized=true;
}

这种方式Car.prototype.showColor只被创建一次。这样依赖,这段代码更像其他语言中的类定义了。

6.混合工厂方式
这种方式通常是不能应该前一种方式的变通方法。它的目的是创建假构造函数,只返回另一种对象的新实例。

function createCar()
{
   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()构造函数内部调用了new运算符,所以自动忽略第二个new运算符。在构造函数内部创建的对象被传递回变量var。这种方式在对象方法的内部管理方面与经典方式有着相同的问题。所以强烈建议:除非万不得已,还是避免使用这种方式。
Javascript 相关文章推荐
ExtJS4如何自动生成控制grid的列显示、隐藏的checkbox
May 02 Javascript
jQuery控制的不同方向的滑动(向左、向右滑动等)
Jul 18 Javascript
javascript面向对象之共享成员属性与方法及prototype关键字用法
Jan 13 Javascript
JavaScript中通过提示框跳转页面的方法
Feb 14 Javascript
JavaScript和JQuery获取DIV值的方法示例
Mar 07 Javascript
JS实现直接运行html代码的方法
Mar 13 Javascript
bootstrap+jQuery实现的动态进度条功能示例
May 25 jQuery
垃圾回收器的相关知识点总结
May 13 Javascript
js中的 || 与 && 运算符详解
May 24 Javascript
Angular请求防抖处理第一次请求失效问题
May 17 Javascript
Vue实现表格批量审核功能实例代码
May 28 Javascript
js实现窗口全屏示例详解
Sep 17 Javascript
Node.js中AES加密和其它语言不一致问题解决办法
Mar 10 #Javascript
JS中的构造函数详细解析
Mar 10 #Javascript
node.js使用nodemailer发送邮件实例
Mar 10 #Javascript
php中给js数组赋值方法
Mar 10 #Javascript
javascript操作referer详细解析
Mar 10 #Javascript
JS数组的赋值介绍
Mar 10 #Javascript
JS删除字符串中重复字符方法
Mar 09 #Javascript
You might like
php is_file 判断给定文件名是否为一个正常的文件
2010/05/10 PHP
PHP使用适合阅读的格式显示文件大小的方法
2015/03/05 PHP
thinkPHP连接sqlite3数据库的实现方法(附Thinkphp代码生成器下载)
2016/05/27 PHP
详解cookie验证的php应用的一种SSO解决办法
2017/10/20 PHP
ThinkPHP中获取指定日期后工作日的具体日期方法
2018/10/14 PHP
基于laravel where的高级使用方法
2019/10/10 PHP
ECMAScript 基础知识
2007/06/29 Javascript
Mootools 1.2教程 事件处理
2009/09/15 Javascript
extJs 文本框后面加上说明文字+下拉列表选中值后触发事件
2009/11/27 Javascript
JavaScript DOM学习第八章 表单错误提示
2010/02/19 Javascript
js下通过getList函数实现分页效果的代码
2010/09/17 Javascript
基于OL2实现百度地图ABCD marker的效果
2015/10/01 Javascript
jQuery得到多个值只能用取Class ,不能用取ID的方法
2016/12/04 Javascript
Jquery给当前页或者跳转后页面的导航栏添加选中后样式的实例
2016/12/08 Javascript
JavaScript 函数节流详解及方法总结
2017/02/09 Javascript
JavaScript实现简单图片轮播效果
2017/08/21 Javascript
AngularJS 中ui-view传参的实例详解
2017/08/25 Javascript
最实用的JS数组函数整理
2017/12/05 Javascript
原生JS+HTML5实现的可调节写字板功能示例
2018/08/30 Javascript
微信小程序实现通过双向滑动缩放图片大小的方法
2018/12/30 Javascript
JavaScript 面向对象程序设计详解【类的创建、实例对象、构造函数、原型等】
2020/05/12 Javascript
基于vue.js仿淘宝收货地址并设置默认地址的案例分析
2020/08/20 Javascript
高性能web服务器框架Tornado简单实现restful接口及开发实例
2014/07/16 Python
python单例模式获取IP代理的方法详解
2018/09/13 Python
运用Python的webbrowser实现定时打开特定网页
2019/02/21 Python
Python3.4学习笔记之列表、数组操作示例
2019/03/01 Python
Python下使用Trackbar实现绘图板
2020/10/27 Python
详解canvas多边形(蜘蛛图)的画法示例
2018/01/29 HTML / CSS
澳大利亚家具和家居用品在线商店:Interiors Online
2018/03/05 全球购物
ghd澳大利亚官方网站:英国最受欢迎的美发工具品牌
2018/05/21 全球购物
公务员个人自我评价分享
2013/11/06 职场文书
销售经理工作职责
2014/02/03 职场文书
实用的简历自我评价
2014/03/06 职场文书
大专应届毕业生求职信
2014/07/15 职场文书
雷峰塔导游词
2015/02/09 职场文书
Oracle删除归档日志及添加定时任务
2022/06/28 Oracle