JavaScript中定义类的方式详解


Posted in Javascript onJanuary 07, 2016

本文实例讲述了JavaScript中定义类的方式。分享给大家供大家参考,具体如下:

Javascript本身并不支持面向对象,它没有访问控制符,它没有定义类的关键字class,它没有支持继承的extend或冒号,它也没有用来支持虚函数的virtual,不过,Javascript是一门灵活的语言,下面我们就看看没有关键字class的Javascript如何实现类定义,并创建对象。

一、定义类并创建类的实例对象

在Javascript中,我们用function来定义类,如下:

function Shape()
{
var x = 1 ;
var y = 2 ;
}

你或许会说,疑?这个不是定义函数吗?没错,这个是定义函数,我们定义了一个Shape函数,并对x和y进行了初始化。不过,如果你换个角度来看,这个就是定义一个Shape类,里面有两个属性x和y,初始值分别是1和2,只不过,我们定义类的关键字是function而不是class。

然后,我们可以创建Shape类的对象aShape,如下:

var aShape = new Shape();

二、定义公有属性和私有属性

我们已经创建了aShape对象,但是,当我们试着访问它的属性时,会出错,如下:

aShape.x = 1 ;

这说明,用var定义的属性是私有的。我们需要使用this关键字来定义公有的属性

function Shape()
{
this .x = 1 ;
this .y = 2 ;
}

这样,我们就可以访问Shape的属性了,如。

aShape.x = 2 ;

好,我们可以根据上面的代码总结得到:用var可以定义类的private属性,而用this能定义类的public属性。

三、定义公有方法和私有方法

在Javascript中,函数是Function类的实例,Function间接继承自Object,所以,函数也是一个对象,因此,我们可以用赋值的方法创建函数,当然,我们也可以将一个函数赋给类的一个属性变量,那么,这个属性变量就可以称为方法,因为它是一个可以执行的函数。代码如下:

function Shape()
{
var x = 0 ;
var y = 1 ;
this .draw = function ()
{
// print; 
};
}

我们在上面的代码中定义了一个draw,并把一个function赋给它,下面,我们就可以通过aShape调用这个函数,OOP中称为公有方法,如:

aShape.draw();

如果用var定义,那么这个draw就变成私有的了,OOP中称为私有方法,如

function Shape()
{
var x = 0 ;
var y = 1 ;
var draw = function ()
{
// print; 
};
}

这样就不能使用aShape.draw调用这个函数了。

三、构造函数

Javascript并不支持OOP,当然也就没有构造函数了,不过,我们可以自己模拟一个构造函数,让对象被创建时自动调用,代码如下:

function Shape()
{
var init = function ()
{
// 构造函数代码 
};
init();
}

在Shape的最后,我们人为的调用了init函数,那么,在创建了一个Shape对象是,init总会被自动调用,可以模拟我们的构造函数了。

四、带参数的构造函数

如何让构造函数带参数呢?其实很简单,将要传入的参数写入函数的参数列表中即可,如

function Shape(ax,ay)
{
var x = 0 ;
var y = 0 ;
var init = function ()
{
// 构造函数 
x = ax;
y = ay;
};
init();
}

这样,我们就可以这样创建对象:

var aShape = new Shape( 0 , 1 );

五、静态属性和静态方法

在Javascript中如何定义静态的属性和方法呢?如下所示

function Shape(ax,ay)
{
var x = 0 ;
var y = 0 ;
var init = function ()
{
// 构造函数 
x = ax;
y = ay;
};
init();
}
Shape.count = 0 ; // 定义一个静态属性count,这个属性是属于类的,不是属于对象的。 
Shape.staticMethod = function (){}; // 定义一个静态的方法

有了静态属性和方法,我们就可以用类名来访问它了,如下

alert ( aShape.count );
aShape.staticMethod();

注意:静态属性和方法都是公有的,目前为止,我不知道如何让静态属性和方法变成私有的~

六、在方法中访问本类的公有属性和私有属性

在类的方法中访问自己的属性,Javascript对于公有属性和私有属性的访问方法有所不同,请大家看下面的代码

function Shape(ax,ay)
{
var x = 0 ;
var y = 0 ;
this .gx = 0 ;
this .gy = 0 ;
var init = function ()
{
x = ax; // 访问私有属性,直接写变量名即可 
y = ay;
this .gx = ax; // 访问公有属性,需要在变量名前加上this. 
this .gy = ay;
};
init();
}

七、this的注意事项

