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()
至于使用哪种方式,可能实际中的理解了.不过不要单独使用构造函数 或者 原型方式!