JavaScript关于对象的总结

//工厂模式

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);
    };
}

【1var 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);
};

【1var 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();

 

posted on 2016-03-30 20:04  各种笔记  阅读(195)  评论(0编辑  收藏  举报