javascript中声明类的方式

来源:互联网 发布:linux 获取tomcat路径 编辑:程序博客网 时间:2024/05/29 06:36

在JS中,创建对象(Create Object)并不完全是我们时常说的创建类对象,JS中的对象强调的是一种复合类型,JS中创建对象及对对象的访问是极其灵活的。

JS对象是一种复合类型,它允许你通过变量名存储和访问,换一种思路,对象是一个无序的属性集合,集合中的每一项都由名称和值组成(听起来是不是很像我们常听说的HASH表、字典、健/值对?),而其中的值类型可能是内置类型(如number,string),也可能是对象。


1.工厂模式

a.
工厂模式可能是很多开发人员使用的一种模式,简单的说这种方法先定义“地基”,然后在往上面扔(绑定)各种功能和属性。下面的代码可能看起来会非常的熟悉:

var oCar = new Object;oCar.color = "red";oCar.showColor = function() {alert(this.color);}oCar.showColor();

b.
当然,既然包装成一个类,就要重用它(上面的方法从语法上说仅仅是变量)。可以使用返回特定对象的工厂函数(factory function)将其封装起来:
function createCar() {var oCar = new Object;oCar.color = "red";oCar.showColor = function() {alert(this.color);}return oCar;}oCar = createCar();oCar.showColor();

c.
当然,变通一下,可以在 createCar 函数上加入些参数,这样看起来已经非常地专业了:
function createCar(sColor) {var oCar = new Object;oCar.color = sColor;oCar.showColor = function() {alert(this.color);}return oCar;}oCar = createCar();oCar.showColor();

d.
匿名函数总是让人感觉非常的高深,但是有时候也会迷惑了自己.如果不考虑篇幅,可以外部定义它.
(这样做还有一个好处,就是不用重复定义oCar.showColor了)
function showColor() {alert(this.color);}function createCar(sColor) {var oCar = new Object;oCar.color = sColor;oCar.showColor = showColor;return oCar;}oCar = createCar();oCar.showColor();

2.构造函数模式

构造函数其实和工厂方式差不多。从代码量上来说,就是省略了构造函数内部没有创建一个对象。
function Car(sColor) {this.color = sColor;this.showColor = function () {alert(this.color);}}oCar = new Car("red");oCar.showColor();
其实此隐含的对象已经在 new 以后就被实例化了.默认情况下,构造函数返回的就是其this的值(所以不必使用 return 返回).但构造函数模式和工厂模式一样可能会重复定义方法,这点可以参考上述工厂模式的做法避免它(始终看起来不完美).

3.混合模式

看起来越来越完美了,结合上述学到的方法就很容易解决原型模式的问题,这样看起来就更像是专业的程序员了。
function Car(sColor) {this.color = sColor;}Car.prototype.showColor = function() {alert(this.color);}oCar = new Car("red");oCar.showColor();
上述的方法声明的类,showColor 方法是原型(仅创建了一个实例),其他的都是构造(互不干扰).

4.动态原型模式

把自己的方法仍在外面总不是件非常环保的事情,下面的方法就非常的“绿色”:
function Car() {this.color = "red";if (typeof Car._initialized == "undefined") {Car.prototype.showColor = function() {alert(this.color);};Car._initialized = true;}}oCar = new Car("red");oCar.showColor();
此方法于上述的混合模式效果一致,即在构造函数内定义属性,而方法则使用原型模式.唯一的区别就是赋予对象方法的位置.

5.混合工厂模式
混合工厂模式可以认为是构造模式与混合模式的整合,因为 function 本身就是一个对象,所以可以使用 new 来实例化(请允许我这样描述).
function Car() {var oCar = new Object;oCar.color = "red";oCar.showColor = function() {alert(this.color);}return oCar;}oCar = new Car();oCar.showColor();
不过建议避免使用此方法定义,因为于上述的工厂模式一样,它存在重复声明的问题.

选用何种模式?

其实通过上面的描述已经有所结果,通常使用的是 混合模式 与 动态原型模式 (我个人投动态原型模式一票)。不过不要单独使用 工厂模式 与 构造模式 (或者其两者的结合体),因为这样会造成不必要的浪费.

另外还有一篇博客中是这样说的:

一、由一对大括号括起来


