js单例模式

设计模式 :复用别人总结的解决问题的经验

js单例模式




单例模式:保证一个类只有一个实例 并提供一个访问他的全局访问点



看一个例子

// function Minister(name) { // 大臣
//     this.name = name;
// }
// Minister.prototype.say = function () {
//     console.log(this.name + ':大王,冤枉啊!');
// };
// function Emperor() { // 皇帝
//     this.name = '大王';
//     this.id = Math.random();
// }
// Emperor.prototype.say = function () {
//     console.log(this.name + this.id + ':滚……');
// };
// var minister1 = new Minister('张三');
// var emperor1 = new Emperor();
// var minister2 = new Minister('李四');
// var emperor2 = new Emperor();
// var minister3 = new Minister('王二麻子');
// var emperor3 = new Emperor();
// minister1.say();
// emperor1.say();
// minister2.say();
// emperor2.say();
// minister3.say();
// emperor3.say();

这里的大王id每次实例都在变化    不是很友好


如何修改?


// function Minister(name) { // 大臣
//     this.name = name;
// }
// Minister.prototype.say = function () {
//     console.log(this.name + ':大王,冤枉啊!');
// };
// function Emperor() { // 皇帝
//     this.name = '大王';
//     this.id = Math.random();
// }
// Emperor.prototype.say = function () {
//     console.log(this.name + this.id + ':滚……');
// };
// Emperor.getInstance = (function () {
//     var instance = null;

//     return function () {
//        if (!instance) {
//           instance = new Emperor();
//        }
//        return instance;
//     };
// })();
// var minister1 = new Minister('张三');
// var emperor1 = Emperor.getInstance();
// var minister2 = new Minister('李四');
// var emperor2 = Emperor.getInstance();
// var minister3 = new Minister('王二麻子');
// var emperor3 = Emperor.getInstance();
// minister1.say();
// emperor1.say();
// minister2.say();
// emperor2.say();
// minister3.say();
// emperor3.say();
这样修改后的id每次都是一样的了  但是有个问题  instance可能会被外部修改


但是如果我想正常的new出一个实例呢?

function Minister(name) { // 大臣
   this.name = name;
}
Minister.prototype.say = function () {
   console.log(this.name + ':大王,冤枉啊!');
};
var Emperor = (function () {
   var instance = null;

   function Emperor() {
      if (instance) {
         return instance;
      }
      this.name = '大王';
      this.id = Math.random();
      return instance = this;
   }
   Emperor.prototype.say = function () {
      console.log(this.name + this.id + ':滚……');
   };

   return Emperor;
})();
var minister1 = new Minister('张三');
var emperor1 = new Emperor();
var minister2 = new Minister('李四');
var emperor2 = new Emperor();
var minister3 = new Minister('王二麻子');
var emperor3 = new Emperor();
minister1.say();
emperor1.say();
minister2.say();
emperor2.say();
minister3.say();
emperor3.say();



问:getInstance方法该如何理解呢?

getInstance()它可以把一个已存在的引用给你使用,getInstance()可以跨栈区域使用,或者远程跨区域使用。所以getInstance()通常是创建static静态实例方法的。跟new的功能差不多,但是又不一样,这个仅作了解即可,开发中我们用new创建对象比较多一些。.

.



具有js特色的单例模式

看一下例子

js单例模式

假如这个代码很长

有其他人要修改的时候 声明了一个getById 与你之前声明的函数名冲突 就会产生bug


所以要用单例模式

例如这里的Alex  和zhangsan

js单例模式


单例的优点  :1.每个修改的人都创建了一个命名空间 这样就不会产生冲突


2.使代码井井有条

js单例模式




惰性单例

按需创建的单例

js单例模式






<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>具有JavaScript特色的单例模式--惰性单例</title>
<style>
   body {
      background-color: #f0f0f0;
   }
   #loginLayer {
      position: absolute;
      left: 240px;
      top: 80px;
      z-index: 2;
      width: 200px;
      height: 200px;
      border: 1px solid #ccc;
      background-color: #fff;
      text-align: center;
   }
   #maskLayer {
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      background-color: #000;
      opacity: 0.3;
   }
</style>
</head>
<body>
   
<button id="loginBtn">登录</button>
<!-- <div id="loginLayer">登录窗口</div>
<div id="maskLayer"></div> -->

<script>
   
// 通用惰性单例
function createLoginLayer() {
   var loginLayer = document.createElement('div');
   loginLayer.id = 'loginLayer';
   loginLayer.innerHTML = '登录窗口';
   loginLayer.style.display = 'none';
   document.body.appendChild(loginLayer);
   return loginLayer;
}
function createMaskLayer() {
   var maskLayer = document.createElement('div');
   maskLayer.id = 'maskLayer';
   maskLayer.style.display = 'none';
   document.body.appendChild(maskLayer);
   return maskLayer;
}
function getSingleton(fn) {//专门实现单例
   var instance = null;

   return function () {
      return instance || (instance = fn.apply(null, arguments));//有些函数需要传参 所以改写为这样  null表示不改变this
   };
}
var createSingletonLoginLayer = getSingleton(createLoginLayer);
var createSingletonMaskLayer = getSingleton(createMaskLayer);
document.getElementById('loginBtn').onclick = function () {
   var loginLayer = createSingletonLoginLayer();
   var maskLayer = createSingletonMaskLayer();
   loginLayer.style.display = 'block';
   maskLayer.style.display = 'block';
};
</script></body></html>