根据笔者的经验,类中的this并不是一直指向我们的这个对象本身的,主要原因还是因为Javascript并不是OOP语言,而且,函数和类均用function定义,当然会引起一些小问题。

this指针指错的场合一般在事件处理上面,我们想让某个对象的成员函数来响应某个事件,当事件被触发以后,系统会调用我们这个成员函数,但是,传入的this指针已经不是我们本身的对象了,当然,这时再在成员函数中调用this当然会出错了。

解决方法是我们在定义类的一开始就将this保存到一个私有的属性中,以后,我们可以用这个属性代替this。我用这个方法使用this指针相当安全,而且很是省心~

我们修改一下代码,解决this问题。对照第六部分的代码看,你一定就明白了

function Shape(ax,ay)
{
var _this = this ; // 把this保存下来,以后用_this代替this,这样就不会被this弄晕了 
var x = 0 ;
var y = 0 ;
_this.gx = 0 ;
_this.gy = 0 ;
var init = function ()
{
x = ax; // 访问私有属性,直接写变量名即可 
y = ay;
_this.gx = ax; // 访问公有属性,需要在变量名前加上this. 
_this.gy = ay;
};
init();
}

以上我们聊了如何在Javascript中定义类,创建类的对象,创建公有和私有的属性和方法,创建静态属性和方法,模拟构造函数,并且讨论了容易出错的this。

关于Javascript中的OOP实现就聊到这里,以上是最实用的内容,一般用Javascript定义类,创建对象用以上的代码已经足够了。当然,你还可以用mootools或prototype来定义类,创建对象。我用过mootools框架,感觉很不错,它对Javascript的类模拟就更完善了,还支持类的继承,有兴趣的读者可以去尝试一下。当然,如果使用了框架,那么在你的网页中就需要包含相关的js头文件,因此我还是希望读者能够在没有框架的情况下创建类,这样,代码效率较高,而且你也可以看到,要创建一个简单的类并不麻烦~

补充:

JavaScript类定义的四种方式:

