JavaScript中定义对象的四种方式

来源:互联网 发布:apache 官方下载 编辑:程序博客网 时间:2024/05/05 21:31
JavaScript中定义对象的方式
    最近在阅读《JavaScript高级程序设计》,未免遗忘读过的内容,就打算以博客的形式做些读书笔记。今天介绍的是JavaScript中的四种定义对象的方法,除了这四种方法,还有工厂方法来定义对象,但考虑到其简单性及非正规性,这里就不做介绍。和Java这样的面向对象语言相比,JavaScript更像是函数式语言,其并没有类的概念,盖之以对象定义的概念,而具体创建的对象叫做对象的实例。
    1)构造函数方式定义对象。这种方式是在构造函数内定义属性和方法。这里举个简单的例子:
   
function Animal(name){
        
this.name = name;
        
this.introduceSelf = function(){
            window.alert(
"I am a " + this.name+"!");
        };
}
    对象的实例化如下:
var dog = new Animal("dog");
dog. introduceSelf();
    当然,
也可以将对象的方法在构造函数外定义,如下所示:
function introduceSelf(){
    window.alert(
"I am a " + this.name+"!");
}
    
function Animal(name){
    
this.name = name;
    
this.introduceSelf = introduceSelf();
}
  
这种在构造函数内定义所有的属性和方法的方式,使得构造函数相当于Java中类的概念。而将方法的具体定义独立地放在构造函数外,会使得对象的定义和方法的定义并不紧密,如果在一个文件中这样的方法和对象定义多的话,就会看起来凌乱许多。

    2)
原型方式。该方式利用对象的prototype属性,可以将其看成创建新对象所依赖的原型(关于
prototype的详细信息,可以百度一下,这方面的资料还是很多的)。这种方式将构造函数做成空构造函数,然后将所有的属性和方法被直接赋予prototype属性,还是前面的例子,重写如下:
   
function Animal(){
    
}
Animal.prototype.name 
= "animal";
Animal.prototype.introduceSelf 
= function(){
    window.alert(
"I am a " + this.name+"!");
};
//对象的实例如下:
var dog = new Animal();
dog.name 
= "dog";
dog.introductSelf();
  
这种方式的缺点是显而易见的,就是不能在构造函数中对属性进行赋值操作。还有一点是,对于引用类型的属性(如Array实例),实例化的多个对象将共享一个引用。正因为这么多的问题,这种对象定义的方式并不可取。

    3)
构造函数、原型混合方式。这种方式是最为流行的对象定义方式。它结合了构造函数及原型方式。这种方式用构造函数定义对象的所有非函数属性,用原型方式定义对象的函数属性(方法)。重写前面的例子:
function Animal(name){
    
this.name = name;
}
Animal.prototype.introduceSelf 
= function(){
    window.alert(
"I am a " + this.name+"!");
};
   
    4)
动态原型方式。和构造函数、原型混合方式相比,动态原型方式只是在函数属性定义的位置上有所不同。重写前面的例子:

   
function Animal(name){
    
this.name = name;
    
if(typeof Animal._initialized == 'undefined'){
        Animal.prototype.introduceSelf 
= function(){
            window.alert(
"I am a " + this.name+"!");
        };
        Animal._initialized 
= true;
    }
}
      其中_initializedAnimal的全局私有属性(JavaScript中没有私有属性的概念,所有的属性都是共有的,但为了表明一些属性的私有特性,人们习惯在属性名前加上“_”。),当第一次实例化Animal时,if条件就为真,这样就会定义Animal中的函数属性。由于“Animal._initialized = true;”的存在,函数的定义调用一次而无论实例化多少个对象。



评论

 re: JavaScript中定义对象的四种方式2007-04-08 14:42zkj
this.introduceSelf = introduceSelf();

写错了吧 
  

 

re: JavaScript中定义对象的四种方式2007-04-08 20:28
确实不对,我试了一下,name属性根本没有起作用,看来外部方法introduceSelf()需要添加参数name才行! 
  

 

re: JavaScript中定义对象的四种方式2007-04-09 11:57 
楼主的 this.introduceSelf = introduceSelf(); 是不是写错了?

