`
zhyt710
  • 浏览: 205687 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JavaScript定义类的几种方式

阅读更多

原文链接http://blog.csdn.net/avon520/archive/2009/01/17/3819751.aspx

 

  提起面向对象我们就能想到类,对象,封装,继承,多态。在《javaScript高级程序设计》(人民邮电出版社,曹力、张欣译。英文名字 是:Professional JavaScript for Web Developers)这本书中描述的还算比较详细。我们看看JavaScript中定义类的各种方法。

1.工厂方式

    javaScript中创建自己的类和对象,我们应该是必须掌握的,我们都知道javaScript中对象的属性可以在对象创建后动态定义,比如下面的代码:

<script type="text/javascript">
    //定义
    var oCar = new Object();
    oCar.color = "red";
    oCar.doors = 4;
    oCar.showColor = function() {
        alert(this.color);
    }
    //调用
    oCar.showColor();
</script> 

    我们很容易使用oCar对象,但是我们创就是想创建多个Car实例。我们可以使用一个函数来封装上面的代码来实现:<script type="text/javascript">
    //定义
    function createCar() {
        var oCar = new Object();
        oCar.color = "red";
        oCar.doors = 4;
        oCar.showColor = function() {
            alert(this.color);
        }
        return oCar;
    }
    //调用
    var ocar1 = createCar();
    var ocar2 = createCar();
    ocar1.color = "black";
    ocar1.showColor();
    ocar2.showColor();
</script>

    顺便说一下,javaScript对象默认成员属性都是public 的。这种方式我们称为工厂方式 ,我们创造了能创建并返回特定类型的对象的工厂。

    这样做有点意思了,但是在面向对象中我们经常使用创建对象的方法是:

Car car=new Car();

    使用new 关键字已经深入人心,因此我们使用上面的方法去定义总感觉别扭,并且每次调用时都去创建新的属性以及函数,功能上也不实际。下来我们看看构造函数的形式定义类。

2.构造函数

这种方式看起来有点象工厂函数。具体表现如下:

<script type="text/javascript">
    //定义
    function Car(color, doors) {
        this.color = color;
        this.doors = doors;
        this.showColor = function() {
            alert(this.color);
        };
    }
    //调用
    var car1 = new Car("red", 4);
    var car2 = new Car("blue", 4);
    car1.showColor();
    car2.showColor();
</script> 

    看起来效果很明显,有差别了吧。感觉有点意思了。在构造函数内部创造对象使用this 关键字,使用new 运算符创建对象感觉非常亲切。但是也有点问题:每次new 对象时都会创建所有的属性,包括函数的创建,也就是说多个对象完全独立,我们定义类的目的就是为了共享方法以及数据,但是car1对象与car2对象都是 各自独立的属性与函数,最起码我们应该共享方法。这就是原形方式的优势所在。

3.原型方式

利用对象的prototype属性,可把它看出创建新对象所依赖的原型。方法如下:

<script type="text/javascript">
    //定义
    function Car() {
    };
    Car.prototype.color = "red";
    Car.prototype.doors = 4;
    Car.prototype.drivers = new Array("Tom", "Jerry");
    Car.prototype.showColor = function() {
        alert(this.color);
    }
    //调用:
    var car1 = new Car();
    var car2 = new Car();
    car1.showColor();
    car2.showColor();
    alert(car1.drivers);
    car1.drivers.push("stephen");
    alert(car1.drivers); //结果:Tom,Jerry,stephen
    alert(car2.drivers); //结果:Tom,Jerry,stephen

//可以用json方式简化prototype的定义:

        Car.prototype =
        {
            color: "red",
            doors: 4,
            drivers: ["Tom", "Jerry",'safdad'],
            showColor: function() {
                alert(this.color);
            }
        }
</script>

    首先这段代码的构造函数,其中没有任何代码,接下来通过对象的prototype属性添加属性定义Car对象的属性。这种方法很好,但是问题是Car的对 象指向的是Array指针,Car的两个对象都指向同一个Array数组,其中一个对象car1改变属性对象的引用(数组Array)时,另一个对象 car2也同时改变,这是不允许的。

    同时该问题也表现在原型不能带任何初始化参数,导致构造函数无法正常初始化。这需要另一种方式来解决:那就是混合的构造函数/原型模式。

4. 混合的构造函数/原型模式

联合使用构造函数和原型方式,定义类就非常方便。

<script type="text/javascript">
//定义
    function Car(color,doors)
   {
        this.color=color;
        this.doors=doors;
        this.drivers=new Array("Tom","Jerry");
   }

   Car.prototype.showColor=function(){
        alert(this.color);
   }
  
   //调用:
   var car1=new Car('red',4);
   var car2=new Car('blue',4);
  
   car1.showColor();
   car2.showColor();
  
   alert(car1.drivers);
   car1.drivers.push("stephen");
   alert(car1.drivers); //结果:Tom,Jerry,stephen
   alert(car2.drivers); //结果:Tom,Jerry
   alert(car1 instanceof Car);

</script>

    该方法是把属性放在内部定义,把方法放在外边利用prototype进行定义。解决了第三种方法的问题。

    这种方法其实应该来说非常友好了,但是比起java的语法来,应该有一些不和谐,感觉比较凌乱,对C++来说,我们就没有那么麻烦的感觉了,可是开发 C++的研发人员一般情况下很少涉及javaScript,而对J2EE的研发人员来说,这种方式总有一些别扭。总感觉不是友好的封装,其实只不过是视觉 上封装效果不是很好而已,要想达到视觉封装效果而又能达到这种方法的效果的也可以以,个人认为其实比较麻烦。那就是动态原型法。

5.动态原型

对于习惯使用其他语言的开发者来说,使用混合的构造函数 / 原型方式感觉不那么和谐。毕竟,定义类时,大多数面向对象语言都对属性和方法进行了视觉上的封装 。考虑下面的 C# 类:

class Car //class
{
    public string color = "red";
    public int doors = 4;
    public int mpg = 23;

    public Car(string color, int doors, int mpg) //constructor
    {
        this.color = color;
        this.doors = doors;
        this.mpg = mpg;
    }
    public void showColor() //method
    {
        Console.WriteLine(this.color);
    }
}

C# 很好的打包了 Car 类的所有属性和方法,因此看见这段代码就知道它要实现什么功能,它定义了一个对象的信息。批评混合的构造函数 / 原型方式的人认为,在构造函数内存找属性,在其外部找方法的做法不合逻辑。因此,他们设计了动态原型方法,以提供更友好的编码风格。

动态原型方法的基本想法与混合的构造函数 / 原型方式相同,即在构造函数内定义非函数属性,而函数属性则利用原型属性定义。唯一的区别是赋予对象方法的位置。 下面是用动态原型方法重写的 Car 类:

    <script type="text/javascript">
        //定义
        function Car() {
            this.color = "red";
            this.doors = 4;
            this.drivers = new Array("Tom", "Jerry");
            if (typeof Car._initialized == "undefined") {
                Car.prototype.showColor = function() {
                    alert(this.color);
                }
                //............
            }
            //最后定义
            Car._initialized = true;
        }
    </script>

直到检查 typeof Car._initialized 是否等于 "undefined " 之前,这个构造函数都未发生变化。这行代码是动态原型方法中最重要的部分。如果这个值未定义,构造函数将用原型方式继续定义对象的方法,然后把 Car._initialized 设置为 true 。如果这个值定义了(它的值为 true 时, typeof 的值为 Boolean ),那么就不再创建该方法。简而言之,该方法使用标志( _initialized )来判断是否已给原型赋予了任何方法。该方法只创建并赋值一次,为取悦传统的 OOP 开发者,这段代码看起来更像其他语言中的类定义了。

6  混合工厂方式

这种方式通常是在不能应用前一种方式时的变通方法。它的目的是创建假构造函数,只返回另一种对象的新实例。这段代码看来与工厂函数非常相似:

function Car() {
            var oTempCar = new Object();
            oTempCar.color="red";
            oTempCar.doors=4;
            oTempCar.mpg=23;
            oTempCar.showColor = function() {
                alert(this.color);
            }
            return oTempCar;
        }

与经典方式不同,这种方式使用 new 运算符,使它看起来像真正的构造函数:
var oCar = new Car();

由于在 Car() 构造函数内部调用了 new 运算符,所以将忽略第二个 new 运算符(位于构造函数之外)。在构造函数内部创建的对象被传递回变量 var 这种方式在对象方法的内部管理方面与经典方式有着相同的问题。强烈建议:除非万不得已(请参阅第 15 章),还是避免使用这种方式。
总结:(采用哪种方式)
目前使用最广泛的是混合的构造函数 / 原型方式 。此外,动态原型方法 也很流行,在功能上与构造函数 / 原型方式等价。可以采用这两种方式中的任何一种。不过不要单独使用经典的构造函数或原型方式,因为这样会给代码引入问题。
//ps
//static class (1:function)
    var CarCollection = new function() {
        var _carCollection = new Array(); //global,private
        this.Add = function(objCar) {
            alert('Add');
        }
        this.Get = function(carid) {
            alert('Get');
        }
    }

//static class (2:json)

    var Car = {
        color: 'red',
        doors: 4,
        showColor: function() { alert(this.color); }
    }
    Car.showColor();

分享到:
评论

相关推荐

    JavaScript定义类的几种方式总结

    JavaScript定义类的几种方式包括工厂方式、构造函数和原型方式,每种方法都有其特点和适用场景,接下来我们将详细探讨。 工厂方式是最早期的面向对象编程在JavaScript中的实践之一。使用工厂方式定义类,本质上就是...

    Javascript对象定义的几种方式

    Javascript对象定义的几种方式

    JavaScript定义类或函数的几种方式小结

    JavaScript中定义类或函数,主要有以下几种方式: 1. 工厂方式 工厂方式是JavaScript中创建对象的一种模式,它通过一个工厂函数来封装创建对象的代码。通过工厂函数,我们可以创建多个具有相同属性和方法的对象实例...

    JAVASCRIPT中定义对象的几种方式.pdf

    在讨论JavaScript中定义对象的几种方式之前,我们先理解一下JavaScript中的对象到底是什么。JavaScript是一种基于原型的编程语言,对象是其核心概念之一。对象可以被视为一个容器,存储各种键值对集合,键为属性名,...

    关于JavaScript定义类和对象的几种方式

    综上所述,在JavaScript中定义类和对象的几种方式各有优劣。直接量方式适用于简单对象的快速定义;工厂方式适用于需要大量重复创建类似对象的场景;而原型方式则提供了代码复用和性能优化的可能性。开发者可以根据...

    在JavaScript中实现类的方式探讨

    在JavaScript中实现类的方式主要有几种,包括对象字面量(Object Literal)、构造函数(Constructor)、原型链(Prototype Chain)以及ES6引入的类语法。每种方式都有其适用的场景和特点,理解它们有助于我们更好地...

    javascript中定义类的方法汇总

    在JavaScript中,定义类的方法多种多样,这使得开发者可以根据需求选择最合适的方式来创建对象。以下是几种主要的方法: 1. **工厂方式**: 工厂模式是一种创建对象的模式,通过函数来模拟类的概念。在JavaScript...

    JavaScript学习之二 — JavaScript创建对象的8种方式

    JavaScript是Web开发中不可或缺的一部分,尤其在前端领域更是发挥着...以上就是JavaScript创建对象的8种常见方式,每种方式都有其适用场景和优缺点。理解并熟练运用这些技巧,可以帮助你在JavaScript开发中游刃有余。

    JavaScript中定义类的方式详解

    以上就是JavaScript中定义类的几种常见方式,虽然它们没有像其他面向对象语言那样提供显式的`class`关键字,但JavaScript的灵活性使得开发者可以通过这些技巧实现面向对象编程的需求。在实际开发中,随着ES6的引入,...

    CKevens#-#05-02.面向对象:类的定义和继承的几种方式1

    前言类与实例:类的声明生成实例类与继承:如何实现继承:继承的本质就是原型链继承的几种方式类的定义、实例化类的定义/类的声明方式一:用构造函数模拟类(传统写法)/

    aspnet操作javascript类

    在ASP.NET中,我们可以通过以下几种方式使用JavaScript类: 1. **定义和实例化JavaScript对象**:在HTML或者JavaScript代码中,可以定义一个函数构造器,通过new关键字来创建对象实例。例如,定义一个名为Person的...

    haoyi2015#Web-1#05-02.面向对象:类的定义和继承的几种方式1

    前言类与实例:类的声明生成实例类与继承:如何实现继承:继承的本质就是原型链继承的几种方式类的定义、实例化类的定义/类的声明方式一:用构造函数模拟类(传统写法)/

    javascript面向对象编程的几种模式详解

    以下是对标题和描述中提到的几种JavaScript面向对象编程模式的详细解释: 1. **构造函数与字面量结合模式** 在JavaScript中,我们可以通过构造函数和字面量语法来创建对象。构造函数用于定义对象的类型,而字面量...

    JS函数的几种定义方式分析

    函数的定义方式多种多样,每种方式都具有特定的用途和特点。本文将对这些函数定义方式及其区别和使用技巧进行分析。 首先,我们来看第一种也是最常用的函数定义方式——函数声明: ```javascript function func1(...

    【JavaScript源代码】详解js创建对象的几种方式和对象方法.docx

    本文将深入探讨JavaScript中创建对象的几种常见方式以及对象方法。 首先,我们来看“工厂模式”。工厂模式是一种创建对象的抽象方式,通过一个函数来返回一个新的对象。例如: ```javascript function getObj(name...

    javascript数组定义的几种方法

    数组在JavaScript中的定义有多种方式,下面将详细讲解。 1. **隐式创建**: ```javascript var arr1 = [1, 3, 5, 7, 9]; ``` 这种方式直接通过方括号 `[]` 创建数组,并在括号内列出数组的初始元素。 2. **...

Global site tag (gtag.js) - Google Analytics