65.9K
CodeProject 正在变化。 阅读更多。
Home

JavaScript 中的 OOP。

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.76/5 (15投票s)

2004年9月14日

5分钟阅读

viewsIcon

53079

JavaScript 编程语言的 OOP 方面。

引言

Sergey Zavadski 的文章介绍了 JavaScript 编程语言的对象模型,并展示了 JavaScript 中 OOP(面向对象编程)的常见实践。

JavaScript 的简洁性。

事实证明,JavaScript 是最容易学习和使用的编程语言之一。 一小段代码(实际上是一行)可以执行各种操作,例如创建窗口或更改状态栏中的文本。 灵活性、简短的学习曲线以及 JavaScript 不是“强类型”语言的事实,解释了 JavaScript 在 Web 开发者社区中的极高人气,他们选择这种语言作为为静态 HTML 页面提供动态吸引人内容的语言。

强大的工具

然而,尽管 JavaScript 表面上很简单,但当遵循 DOM 规范时,它实际上是一个非常先进且功能强大的工具,为创建复杂的(客户端)解决方案(如菜单、树、网格等)提供了所有必需的功能。这些可能性实际上反映了 JavaScript 在图层操作方面的强大功能。 这并非最重要的原因,而是 JavaScript 编程语言的 OOP 结构,它被设计和实现为一种面向对象的语言!

对象模型

JavaScript 对象是具有属性的实体,这些属性可以是其他对象或变量。 例如,我们有一个 Country_Italy 对象。 我们可以像这样为该对象的属性赋值

Country_Italy.Name=”Italy”;
Country_Italy.Capital=”Rome”;
Country_Italy.Area=301000;

但是,‘Country_Italy’ 对象本身也可以是另一个对象的属性

Europe.MostBeautifulCountry= Country_Italy;

JavaScript 带有像 WindowMathString 等内置对象的库。 但使该语言真正灵活的是创建自定义对象的能力。 在 JavaScript 中创建自定义对象有两种可能的方法。 第一种是使用直接初始化。 这种情况下代码可能看起来像这样

Country={Name:”France”,Capital:”Paris”,Government:{President:”Jacques Chirac”}};

我们创建了具有‘Name’、‘Capital’ 和‘Government’ 属性的 Country 对象,并且‘Government’ 属性是一个具有自己属性列表的对象。 我们还用初始值初始化了这些属性。 所有这些都在一个字符串中完成。 以下构造创建并初始化了空对象

Country={};

在 JavaScript 中创建对象的另一种方法是定义特殊函数构造函数,并使用‘new’运算符初始化对象。 例如

function Country(Name,Capital,Population){
     this.Name=Name;
     this.Capital=Capital;
     this.Population=Population;
}

Country’函数是构造函数。 现在,要使用这个定义的构造函数创建对象,我们使用 new 运算符

Country_Italy=new Country(“Italy”,”Rome”,301000);

就像在前面的示例中一样,属性可以是对象本身

function Government(President){
     this.President=President;
}
 
function Country(Name,Capital,Government){
     this.Name=Name;
     this.Capital=Capital;
     this.Government=Government;
}
Government_France=new Government(“Jacques Chirac”);
Country_France=new Country(“France”,”Paris”,Government_France);

JavaScript 中完全实现的 OOP 的另一个优点是对象可以拥有方法(而不仅仅是属性)。 方法是在对象范围内描述的函数,通常操作对象属性。 方法的描述方式与属性类似

function describeCountry(){
           var desc=”Name: ”+this.Name+” Capital: ”+
this.Capital+” Population: “+this.Population;
           alert(desc);
}

在上面的定义中,this 运算符提供了对描述的方法所属对象的访问。

Country_Italy.describeCountry=describeCountry;

下面的构造完全重复了上面的构造

Country_Italy.describeCountry=function(){
           var desc=”Name: ”+this.Name+” Capital: ”+
this.Capital+” Population: “+this.Population;
     alert(desc);
}

构造

Country_Italy.describeCountry();

调用‘Country_Italy’对象的‘describeCountry’方法。

基于原型的面向对象语言

与某些其他流行的 OO 语言(Java、C++)不同,后者的对象模型基于类,JavaScript 的对象模型基于原型。 这两种方法的主要区别在于,在基于原型的语言中,类和类实例实体之间没有区别——你只处理对象。

原型(可以看作是定义初始对象属性值如何分配的模板)是任何用原型运算符声明的对象。 该对象可以是任何新创建对象的父对象,这就是 JavaScript 支持继承的方式——OOP 语言的重要特征。 让我们看看我们的 Country 对象

function Country(Name,Capital,Population){
      this.Name=Name;
      this.Capital=Capital;
      this.Population=Population;
}

现在,让我们声明‘Cn’——‘Country’对象的原型

Cn=Country.prototype;

Cn.describeCountry=function(){
           var desc=”Name: ”+this.Name+” Capital: ”+
this.Capital+” Population: “+this.Population;
           alert(desc);
}

现在,我们可以用只有两行代码的方式在任何‘Country’的后代中调用‘describeCountry’方法

Country_Italy=new Country(“Italy”,”Rome”,301000);
Country_Italy.describeCountry();

