通过一个getInstance
方法获取对象,首先判断一个对象是否存在,如果存在则就将改对象返回,如果不存在就先实例化对象(创建对象),然后再返回
let Singleton = function(name){
this.name = name;
}
// 将实例存储在对象中
Singleton.getInstance = function() {
// 如果本身到
if(this.instance === null){
this.instance = new Singleton();
}
return this.instance;
}
let aIns = Singleton.getInstance("test");
let bIns = Singleton.getInstance("test");
console.log(aIns === bIns);
// 将实例使用闭包的形式存储起来
Singleton.getInstanceNew = (function() {
let instance = null;
return function(){
if(instance === null){
instance = new Singleton();
}
return instance;
}
}())
let cIns = Singleton.getInstanceNew("test");
let dIns = Singleton.getInstanceNew("test");
console.log(cIns === dIns, aIns === dIns);
我们看到以上两个方法,都是创建单例的简单方法,虽然实现了,但是如果别人不知道这个对象时单例的,还是可以使用
new
关键字创建。并且不再是单例了,所以很容易违背了我们单例的初心
我们依然通过new
创建实例,但是创建的还是单例的,这样即使不需要我们特意去嘱咐这个对象是单例
var TransparentSingleton = (function() {
var instance = null;
var TransparentSingleton = function(){
if(instance){
return instance;
}
this.init();
return instance = this;
}
TransparentSingleton.prototype.init = function(){
console.log("Dom操作")
}
return TransparentSingleton;
}())
let eIns = new TransparentSingleton();
let fIns = new TransparentSingleton();
console.log(eIns === fIns);
这种方法虽然满足了我们的要求,但是这里存在一个问题,就是内部的
TransparentSingleton
的这对象,成为了一个私有对象,我们在外面无法访问到
var CreateDom = function(html){
this.html = html;
this.init();
}
CreateDom.prototype.init = function(){
console.log(this.html);
}
var ProxyCreateDom = (function(){
let instance = null;
return function(html){
if(instance === null){
instance = new CreateDom(html);
}
return instance;
}
}())
let hIns = new ProxyCreateDom("测试");
let gIns = new ProxyCreateDom("前端");
console.log(hIns === gIns, hIns.html, gIns.html)
这里我们将对象提了出来了,通过
ProxyCreateDom
去创建一个关于CreateDom
的单例,但是这个版本是比较有限的,我们可以看到这个代理单例并不是一个可复用的,代码很可能会翻倍。并且不管我们需不要单例,其实ProxyCreateDom
里的instance
就创建了。并且这个是属于传统面向对象语言的,在JavaScript这个没有类的语言中,这样创建意义并不大
let getSingleton = function(func) {
let result = null;
return function(){
return result || (result = func.apply(this, arguments));
}
}
function createLoginLayer(){
var div = document.createElement("div");
div.innerHTML = "我是登录浮窗";
div.style.display = "none";
document.body.appendChild(div);
return div;
}
/**
* 测试代码
*/
let createSingleLoginLayer = getSingleton(createLoginLayer);
// 添加一个登陆浮窗
document.getElementById("loginTest").onclick = function(){
var loginLayer = createSingleLoginLayer();
loginLayer.style.display = "block"
}
// 创建一个iframe的单例
var createSingleIfame = getSingleton(function () {
var iframe = document.createElement("iframe");
document.body.appendChild(iframe);
return iframe;
})
// 创建一个iframe,并将src属性设置为百度
document.getElementById("loginBtn").onclick = function(){
var loginLayer = createSingleIfame();
loginLayer.src = "http://baidu,com";
}
// 将浮窗单例隐藏
document.getElementById("closeLoginBtn").onclick = function(){
var loginLayer = createSingleLoginLayer();
loginLayer.style.display = "none"
}
// 改变iframe的src属性
document.getElementById("changeUrlBtn").onclick = function(){
var loginLayer = createSingleIfame();
loginLayer.src = "http://127.0.0.1:5500/index.html";
}
原文:https://www.cnblogs.com/wangzhaoyv/p/14403958.html