这样的用意, 并不是把introduceSelf()的句柄传给 内部变量this.introduceSelf,而是首先执行了introduceSelf()这个方法, 由于只是一个alert, 故此方法会返回一个underfined,然后赋值给this.introduceSelf.
  

 

re: JavaScript中定义对象的四种方式2007-04-09 19:11 

学艺不精,还需努力!

http://www.blogjava.net/kafka0102/archive/2007/04/08/109213.html

 

 

Javascript对象定义的几种方式http://www.xland.com.cn/article/29/30/0809/29564.htm

一.工厂方式:先创建对象,再向对象添加方法和属性,封闭后调用不要使用new操作符创建对象。使用这种方法有很多弊端,把方法定义在工厂函数内部的时候,每次调用的时候都会产生新的函数

function factory(name,person,address,time){
    var tmp=new Object;
    tmp.name=name;
    tmp.person=person;
    tmp.address=address;
    tmp.workTime=function(){
        alert("we start to work at" + time);
    }
    return tmp;
}
var factory1=factory("drugs",100,"huashan Rd",10);
var factory2=factory("TCMdrugs",100,"hongqiao Rd",11);
factory1.workTime();
factory2.workTime();//Here,factory1 and factory2 have different method
对这种问题虽然可以用下面的方式改进,但是缺乏很好的封装性

function factory(name,person,address,time){
    var tmp=new Object;
    tmp.name=name;
    tmp.person=person;
    tmp.address=address;
    tmp.workTime=workTime();
    return tmp;
}
function workTime(){
    alert("we start to work at" + this.time);
}

二,构造函数方式,在构造函数内部不创建对象,使用this关键字,使用时候用new操作符,存在和工厂方式相同的问题,重复创建函数。

function counstruct(name,person,address,time){
    this.name=name;
    this.person=person;
    this.address=address;
    this.workTime=function(){
        alert("we start to work at" + this.time);
    };
}
三.原型方式:利用prototype属性来实现属性和方法,可以通过instanceof 检查对象类型,解决了重复创建函数的问题,但不能通过传递参数初始化属性

function Car(){
 
}
Car.prototype.color = "red";
Car.prototype.doors = 4;
Car.prototype.mpg = 23;
Car.prototype.showColor = function(){
    alert(this.color);
};
var car1 = new Car();
var car2 = new Car();
但是如果遇到下面的情况,又出问题了

Car.prototype.drivers = new Array("mike", "sue");
car1.drivers.push("matt");
alert(car1.drivers);  //outputs "mike,sue,matt"
alert(car2.drivers);  //outputs "mike,sue,matt"
drivers是指向Array对象的指针,Car的两个实例都指向同一个数组。
四.混合的构造函数/原型方式:针对原型方式的解决方案

function Car(sColor, iDoors, iMpg){
    this.color = sColor;
    this.doors = iDoors;
    this.mpg = iMpg;
    this.drivers = new Array("mike", "sue");
}
Car.prototype.showColor = function (){
    alert(this.color);
};
var car1 = new Car("red", 4, 23);
var car2 = new Car("blue", 3, 25);
car1.drivers.push("matt");
alert(car1.drivers);
alert(car2.drivers);
五.动态原型方式:这种方式是极力推荐的方式,避免了前面几种方式所出现的问题,提供了更友好的编码风格

function Car(sColor, iDoors, iMpg){
    this.color = sColor;
    this.doors = iDoors;
    this.mpg = iMpg;
    this.drivers = new Array("mike", "sue");
   
    if(typeof Car.initialized == "undefined"){
        Car.prototype.showColor = function (){
            alert(this.color);
        };
        Car.initialized = true;
    }
}
 
var car1 = new Car("red", 4, 23);
var car2 = new Car("blue", 3, 25);
 
car1.drivers.push("matt");
alert(car1.drivers);
alert(car2.drivers);
六.混合工厂方式:和工厂方式有些相似,但采用new关键字实例化,具有和工厂方式相同的弊端,不推荐使用

原创粉丝点击