var emptyObj = {};var myObj ={'id': 1, //属性名用引号括起来,属性间由逗号隔开'name': 'myName'};//var m = new myObj(); //不支持


  不知你注意到对象都是用 var 声明的没有,像上面的代码,就只是简单的声明一个对象,它只有一份拷贝,你不能像实例化类对象一样对它采用new操作,像上面代码的注释部分。这样就极大的限制了对象的重用,除非你建立的对象只需要一份拷贝,否则考虑用其他方法建立对象。
  下面一起看看如何访问对象的属性和方法。

var myObj ={'id': 1,'fun': function() {document.writeln(this.id + '-' + this.name);//以"对象.属性"方式访问},'name': 'myObj','fun1': function() {document.writeln(this['id'] + '+' + this['name']);//以集合方式访问}};myObj.fun();myObj.fun1();// 结果// 1-myObj 1+myObj 


二、用 function 关键字模拟 class
在 function 中用 this 引用当前对象,通过对属性的赋值来声明属性。如果用var声明变量,则该变量为局部变量,只允许在类定义中调用。

function myClass() {this.id = 5;this.name = 'myclass';this.getName = function() {return this.name;}}var my = new myClass();alert(my.id);alert(my.getName());// 结果// 5// myclass


三、在函数体中创建一个对象,声明其属性再返回
在函数体中创建对象可利用第一点的方法,或先 new Object(); 再为各属性赋值。
不过用这种方式创建的对象在VS2008 SP1中是没有智能提示的。
 function myClass() {var obj ={'id':2,'name':'myclass'};return obj;}function _myClass() {var obj = new Object();obj.id = 1;obj.name = '_myclass';return obj;}var my = new myClass();var _my = new _myClass();alert(my.id);alert(my.name);alert(_my.id);alert(_my.name);// 结果// 2// myclass// 1// _myclass

还有另外一篇博客说的也不错,也一并贴出来:

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 = newShape();



二:定义公有属性和私有属性
我们已经创建了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 = newShape(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本身并不是设计成面向对象的,所以没有class之类的关键字用来定义类,但JavaScript本身相当灵活,可以利用function关键字来定义类并创建对象。JavaScript定义类是有多种方式的,这里只详细介绍最常用的一种。

  1. 一、定义类并创建实例
function MyClass() {this.id = 5;this.name = 'myclass...';}

这样,我们就定义了一个MyClass类,里面有两个公共属性id name。其中this关键字表示当前对象,类似于C#等强类型语言。

注意:列出属性的同时必须对属性进行赋初值,这样JS才会将其解释为对象的属性。

接下来我们可以这样定义类的实例(其中 new不可省略):

var my =new MyClass();

并以下列形式访问类属性:

my.id

  1. 二、定义公有属性和私有字段

function中,用var定义的变量为私有变量,可以理解为类的私有字段。

this定义的变量为公有属性。

function MyClass() {this.id = 5;var name = 'myclass...';}my = new MyClass();alert(my.id);alert(my.name);

//结果

// 5

// undefined

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

同样的,用var定义的方法为私有方法,用this定义的方法为公有方法。

function myClass() {this.id = 5;this.alert = function(msg) {window.alert(msg);}}my = new myClass();my.alert('the function alert is called...');

//结果

// the function alert is called...

如果将上述代码的 this.alert =function(msg)改成var alert =function(msg),那么就不能用my.alert来调用这个方法了。私有方法只能供类内部的其他方法调用。

定义公有方法(实例方法)还有另一种形式,就是利用prototype 属性,
其实prototype 属性还可以用来扩展内置类的实例方法的,比如去掉字符串两边空格的 trim 方法:String.prototype.trim =function() { return ... }

function myClass() {this.id = 5;}myClass.prototype.alert = function(msg) {window.alert(msg);}var my = new myClass();my.alert('the function alert is called...');

将和上面显示同样的结果。

  1. 四、构造函数

新建对象(my =new myClass();)和调用函数(myClass())是相似的,所以我们自然想到为函数添加一些参数,在调用此函数时输入一些参数。新建对象也是一样的。看下面的示例:

function myClass(id, name) {this.id = id;this.name = name;}var my = new myClass(5, 'test name ...');alert(my.id);alert(my.name);

//结果

// 5

// test name ...

这样定义的构造函数有个局限性,实例化对象的时候如果没有传参数,或少传参数,那么没有实参的参数值将会是undefined,比如将上面代码的对象实例化改为:var my = new myClass(5);

输出结果将会变成:

// 5

// undefined

为了让属性具有默认值,比如 int默认是 0,可以采用以下方法,虽然比较麻烦。

function myClass(id, name) {this.id = 0; //整型默认为0this.name = ''; //字符串默认为空字符串if (id != null) { //当 id=undefined 时 id==null 依然为truethis.id = id;}if (name != null) {this.name = name;}}var my = new myClass();alert(my.id);alert(my.name);

//结果

// 0

// (空字符串)

这样的情况下,延伸出另一个问题,就是你无法在构造函数中初始化 idnull

总之,一切看个人需要,灵活应用便是。

  1. 五、静态属性和静态方法

静态的属性和方法是在定义了类之后定义的。如下例:

function myClass() {this.id = 5;}myClass.count = 0; //静态属性myClass.staticFun = function() { //静态方法alert(++myClass.count);}var my = new myClass();alert(my.id); //用实例访问实例属性alert(myClass.count); //用类名访问静态属性myClass.staticFun(); //用类名访问静态方法

//结果

// 5

// 0

// 1

  1. 六、类的继承
  2. 在JS中实现类的继承,实际上是用到了类的另一种创建方式,先创建基类的一个对象,再为这个对象添加新的属性和方法,然后再返回这个对象。
  3. 在这里先不讨论这种创建对象的方法。

    function baseClass() {this.id = 5;}function myClass() {var my = new baseClass();my.name = 'className';my.testFun = function() {alert(my.name); //this.name 也可以}return my;}var my = new myClass();alert(my.id);alert(my.name);my.testFun();
    // 结果
    // 5
    // className
    // className



原创粉丝点击