阿不

潜水

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

【原文地址】Classes in JScript – Part II: Instance Properties / Methods & Class Properties / Methods

【原文发表日期】 Sunday, September 30, 2007 4:17 PM by don.raman

上篇博客,在这篇博客中,我们会更加详细的讨论一下关于实例属性(Instance Properties)和实例方法(Instance Methods),静态属性(Class Properties)和静态方法(Class Methods)。

我仍然会使用上一篇博客中用的例子,并且对它进行一些必要的修改。

function Rectangle (ht, wt) {

                this.height = ht;

                this.width=wt;

}

Rectangle.prototype.area = function() {return this.height * this.width;}

var rect1 = new Rectangle(5,10);

var rect2 = new Rectangle(2,4);

var rect1Area = rect1.area(); // rect1.area() will return 50.

var rect2Area = rect2.area(); // rect2.area() will return 8.

上面的代码是通过定义一个构造器函数(constructor function)定义了一个Rectangle类。Rectangle包含了两个属性heightwidth,同时它还通过它的prototype对象定义了area方法。

在上面的例子中,每个Rectangle对象都有属于自己的widthheight拷贝。这些属性通过拥有它们的对象实例来访问它们,比如rect1height属性可以被赋值给rect2height

rect2.height = rect1.height;

上面的代码演示了属性如何被与它们关联的对象读写。这些属性,我们都称它为实例属性(Instance Properties)。

area方法又是什么呢?它同样也是通过Rectangle的实例访问的,我们称之为实例方法(Instance Method)。

实例方法与实例属性除了两点不同外,其它的特性都一样。第一点不同是,一个方法可以返回多个值。另外一个不同之处在于,并不是所有的实例中都包含有实例方法的拷贝。实例方法可以通过this关键字来引用到当前对象的实例(译注:这里的this与C#中的this起用相似的作用。)。

实例属性和实例方法都只能通过对象的实例来引用。

那么我们再来看一种情况,通过下面的代码添加一个实例方法,将会发生什么事情呢?

rect1.area = function() {return ½ * this.height * this.width;}

它是怎样影响rect1的?它会影响所有的Rectangle对象的实例吗?

要回答这些问题,必须要了解Jscript读写实例属性上的不同规则。

当我们要去读取一个实例(比如rect1)属性(比如:area)时,Jscript解析器会先去检查一下在实例(rect1)上是否已经有定义了这个属性(area)。(译注:有则直接使用,不再进行下面的检查,下面步骤如是。)

如果实例里没有定义这个属性,Jscript解析器会再去检查判断构造器函数(Rectangle)对应的prototype对象是否有定义了这个属性(area)。

如果还是没有,那么Jscript解析器会再去检查构造器函数(Rectangle)对应的prototype对象的构造器函数(Rectangle.prototype.constructor.prototype),直到Object为止。(译注:如果这样一个查找顺序下来还找不到的话,才返回#ff0000)。

当我们试图往对象上写(添加)一个属性时,如果当前的对象上并不存在一个相同名字的属性时,Jscript会在当前的对象上添加这个属性(译注:有存在当然是重新赋值了)。所以此时这个对象(rect1)就拥有了自己的area属性。Jscript在调用属性时将不会再去查找构造器函数(Rectangle)的prototype对象了。

继续解释上面关于属性的读取。当以后(新添加了area以后),再调用当前对象再调用area 属性时(rect1.area())时,始终调用的都是调用了当前对象中新添加的属性,而不是prototype中定义的相同名称的属性。但是,无论什么时候我们调用其它对象的相同属性时,都不会受到这个对象的影响,仍然是调用prototype对象中的area方法。

总结一下,对象实例中定义的属性会覆盖prototype对象上相同名称的属性,但是只是对于当前实例而言的(rect1.area覆盖Rectangle.prototype.area只影响rect1)。其它实例并不会受到影响。

同样是上面的例子。我想要通过一个标准值而区分当前矩形的大小。任何面积小于10的矩形,我们都认为是小矩形,否则就认为是大矩形。

此时,我可以这样定义一个属性:

Rectangle.MINBIGSIZE = 10;

MINBIGSIZE是在构造器函数(类)上定义的一个属性,而不是在实例或prototype对象上。像这样的例子,我们就称它为静态属性(类属性).

静态属性是与类本身相关的,而不是类的对象。不管有多少上对象实例被创建,始终都只有一份静态属性的拷贝。这种属性的访问通过类来完成的。

为了要区分出矩形的大小,我定义type方法来判断:

Rectangle.type = function (obj) {

                var retType;

                obj.area()<Rectangle.MINBIGSIZE ? retType="SMALL" : retType="BIG";

                return retype;

}

MINBIGSIZE一样,type方法也是定义在构造器函数上,这种方法我们则类似的称之为静态方法(类方法)。静态方法就是一个做为构造器函数的一个属性的函数。一个静态方法是与类本身相关联的,而不是类的对象。

上面设计的定义我们可以这样调用:

Rectangle.type(rect1); // would return BIG.

这就是实例属性/方法和静态属性/方法的完整介绍。在下一篇博客中,我将会来讨论关于数据的封装和继承。

希望这篇博客对你有益,也希望你能喜欢。

谢谢!

Ritesh

SDET, JScript Team.

阿不 译

posted on 2007-10-15 14:55  阿不  阅读(863)  评论(3编辑  收藏  举报