// 1、工厂方式
function createCar(name,color,price){
  var tempcar=new Object;
  tempcar.name=name;
  tempcar.color=color;
  tempcar.price=price;
  tempcar.getName=function(){
   document.write(this.name+"-----"+this.color+"<br>");
  };
  return tempcar;
}
var car1=new createCar("工厂桑塔纳","red","121313");
car1.getName();
/*
定义了一个能创建并返回特定类型对象的工厂函数, 看起来还是不错的, 但有个小问题 ,
每次调用时都要创建新函数 showColor,我们可以把它移到函数外面,
function getName(){
  document.write(this.name+"-----"+this.color+"<br>");
}
在工厂函数中直接指向它 tempCar.getName = getName;
这样避免了重复创建函数的问题,但看起来不像对象的方法了。
*/
// 2、构造函数方式
function Car(name,color,price){
  this.name=name;
  this.color=color;
  this.price=price;
  this.getColor=function(){
   document.write(this.name+"-----"+this.color+"<br>");
  };
}
var car2=new Car("构造桑塔纳","red","121313");
car2.getColor(); 
/*
可以看到与第一中方式的差别,在构造函数内部无创建对象,而是使用 this 关键字。
使用 new 调用构造函数时,先创建了一个对象,然后用 this 来访问。
这种用法于其他面向对象语言很相似了, 但这种方式和上一种有同一个问题, 就是重复创建函数。
*/
// 3、原型方式
function proCar(){
}
proCar.prototype.name="原型";
proCar.prototype.color="blue";
proCar.prototype.price="10000";
proCar.prototype.getName=function(){
  document.write(this.name+"-----"+this.color+"<br>");
};
var car3=new proCar();
car3.getName();
/*
首先定义了构造函数 Car,但无任何代码,然后通过 prototype 添加属性。优点:
  a. 所有实例存放的都是指向 showColor 的指针,解决了重复创建函数的问题
  b. 可以用 instanceof 检查对象类型
  alert(car3 instanceof proCar);//true
  缺点,添加下面的代码:
  proCar.prototype.drivers = newArray("mike", "sue");
  car3.drivers.push("matt");
  alert(car3.drivers);//outputs "mike,sue,matt"
  alert(car3.drivers);//outputs "mike,sue,matt"
  drivers 是指向 Array 对象的指针,proCar 的两个实例都指向同一个数组。
*/
// 4、动态原型方式
function autoProCar(name,color,price){
  this.name=name;
  this.color=color;
  this.price=price;
  this.drives=new Array("mike","sue");
  if(typeof autoProCar.initialized== "undefined"){
   autoProCar.prototype.getName =function(){
   document.write(this.name+"-----"+this.color+"<br>");
   };
   autoProCar.initialized=true;
  }
}
var car4=new autoProCar("动态原型","yellow","1234565");
car4.getName();
car4.drives.push("newOne");
document.write(car4.drives);
/*
这种方式是我最喜欢的, 所有的类定义都在一个函数中完成, 看起来非常像其他语言的
类定义,不会重复创建函数,还可以用 instanceof
*/

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
(转载)JavaScript中匿名函数,函数直接量和闭包
May 08 Javascript
js单例模式的两种方案
Oct 22 Javascript
js 限制input只能输入数字、字母和汉字等等
Dec 18 Javascript
JS常用字符串处理方法应用总结
May 22 Javascript
用JS动态设置CSS样式常见方法小结(推荐)
Nov 10 Javascript
BootStrap3使用错误记录及解决办法
Dec 22 Javascript
Javascript中类式继承和原型式继承的实现方法和区别之处
Apr 25 Javascript
vue.js 使用v-if v-else发现没有执行解决办法
May 15 Javascript
深入理解 webpack 文件打包机制(小结)
Jan 08 Javascript
vue自定义指令directive实例详解
Jan 17 Javascript
layui从数据库中获取复选框的值并默认选中方法
Aug 15 Javascript
Vue axios 跨域请求无法带上cookie的解决
Sep 08 Javascript
javascript类型系统 Window对象学习笔记
Jan 07 #Javascript
直接拿来用的页面跳转进度条JS实现
Jan 06 #Javascript
基于jQuery实现鼠标点击导航菜单水波动画效果附源码下载
Jan 06 #Javascript
JavaScript动态创建div等元素实例讲解
Jan 06 #Javascript
谈谈JavaScript类型系统之Math
Jan 06 #Javascript
莱鸟介绍javascript onclick事件
Jan 06 #Javascript
莱鸟介绍window.print()方法
Jan 06 #Javascript
You might like
用PHP函数解决SQL injection
2006/12/09 PHP
php获取网页内容方法总结
2008/12/04 PHP
firefo xml 读写实现js代码
2009/06/11 Javascript
window.parent调用父框架时 ie跟火狐不兼容问题
2009/07/30 Javascript
5分钟理解JavaScript中this用法分享
2013/11/09 Javascript
javaScript如何生成xmlhttp
2013/12/16 Javascript
javascript实现动态表头及表列的展现方法
2015/07/14 Javascript
JavaScript基础篇(6)之函数表达式闭包
2015/12/11 Javascript
AngularJS入门教程之Cookies读写操作示例
2016/11/02 Javascript
jQuery删除当前节点元素
2016/12/07 Javascript
vue小图标favicon不显示的解决方案
2017/09/19 Javascript
详解vue使用插槽分发内容slot的用法
2019/03/28 Javascript
jQuery实现文本显示一段时间后隐藏的方法分析
2019/06/20 jQuery
Vue实现导航栏的显示开关控制
2019/11/01 Javascript
jquery获取input输入框中的值
2019/11/13 jQuery
[00:35]2016完美“圣”典风云人物:冷冷宣传片
2016/12/08 DOTA
[57:53]Secret vs Pain 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
python实现绘制树枝简单示例
2014/07/24 Python
python分析apache访问日志脚本分享
2015/02/26 Python
numpy找出array中的最大值,最小值实例
2018/04/03 Python
如何使用Python的Requests包实现模拟登陆
2018/04/27 Python
如何在Django中设置定时任务的方法示例
2019/01/18 Python
如何设置PyCharm中的Python代码模版(推荐)
2020/11/20 Python
全球高级音频和视频专家:HiDef Lifestyle
2019/08/02 全球购物
英国第一的滑雪服装和装备零售商:Snow+Rock
2020/02/01 全球购物
大学本科毕业生求职信范文
2013/12/18 职场文书
《回乡偶书》教学反思
2014/04/12 职场文书
市场开发计划书
2014/05/07 职场文书
农业开发项目建议书
2014/05/16 职场文书
2014年高数考试作弊检讨书
2014/12/14 职场文书
《失物招领》教学反思
2016/02/20 职场文书
三八红旗手先进事迹材料(2016推荐版)
2016/02/25 职场文书
pytorch DataLoader的num_workers参数与设置大小详解
2021/05/28 Python
GO语言字符串处理函数之处理Strings包
2022/04/14 Golang
使用MybatisPlus打印sql语句
2022/04/22 SQL Server
Android Studio 计算器开发
2022/05/20 Java/Android