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 相关文章推荐
document.getElementById的简写方式(获取id对象的简略写法)
Sep 10 Javascript
网页中CDATA标记的说明
Sep 12 Javascript
自写简单JS判断是否已经弹出页面
Oct 20 Javascript
精心挑选的15款优秀jQuery 本特效插件和教程
Aug 06 Javascript
JavaScript实现删除,移动和复制文件的方法
Aug 05 Javascript
举例讲解jQuery中可见性过滤选择器的使用
Apr 18 Javascript
根据输入邮箱号跳转到相应登录地址的解决方法
Dec 13 Javascript
微信小程序 向左滑动删除功能的实现
Mar 10 Javascript
jQuery ajax动态生成table功能示例
Jun 14 jQuery
vue中appear的用法
Aug 17 Javascript
微信小程序如何实现全局重新加载
Jun 05 Javascript
编写v-for循环的技巧汇总
Dec 01 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常用hash加密函数
2014/11/22 PHP
php上传图片并压缩的实现方法
2015/12/22 PHP
laravel项目利用twemproxy部署redis集群的完整步骤
2018/05/11 PHP
详解PHP变量传值赋值和引用赋值变量销毁
2019/03/23 PHP
PHP中md5()函数的用法讲解
2019/03/30 PHP
PHP Beanstalkd消息队列的安装与使用方法实例详解
2020/02/21 PHP
jquery HotKeys轻松搞定键盘事件代码
2008/08/30 Javascript
网络图片延迟加载实现代码 超越jquery控件
2010/03/27 Javascript
jQuery1.6 类型判断实现代码
2011/09/01 Javascript
PHP+MySQL+jQuery随意拖动层并即时保存拖动位置实例讲解
2015/10/09 Javascript
javascript for-in有序遍历json数据并探讨各个浏览器差异
2015/11/30 Javascript
JS排序方法(sort,bubble,select,insert)代码汇总
2016/01/30 Javascript
jquery单击事件和双击事件冲突解决方案
2016/03/02 Javascript
基于Bootstrap 3 JQuery及RegExp的表单验证功能
2017/02/16 Javascript
javascript基本数据类型和转换
2017/03/17 Javascript
JavaScript 通过Ajax 动态加载CheckBox复选框
2017/08/31 Javascript
javascript+jQuery实现360开机时间显示效果
2017/11/03 jQuery
vue基于better-scroll仿京东分类列表
2020/06/30 Javascript
微信小程序淘宝首页双排图片布局排版代码(推荐)
2020/10/29 Javascript
在Linux系统上通过uWSGI配置Nginx+Python环境的教程
2015/12/25 Python
Python数据结构与算法之常见的分配排序法示例【桶排序与基数排序】
2017/12/15 Python
python MNIST手写识别数据调用API的方法
2018/08/08 Python
详解python调用cmd命令三种方法
2019/07/08 Python
基于python 等频分箱qcut问题的解决
2020/03/03 Python
利用Python制作动态排名图的实现代码
2020/04/09 Python
python 实现朴素贝叶斯算法的示例
2020/09/30 Python
使用phonegap创建联系人的实现方法
2017/03/30 HTML / CSS
BabyBjörn婴儿背带法国官网:BabyBjorn法国
2018/06/16 全球购物
单位人事专员介绍信
2014/01/11 职场文书
2014年设计师工作总结
2014/11/25 职场文书
2014年乡镇团委工作总结
2014/12/18 职场文书
党员考试作弊检讨书1000字
2015/02/16 职场文书
计划生育责任书
2015/05/09 职场文书
2015年预算员工作总结
2015/05/14 职场文书
Nginx访问日志及错误日志参数说明
2021/03/31 Servers
详解Django的MVT设计模式
2021/04/29 Python