浅谈构造模式、原型模式、混合模式、动态原型模式

构造模式 

构造模式虽然比前面的工厂模式更加的完善,能够通过instanceof识别对象类型,但有个最大的问题就是每一次实例化,该对象内部函数都会被创建一遍,就是都会把属性和方法复制一遍。这是什么意思?

举个栗子:
function Person(name,age,job){

this.name=name;

this.age=age;

this.job=job;

this.sayName=function(){

alert(this.name);

 };

}

 var person1=new Person("yao",19,"Student");
 var person2=new Person("xiyao",29,"Teacher");

  在这个例子中,因为每个对象的属性是不一样的,这个没有问题(有意义),但是执行方法执行的是一样的代码,所以我们认为没有必要复制,存在冗余现象,这就是缺点。
  构造模式还有一个缺点就是对象继承并需要在子类中调用父类的方法是不可能的,只可以覆盖或者使用。
  还是那句话,一个问题的出现,肯定有它的解决之案,下面我们一起来学习一下原型模式。


  原型模式


  我们创建的每个函数都有prototype(原型)属性,这个属性是一个指针(地址),指向一个对象,而这个对象的用途是包含可以由特定类型(与构造函数相结合)的所有实例共享(共有)的属性和方法(一劳永逸),使用原型对象的好处就是可以让所有对象实例共享它(原型对象)所包含的属性及方法。都晕了?简单来说就是存放相同的东西,让大家都用。各自不同需求请去构造(自定义嘛)……
  原型模式也不是没有缺点,首先,它省略了构造函数传递初始化参数这一环节,结果所有实例在默认情况下都取得了相同的属性值,这样非常不方便,但这还是不是原型的最大问题,原型模式的最大问题在于共享的本性所导致的,由于共享,因此一个实例修改了引用,另一个也随之更改了引用。因此我们通常不单独使用原型,而是结合原型模式与构造函数模式。
  OK…我们又来解决这个问题,快来一起学习一下混合模式

  

 混合模式


  举个栗子:
  function Blog(name, url, friend) {
    this.name = name;
    this.url = url;
    this.friend = friend;
}

Blog.prototype.alertInfo = function() {
    alert(this.name + this.url + this.friend);
}

var blog1 = new Blog('wuyuchang', 'http://www.cnblogs.com/wuyuchang/', ['fr1', 'fr2', 'fr3']), blog2 = new Blog('wyc', 'http://**.com', ['a', 'b']);

blog1.friend.pop();
blog1.alertInf();                       //wuyuchanghttp://www.cnblogs.com/wuyuchang/fr1,fr2,fr3
blog2.alertInfo();                  // wychttp://**.com,a,b

混合模式中构造函数模式用于定义实例属性,而原型模式用于定义方法和共享属性。每个实例有自己的一份实例属性,同时共享着方法,最大限度的节省了内存。另外这种模式还支持传递初始参数,优点甚多,这种模式在ECMAScript中是使用最广泛、认同度最高的一种创建自定义对象的方法。

 动态原型模式

  动态原型模式将所有信息封装在了构造函数中,而通过构造函数中初始化原型(仅第一个对象实例化时初始化原型),这个可以通过判断该方法是否有效而选择是否需要初始化原型。

举个栗子:

function Blog(name, url) {
    this.name = name;
    this.url = url;

    if (typeof this.alertInfo != 'function') {
    // 这段代码只执行了一次
        alert('exe time');
        Blog.prototype.alertInfo = function() {
            alert(thia.name + this.url);
        }
    }
}

var blog1 = new Blog('wuyuchang', 'http://www.cnblogs.com/wuyuchang'),blog2 = new Blog('wyc', 'http:***.com');

上面的例子中只弹出一次窗:'exe time',当blog1初始化时,这样做blog2就不在需要初始化原型,对于使用这种模式创建对象,可以算是perfect了。

  注意:
  1、ECMA-262中定义,JS变量松散类型(不同于java的强类型)的本质,决定了它只是在特定时间用于保存特定值的一个名字而已,由于不存在必须定义变量数据类型的规则,变量的值及其数据类型可以在脚本生命周期内改变。虽然这是一个既有趣又强大,但同时容易出问题,js变量实际的复杂程度还远不止如此。
  2、ECMAScript变量可能包含两种不同的数据类型的值:基本类型值和引用类型值
  基本类型值指的是那些保存在栈内存(是在类加载中有系统静态分配的,而且分配时按照内存的高低地址分配。这部分内存系统会自动进行释放。)中的简单数据段,即这种值完全保存在内存中的一个位置。

  而引用类型值则是指那些保存在堆内存(首先堆是动态分配的,JVM并不会自动释放这部分内存,只用等待系统的gc来进行内存回收。)中的对象,意思是变量中保存的实际上只是一个指针,这个指针指向内存中的另一个位置,该位置保存对象。(另一个位置,这个概念值得你深思哟?这可能需要你了解一下操作系统的存储管理知识以及虚存知识了)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值