//工厂模式
function creatCar(color,host,size){
var o = new Object();
o.color = color;
o.host = host;
o.size = size;
o.tellColor = function(){alert(o.color);};
return o;
}
var myCar = creatCar("red","Kate",4);
myCar.tellColor();
************************************************************
//构造函数模式
function CreateCar(color,host,size){
this.color=color;
this.host=host;
this.size=size;
this.tellColor=function(){
alert(this.color);
};
}
【1】
var myCar = new CreateCar("red","Kate",4); // 必须用new关键字
myCar.tellColor();
此时myCar里面有一个constructor属性,该属性指向CreateCar
一般用这个来检验类型:alert(myCar instanceof CreateCar);
任何函数用new来调用,都可以当作为构造函数。
【2】
如果当做普通函数来调用,就是如下情形:
在全局作用域中调用一个函数时,this对象总是指向global对象,在浏览器中就是window对象
CreateCar("red","Kate",4);
window.tellColor();
【3】
也可以这样:用函数的方法call在对象o的作用域中调用CreateCar方法
var o = new Object();
CreateCar.call(o,"red","Kate",4);
o.tellColor();
【4】
该方式的问题:每个方法需要在每个实例上重新创建一遍。因此可以做如下修改:
this.tellColor= new Function("alert(this.color)");
//注意这个Function首字母大写
【5】
其实,创建相同的Function实例其实没有必要,这里不需要把函数绑定到特定的对象上面:
function CreateCar(color,host,size){
this.color=color;
this.host=host;
this.size=size;
this.tellColor=tellColor;
}
function tellColor(){
alert(this.color);
}
然而这就没什么封装性可言了。。。
**********************************************************
//原型模式
每个函数都有一个prototype属性,其指向一个对象。该对象包含可由特定类型所有实例共享的属性和方法。所以,把公共的部分移到prototype里面就行了。
function CreateCar(color,host,size){
this.color=color;
this.host=host;
this.size=size;
}
CreateCar.prototype.tellColor = function(){
alert(this.color);
};
【1】
var o = new CreateCar("red","Kate",4);
o.tellColor();
但是这种方法,用call函数是不行的。
【2】
prototype对象有constructor属性,该属性指向prototype属性所在函数的指针。
alert(CreateCar.prototype.constructor==CreateCar); //true
但是如果直接用CreateCar.prototype={ };的形式,constructor就不会指向CreateCar了。此时要用到defineProperty();
对象里有指向prototype的指针
【3】
可以通过对象实例访问保存在原型中 值,但不能通过对象重写原型中的值。然而原型中做的任何修改都能在实例中立即显现出来,哪怕在修改前就有实例化。 但是如果直接用CreateCar.prototype={ };的形式,实例与原型的联系就被切断。里面新定义的属性和方法也不好用。
【4】
实例中的属性会屏蔽原型中相应的属性。如果delete该属性,那么就能访问到原型中相应的属性了
【5】
原型中不能写“引用型”的属性。比如数组、对象。因为存进去的只是一个指针。在实例化不同对象的时候,一个修改了,另一个也会跟着修改。
【6】
CreateCar.prototype.tellColor = function(){
alert(this.color);
};
这个可以写在构造函数的里面,但是需要先判断方法是否存在:
function CreateCar(color,host,size){
this.color=color;
this.host=host;
this.size=size;
if(typeof this.tellColor != "function"){
CreateCar.prototype.tellColor = function(){
alert(this.color);
};
}
}
if的那一块只在初次调用构造函数的时候才会执行
***********************************************************
继承:
子的原型=父的实例
function CreateCar(){
this.color="black";
if(typeof this.tellColor != "function"){
CreateCar.prototype.tellColor = function(){
alert(this.color);
};
}
}
function CreateSmallCar(){
}
CreateSmallCar.prototype = new CreateCar();
var o = new CreateSmallCar();
o.tellColor();
【1】
可以新增CreateSmallCar里原型的方法,CreateSmallCar原型的方法也可以覆盖掉父CreateCar中原型的方法。但是这必须在
CreateSmallCar.prototype = new CreateCar();
这句之后进行
【2】
另外,不能用CreateSmallCar.prototype = { };的方式增加新的方法,这样会重写圆形链,导致之前的语句无效
【3】
如果CreateCar的构造函数中包含引用型属性,那么CreateSmallCar.prototype里面也会包含该类属性,就会出现之前所说的问题
解决方案------在子的构造函数中调用父构造函数,可以用call
function CreateSmallCar(){
CreateCar.call(this);
}
【4】
没法传参,于是下面的是最常用的方式
function CreateCar(color){
this.color=color;
if(typeof this.tellColor != "function"){
CreateCar.prototype.tellColor = function(){
alert(this.color);
};
}
}
function CreateSmallCar(color,owner){
this.owner=owner;
CreateCar.call(this,color);
}
CreateSmallCar.prototype = new CreateCar();
CreateSmallCar.prototype.constructor=CreateSmallCar;
//因为它的上一句,使得CreateSmallCar.prototype被重写。因此需要这样改一下。
var o = new CreateSmallCar("red","Kate");
o.tellColor();