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特色的单例模式
看一下例子
假如这个代码很长
有其他人要修改的时候 声明了一个getById 与你之前声明的函数名冲突 就会产生bug
所以要用单例模式
例如这里的Alex 和zhangsan
单例的优点 :1.每个修改的人都创建了一个命名空间 这样就不会产生冲突
2.使代码井井有条
惰性单例
按需创建的单例
<!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>