使用这种方法,我们可以在原型中定义任意数量的方法和属性。 在原型中定义方法和属性,而不是直接为每个对象定义它们,有很多优点

  • 每次设计对象时,您不必定义所有必需的方法或属性。 您在原型中定义所有必需的方法和属性,然后您所要做的就是创建对象。
  • 使您的代码更安全,因为您可以将所有对象定义保留在一个单独的文件中。
  • 使您的代码更易于阅读。

继承

JavaScript 还支持继承机制,这是 OOP 的基石。

为了展示 JavaScript 继承机制的简便性,让我们回顾一下我们已经定义的两个对象:“Country”和“Government”,以及一个新对象“Parliament”。

这些对象的构造函数将是这样的

function Country(Name,Capital,Population){
     this.Name=Name;
           this.Capital=Capital;
     this.Population=Population;
}
 
function Government(President){
     this.President=President;
}
 
function Parliament(Speaker){
     this.Speaker=Speaker;
}

看看‘Country’对象原型。

Cn=Country.prototype;
 
Cn.describeCountry=function(){
           var desc=”Name: ”+this.Name+” Capital: ”+
this.Capital+” Population: “+this.Population;
     alert(desc);
}

以下构造定义了‘Country’为‘Government’原型(‘Government’继承自‘Country’)

Government.prototype=new Country("France","Paris",59330000);

当创建‘Government’对象时,它会继承‘Country’的所有方法和属性。 换句话说,虽然‘describeCountry()’方法未为‘Government’对象定义,但它可用,因为‘Country’对象被定义为‘Government’原型。

Government_France=new Government("Jacques Chirac");
Government_France.describeCountry();

还可以为‘Government_France’对象定义新方法

Government_France.describeGovernment=function(){
             alert(“President: ”+this.President);
}

让我们完成‘Parliament’对象定义。

Parliament.prototype=new Country("France","Paris",59330000);
 
Pn=Parliament.prototype;
Pn.describeParliament=function(){
     alert("Speaker: "+this.Speaker);
}

Parliament_France=new Parliament("Jean-Louis Debre");

如您所见,原型也可以为继承的对象修改。

上面的例子展示了 JavaScript OOP 模型的优雅,它使这种易于学习的语言能够执行各种复杂的实际编程任务。

实际示例

在我们的公司开发 CodeThat.Com 的 Web 控件集时,就使用了这种 OOP 方法。 例如,‘CodeThatCalendar’只不过是一个声明为

 function CodeThatCalendar(def) {
     this.def = def;
     this.links = {};
     this.styles = {};
     this.hideifr = true;
           
     if (typeof(this.def.img_path)!="undefined") {
         if (this.def.img_path.lastIndexOf("\/")!=this.def.img_path.length-1)
             this.def.img_path=this.def.img_path+"\/";           
     }
             
     if (typeof(this.def.template_path)!="undefined") {
         if (this.def.template_path.lastIndexOf("/")!=
                       this.def.template_path.length-1) 
             this.def.template_path=this.def.template_path+"/";             
         if (this.def.template_path.indexOf("\/")!=0) 
             if (typeof(this.def.img_path)!="undefined" && 
                        this.def.img_path.indexOf("\/")!=0) {
                 s=this.def.template_path;
                   a=s.split("/");
                 a.length=a.length-1;
                 t="";
                 for (i=0; i<a.length; i++){
                     t=t+"../";
                 }
                 this.img_path=t+this.def.img_path;      
                 } 
         }
     };
 
var CTc = CodeThatCalendar.prototype;
 
CTc.hide = function()
     {
     …
     }
 
CTc.create = function(d,ctl) {
           …
    }

控件的各种方法使用图层,为控件提供精美的外观和感觉,并使用户能够执行日历应执行的各种操作。 例如,下面的函数将 HTML 表单控件的值设置为用户选择的日期。 每次用户单击日历日期时都会执行此操作。

function CodeThatSetDay(c,f,d,m,y,i,ifr) {
     var doc;
     var w = window.opener||this.parent;
 
     if(w&&!i)
           doc = w.document;
     else
           doc = document;
     var e = CodeThatFind(doc,c);
     if(Def(e))
     {
           e.value=CodeThatDateFormat(f,d,m,y);
           if(e.fireEvent) e.fireEvent("onchange");
           else {
            if(e.onchange) e.onchange();   
           }
     }
 
     if(w&&!i)                            
     {
 
           if(Def(w) && Def(ifr))
           {
                var iframe = CodeThatFind(doc,ifr);
                if(Def(iframe))
                     iframe.style.visibility = 'hidden';
                if(ua.opera6)
                {
                     var d = CodeThatFind(doc,"calendar_div");
                     if(Def(d))
                     d.style.visibility='hidden';
                }
           }
           else
           {
                window.close();
           }
     }
};

(CodeThatCalendar 函数的示例不完全可用。此处列出仅供说明之用)。如您所见,JavaScript 确实是一种强大且用户友好的编程语言,它具有许多功能,有助于创建真正复杂且有趣的解决方案。由于大多数现代浏览器都支持 DOM 模型,因此您可以确信您的解决方案将对大多数用户可用。当然,JavaScript 中还有很多东西需要学习:事件、DOM、图层以及跨浏览器兼容性有时也不那么透明,但这又是另一篇故事或……几篇故事。

© . All rights reserved.