js单例模式和闭包

503 阅读1分钟
function Student(options){
    this.init(options)
    // others...
}
Student.prototype.init=function(options){
    // do somthing...
}

/**
 * 全局变量 ProxySingleton 被创建
 * 外面的匿名函数创建并立即执行,暂且叫它A。
 * A执行,创建了A的局部作用域(AO),这个AO中保存了 instance 这个变量。同时A的scope指向window(A在window被创建)
 * A -> window
 
 * 正常调用A完毕后AO将会释放,但是这里不是正常调用。它返回了另外一个匿名函数,暂且叫它B。
 * B被 ProxySingleton 引用 
 * ProxySingleton -> B
 
 * 同时B的scope指向AO(B在AO中被创建)
 * B -> AO
 
 * 最终的结局就是:
 * ProxySingleton全局变量不会被释放,导致B不会被释放
 * B不会被释放 导致 AO不会被释放 
 
 * 下次再调用 ProxySingleton(之前的全局变量),这个全局变量引用着没有被释放的B,这个时候如果B函数体中使用了AO中的变量,就会用到以前的变量值,因为AO也一直没被释放,里面的变量值也就回不到初始值
 * 于是,可以利用AO中的变量值来判断是否是 第一次调用ProxySingleton
 
 * 如果使用了其他的全局变量(例如ProxySingleton2),就会形成多个闭包
 * 避免这种情况,暴露出去的变量只能是ProxySingleton这一个全局变量
 * 消除闭包,释放内存,ProxySingleton=null就行了
 */
var ProxySingleton = (function () {
  var instance = []
  return function (options,id) {
    if(typeof id ==="undefined"){
        id=0
    }
    if (!instance[id]) {
      instance[id] = new Student(options)
    } else {
      console.error('Student是单例模式,本次传入options未生效', options)
    }
    return instance[id]
  }
})()