在vue,react的横行的时代,单例模式估计知道的人不多了,但是作为一个要成为高级高开的前端er,必须知道的单例模式这几点
什么是单例模式
单例模式是保证一个class类只有一个实例
并提供一个访问它的全局访问点
//版本1
var SingleTon = function (name) {
this.name = name
this.instance = null
}
SingleTon.prototype.getName = function () {
alert(this.name)
}
SingleTon.getInstance = function (name) {
if (!this.instance) {
this.instance = new SingleTon(name)
}
return this.instance
}
var a = SingleTon.getInstance('gaofeng')
var b = SingleTon.getInstance('gaofeng2')
alert(a == b) //true
//版本2
SingleTon.getInstance1 = (function () {
var instance = null
return function (name) {
if (!instance) {
instance = new SingleTon(name)
}
return instance
}
})()
var a1 = SingleTon.getInstance1('gaofeng')
var b1 = SingleTon.getInstance1('gaofeng2')
alert(a1 == b1) //true
//向页面中插入一个div
var CreateDiv = (function () {
var instance = null
var CreateDiv = function (html) {
if (instance) {
return instance
}
this.html = html
this.init()
return instance = this
}
CreateDiv.prototype.init = function () {
var div = document.createElement('div')
div.innerHTML = this.html
div.style.backgroundColor = 'red'
div.style.width = '100px'
div.style.height = '100px'
div.style.color = '#fff'
document.body.appendChild(div)
}
return CreateDiv
})()
var a = new CreateDiv('gaofeng')
var b = new CreateDiv('gaofeng2')
//可以看到页面值插入了一个div
//用代理实现构造函数
var CreateDiv = function (html) {
this.html = html
this.init()
}
CreateDiv.prototype.init = function () {
var div = document.createElement('div')
div.innerHTML = this.html
div.style.backgroundColor = 'green'
div.style.width = '100px'
div.style.height = '100px'
div.style.color = '#fff'
document.body.appendChild(div)
}
//代理类
var ProxySingleTon = (function () {
var instance = null
return function (html) {
if (!instance) {
instance = new CreateDiv(html)
}
return instance
}
})()
var c = new ProxySingleTon('gaofeng')
var d = new ProxySingleTon('gaofeng2')
页面也只出现了div
//动态创建命名空间
var myApp = {}
myApp.namespace = function (name) {
var parts = name.split('.')
var current = myApp
for (var i in parts) {
// console.log(i, 'i')
if (!current[parts[i]]) {
current[parts[i]] = {}
}
//改变current当前的遍历数据
current = current[parts[i]]
}
}
myApp.namespace('event')
myApp.namespace('a.test.app')
console.dir(myApp)
使用闭包封装私有变量
var user = (function () {
var _name = 'gaofeng'
, _age = 29
return {
getUserInfo() {
return _name + " " + _age
}
}
})()
console.log(user.getUserInfo()) //gaofeng 29
惰性单例写一个弹窗
//方式1 缺点是一开始就创建好了,如果不用的话就会浪费资源
var loginDiv = (function () {
var div = document.createElement('div')
div.innerHTML = `<div class="loginMain">
<h2>登陆提示</h2>
<p>我是登陆弹窗</p>
<div><button id="closeBtn">关闭</button></div>
</div>`
div.id = "loginDiv"
div.style.display = 'none'
document.body.appendChild(div)
return div
})()
document.getElementById('login').onclick = function () {
loginDiv.style.display = 'block'
let btn = document.getElementById('closeBtn')
btn.onclick = function () {
console.log('aaaaa')
loginDiv.style.display = 'none'
}
}
//方式2 没有了单例的功能,会不断的创建新的div
var loginDiv = function () {
var div = document.createElement('div')
div.innerHTML = `<div class="loginMain">
<h2>登陆提示</h2>
<p>我是登陆弹窗</p>
<div><button id="closeBtn">关闭</button></div>
</div>`
div.id = "loginDiv"
div.style.display = 'none'
document.body.appendChild(div)
return div
}
document.getElementById('login').onclick = function () {
let div = loginDiv()
div.style.display = 'block'
let btn = document.getElementById('closeBtn')
btn.onclick = function () {
console.log('aaaaa')
div.style.display = 'none'
}
}
//方式3
var loginDiv = (function () {
var div = null
return function () {
if (!div) {
div = document.createElement('div')
div.innerHTML = `<div class="loginMain">
<h2>登陆提示</h2>
<p>我是登陆弹窗</p>
<div><button id="closeBtn">关闭</button></div>
</div>`
div.id = "loginDiv"
div.style.display = 'none'
document.body.appendChild(div)
}
return div
}
})()
document.getElementById('login').onclick = function () {
let div = loginDiv()
div.style.display = 'block'
let btn = document.getElementById('closeBtn')
btn.onclick = function () {
console.log('aaaaa')
div.style.display = 'none'
}
}
//方式4 封装出一个通用的惰性单例模式
var singleTon = (function () {
var div = null
return function (fn) {
return div || (div = fn.apply(this, arguments))
}
})()
document.getElementById('login').onclick = function () {
let div = singleTon(function () {
let div = document.createElement('div')
div.innerHTML = `<div class="loginMain">
<h2>登陆提示</h2>
<p>我是登陆弹窗</p>
<div><button id="closeBtn">关闭</button></div>
</div>`
div.id = "loginDiv"
div.style.display = 'none'
document.body.appendChild(div)
return div
})
div.style.display = 'block'
let btn = document.getElementById('closeBtn')
btn.onclick = function () {
console.log('aaaaa')
div.style.display = 'none'
}
}
//方式5 对方式4的进一步的封装
var singleTon = (function () {
var div = null
return function (fn) {
return div || (div = fn.apply(this, arguments))
}
})()
var createDiv = function () {
let div = document.createElement('div')
div.innerHTML = `<div class="loginMain">
<h2>登陆提示</h2>
<p>我是登陆弹窗</p>
<div><button id="closeBtn">关闭</button></div>
</div>`
div.id = "loginDiv"
div.style.display = 'none'
document.body.appendChild(div)
return div
}
document.getElementById('login').onclick = function () {
let div = singleTon(createDiv)
div.style.display = 'block'
let btn = document.getElementById('closeBtn')
btn.onclick = function () {
console.log('aaaaa')
div.style.display = 'none'
}
}
至此,单例模式的首先就完成了。