常见问题当前位置:帝豪2娱乐 > 常见问题 > >

帝豪2娱乐:JavaScript实现设计模式中的单例模式的

  

[JavaScript,设计模式,单例模式]JavaScript实现设计模式中的单例模式的一些技巧总结

  

一、使用全局变量保存单例  

  

这是最简单的实现方法  

  
  
  function Person(){  this.createTime=new Date();  }  var instance=new Person();  function getInstance(){  return instance;  }  
  
  

加载该js时就创建一个Person对象,保存到instance全局变量中,每次使用都取这个对象。如果一次都没使用,那么创建的这个对象则浪费了,我们可以优化一下,  

  
  
  var instance  function getInstance(){  if(!instance){  instance=new Person();  }  return instance;  }  
  
  

这样,第一次使用时才创建对象。

  
  这个方法的缺点是,instance是全局的变量,在多人合作或者开发周期比较长的情况下,很难保证instance不会被其它代码修改或覆盖,很可能到调用的时候,发现instance根本就不是Person对象。

  
  我们考虑下使用闭包来封装起instance,使它不再是全局变量就可以解决这个问题了  

  

二、闭包创建对象  

  
  
  var getInstance(){  var instance;  return function(){  if(!instance){  instance=new Person();  }  return instance;  }  }();  
  
  

这样,instance就被封装起来了,不用担心被修改了。

  
  现在通过getInstance()函数可以获得单例了。新的问题,如果我通过new Person()来创建对象,获得的还是多个对象,javascript又不可以像java一样把构造器私有化。那怎么样可以让多次new出来的对象都是一个实例呢?

  

  

三、构造函数的静态属性缓存实例  

  

先看代码  

  
  
  function Person(){  //如果已经缓存了实例,则直接返回缓存的实例  if(typeof Person.instance==='object'){  return Person.instance;  }  this.createTime=new Date();  //缓存实例  Person.instance=this;  return this;  }  
  
  

从代码可以看到,第一次new时,if的条件返回false,会往下走,初始化对象,然后保存对象到Person.instance这个静态属性中。

  
  第二次new 时,if的条件返回true,直接返回Person.instance,不会再往下运行初始化的代码。所以不管new几次,返回的都是第一次创建的对象。

  

  

这个方法的缺点和方法一的缺点一样,Person.instance也是公开属性,有可能会被修改。

  

  

我们参考方法二,使用闭包来封装一个,也许就能解决该问题了  

  

四、重写构造函数  

  

这个方法要使用闭包,但不能像方法二那么简单,我们需要重写构造函数。

  

  
  
  function Person(){  //缓存实例  var instance=this;  this.createTime=new Date();  //重写构造函数  Person=function(){  return instance;  }  }  
  
  

第一次new 时,调用原始构造函数先缓存该实例,然后再初始化,同时,重写该构造函数。以后再new 时,永远调用不到原始的构造函数了,只能调用到重写后的构造函数,而这个函数总是返回缓存的instance.

  
  上面的方法似乎没什么问题,但通过下面的测试,可以发现问题  

  
  
  //向原型添加属性  Person.prototype.prop1=true;  var p1=new Person();  //在创建初始化对象后,再次向该原型添加属性  Person.prototype.prop2=true;  var p2=new Person();  //开始测试  console.log(p1.prop1);//结果为true  console.log(p2.prop1);//结果为true  console.log(p1.prop2);//结果为undefined  console.log(p2.prop2);//结果为undefined  console.log(p1.constructor===Person);//结果为false  console.log(p2.constructor===Person);//结果为false  
  
  

我们预期中的结果,应该是全都是true。

  
  分析一下上述测试代码  

  

Person.prototype.prop1=true;是在原始构造函数的原型下增加了prop1这个属性,并赋值  

  

而在执行 var p1=new Person();之后,Person这个构造函数已经被重写了  

  

所以Person.prototype.prop2=true;是在新的原型下增加prop2这个属性  

  

var p2=new Person(); p2和p1实际上是同一个对象,即原始构造函数创建的对象  

  

所以p1 p2都有prop1这个属性,而没有prop2这个属性  

  

同样的,p1 p2的constructor指向的也是原始的构造函数,而Person此时已不是原来那个函数了   (责任编辑:admin)

上一篇:extJs 常用到的增,删,改,查操作代码

下一篇:没有了

推荐内容