构造函数而不是类

来源:百度文库 编辑:神马文学网 时间:2024/04/29 12:22:56
原 型 | JavaScript 函数是最棒的 2009-01-04

构造函数而不是类

关键字: javascript oop

构造函数而不是类

前面提到过,有关JavaScript OOP的最奇怪的事情是,JavaScript不想C#或C++那样,它没有类。在C#中,在执行类似下面的操作时:

C#代码
  1. Dog spot = new Dog();  

 将返回一个对象,该对象是Dog类的实例。但在JavaScript中,本来就没有类。与访问类最近似的方法是定义构造函数,如下所示:

Js代码
  1. function DogConstructor(name)    
  2. {   
  3.     this.name = name;   
  4.     this.respondTo = function(name)    
  5.     {   
  6.         if(this.name == name)    
  7.         {   
  8.             alert("Woof");           
  9.         }   
  10.     };   
  11. }   
  12.   
  13. var spot = new DogConstructor("Spot");   
  14. spot.respondTo("Rover"); // nope   
  15. spot.respondTo("Spot"); // yeah!  

 那么,结果会怎么样呢?暂时忽略 DogConstructor 函数定义,看一看这一行:

Js代码
  1. var spot = new DogConstructor('Spot');  

 "new"运算符执行的操作很简单。首先,它创建一个新的空对象,然后执行紧随其后的函数调用,将新的空对象设置为该函数中"this"的值。换句话说,可以认为上面这行包含"new"运算符的代码与下面两行代码的功能相当:

Js代码
  1. // create an empty object   
  2. var spot = {};    
  3. // call the function as a method of the empty object   
  4. DogConstructor.call(spot, 'Spot');  

 (call函数的第一个参数是调用DogConstructor()函数的对象,第二个参数是DogConstructor()函数的参数)

正如在DogConstructor主体中看到的那样,调用此函数将初始化对象,在调用期间关键字"this"将引用此对象。这样,就可以为对象创建模板!只要需要创建类似的对象,就可以与构造函数一起调用"new",返回的结果将是一个完全初始化的对象。这与类非常相似,不是吗?实际上,在JavaScript中构造函数的名称通常就是所模拟的类的名称,因此在上面的示例中,可以直接命名构造函数Dog:

Js代码
  1. // Think of this as class Dog   
  2. function Dog(name) {   
  3.     // instance variable    
  4.     this.name = name;   
  5.     // instance method? Hmmm...   
  6.     this.respondTo = function(name) {   
  7.         if(this.name == name) {   
  8.             alert('Woof');           
  9.         }   
  10.     };   
  11. }   
  12.   
  13. var spot = new Dog('Spot');  

 在上面的Dog定义中,我定义了名为name的实例变量。使用Dog作为其构造函数所创建的每个对象都有它自己的实例变量名称副本(前面提到过,它就是对象词典的条目)。这就是希望的结果。毕竟,每个对象都需要它自己的实例变量副本来表示其状态。但如果看看下一行,就会发现每个Dog实例也都有它自己的responseTo方法副本,这是个浪费;您只需要一个可供各个Dog实例共享responseTo实例!通过在Dog以外定义responseTo,就可以避免此问题,如下所示:

Js代码
  1. function respondTo()    
  2. {   
  3.     // respondTo definition   
  4. }   
  5.   
  6. function Dog(name)    
  7. {   
  8.     this.name = name;   
  9.     // attached this function as a method of the object   
  10.     this.respondTo = respondTo;   
  11. }  

 这样,所有Dog实例(即用构造函数Dog创建的所有实例)都可以共享responseTo方法的一个实例。但随着方法数量的增加,维护工作将越来越难。最后,基本代码中将有很多全局函数,而且随着"类"的增加,事情只会变得更加糟糕(如果它们的方法具有相似的名称,则尤甚)。是使用原型对象可以很好地解决这个问题,这是下一节的主题。