javascript 对象基础定义类或对象(1)

对象基础

  • 封装  --- 把相关信息(无论数据或方法)储存在对象上的能力;
  • 聚集  --- 把一个对象储存在另一个对象上的能力;
  • 继承  --- 有另一个类(或多个)得来类的属性和方法的能力;
  • 多态  --- 编写能以多种方法运行的函数或方法的能力.

1.工厂方式

var oSite = new Object;
oSite.name="noyobo";
oSite.url = "http://noyobo.cnblogs.com/";
oSite.showName = function(){
    alert(this.name);
};

 此代码创建对象 oSite,接着设置了几个属性.它的名字是noyobo ,链接是 http://noyobo.cnblogs.com/  showName 属性是指向函数的指针. 那么这个属性就是一个方法.如果要创建多个 site 实例怎么办呢? 

创建并返回特定类型对象,工厂函数(factory function)

function creatSite(){
    var oTempSite= new Object;
    oTempSite.name="noyobo";
    oTempSite.url = "http://noyobo.cnblogs.com/";
    oTempSite.showName = function(){
        alert(this.name);
    };
    return oTempSite;
}
var oSite1 = new creatSite();
var oSite2 = new creatSite();

 把代码包含在 creatSite() 函数中. 最后一行代码 采用 return oTempSite; 返回该函数值.

创建的  oSite1 和 oSite2 都具有相同的属性和方法. 我们还可以给它传入值

function creatSite(sName,sUrl){
    var oTempSite= new Object;
    oTempSite.name = sName;
    oTempSite.url = sUrl;
    oTempSite.showName = function(){
        alert(this.name);
    };
    return oTempSite;
}
var oSite1 = new creatSite("baidu","wwww.baidu.com");
var oSite2 = new creatSite("google","www.google.cn"); 
oSite1.showName(); // 输出 "baidu"
oSite2.showName(); // 输出 "google"

 给函数 creatSite() 函数加上参数,就可以创建 具有相同属性与方法.却有不同的值.

可这样每创建一个 creatSite() 对象 就创建了一个 showName() , 实际他们共享使用了这一函数.(避免内存浪费) 我们可以这么写

function showName(){
  alert(this.name) // this 总是指向调用该函数的对象
}
function creatSite(sName,sUrl){
    var oTempSite= new Object;
    oTempSite.name = sName;
    oTempSite.url = sUrl;
    oTempSite.showName = showName;
    return oTempSite;
}
var oSite1 = new creatSite("baidu","wwww.baidu.com");
var oSite2 = new creatSite("google","www.google.cn"); 
oSite1.showName(); // 输出 "baidu"
oSite2.showName(); // 输出 "google"

 这样 oSite1 和 oSite2 就共享使用了  showName() 方法.

但是这样看. showName() 并不是 creatSite() 对象的一个方法,我们可以采用 构造函数的方 来创建.

2.构造函数方式

函数名既为类名  类名采用首字母大写. 这是一个好习惯.用于区分其他类型,也与本地对象(Object String Number ... )保持一致

function Site(sName,sUrl){
    this.name = sName;
    this.url = sUrl;
    this.showName = function(){
    alert(this.name);
   }
}
var oSite1 = new Site("baidu","wwww.baidu.com");   
var oSite2 = new Site("google","www.google.cn");  
oSite1.showName(); // 输出 baidu
oSite2.showName(); // 输出 google

 和工厂方式很相似,值是函数内部使用 this 关键字 使用 new 运算符 后就创建了一个对象,并使用this才能访问此对象, 函数内部也不需要 使用 return 放回.默认情况下 构造函数的返回值就是  this . 这里又回了前面提到的 问题.  每个 new 对象 都创建了一个 showName() ;

3.原型方式

该方式使用对象的 prototype 属性.可以看成是新建对象所以来的原型. 重写上面的实例

function Site(){

};
Site.prototype.name = "baidu";
Site.prototype.url = "www.baidu.com";
Site.prototype.showName = function(){
  alert(this.name);
};
var oSite1 = new Site();   
var oSite2 = new Site();  
oSite1.showName(); // 输出 baidu
oSite2.showName(); // 输出 baidu
alert(oSite1 instanceof Site) // 输出 true oSite1 是 Site()的一个对象类型. 使用原型方式还可以使用  instanceof 运算符检查

 这段代码,先定义构造函数 Site() 并没有任何代码. 接下来通过 prototype 添加 Site 的属性 和方法. 从语义上看所有的属性和方法都属于一个对象.

 函数共享上不会存在问题.可是这里不能使用参数初始化的值. 必须在对象创建之后才能改变值. 考虑下面的例子

function Site(){

};
Site.prototype.name = "baidu";
Site.prototype.url = "www.baidu.com";
Site.prototype.area = new Array("beijing","hangzhou");
Site.prototype.showName = function(){
  alert(this.name);
};

var oSite1 = new Site();   
var oSite2 = new Site();  
alert(oSite1.area); // 输出 beijing,hangzhou
alert(oSite2.area); // 输出 beijing,hangzhou
oSite1.area.push("shanghai");
alert(oSite1.area); // 输出 beijing,hangzhou,shanghai
alert(oSite2.area); // 输出 beijing,hangzhou,shanghai

 看到 oSite1.area 属性 添加"shanghai" 之后.  oSite1.area 改变了. 可是 oSite2.area 也跟着改变了.  

这里属性  area 是指向 Array 对象的指针. 该数字包含两个地名"beijing" 和"hangzhou". area 都是引用值.(如工厂模式的第四个例子) Site 的两个实力都是指向同一个数组的,所以改变其中一个.在另一个也能看到. 那我们该如何创建对象的方法呢?   聪明的你可能已经想到了.

3.混合的构造函数/原型方式

重写上面的例子

function Site(sName,sUrl){
  this.name = sName; 
  this.url = sUrl; 
  this.area = new Array("beijing","hangzhou");
};
Site.prototype.showName = function(){
  alert(this.name);
};

var oSite1 = new Site("baidu","wwww.baidu.com"); 
var oSite2 = new Site("google","www.google.cn");   
alert(oSite1.area); // 输出 beijing,hangzhou
alert(oSite2.area); // 输出 beijing,hangzhou
oSite1.area.push("shanghai");
alert(oSite1.area); // 输出 beijing,hangzhou,shanghai
alert(oSite2.area); // 输出 beijing,hangzhou

 现在看起来更像创建一个对象了.所有的属性都在构造函数中创建.我们又可以用参数设置默认值了.并且只创建了一个  showName() 方式.没有造成内存浪费.

 我们再视觉上封装有一下.也让结构看起来更紧凑

function Site(sName,sUrl){
this.name = sName;
this.url = sUrl;
this.area = new Array("beijing","hangzhou");
if(typeof Site._initialized == "undefined"){
Site.prototype.showName = function(){
alert(this.name);
};
//alert("我只运行了一次");
Site._initialized = true;
};
};
var oBaidu = new Site("baidu","www.baidu.com");
var oGoogle = new Site("google","www.google.cn");
oBaidu.showName()

至于使用哪种方式,可能实际中的理解了.不过不要单独使用构造函数 或者 原型方式!

posted @ 2011-12-28 15:53  noyobo  阅读(295)  评论(0编辑  收藏  举报