一、单例模式的分类
一个环境中有且只有一个实例,并且当前环境可以访问到它。往小了说,当前环境可以是一个函数作用域、块级作用域,往大了说可以是全局window或者global环境。如果按照实例的创建时机进行单例模式的分类,有:
- 普通单例模式:在环境初始时就创建
- 惰性单例模式:在某个特定的时机才创建
二、惰性单例模式
从单例模式的定义出发,一个环境中有且只有一个实例,并且使用时才去创建它,那么就可以把当前单例模式称之为惰性单例模式
- 惰性,指的是只有在使用的时候才去创建
- 单例,指的是当前环境有且只有单一的一个实例
弹窗案例
:在页面打开的时候,页面中有登录按钮,在点击时,需要创建一个dom节点。
(1)首先,实现一个功能函数:创建节点的函数
var domFun = function () {
var dom = document.createElement('div');
dom.innerHTML = '登录窗口demo'
dom.style.display = 'none';
document.body.appendChild(dom);
return dom;
}
(2)其次,创建管理单例的函数
var createSingle = function (fn) {
var result;
return function () {
return result || (result = fn.apply(this, arguments));
}
}
采用闭包的形式,让result变量在当前环境不销毁,如果该变量已经存在,直接返回,如果没有,让当前环境调用fn功能函数,并赋值给result。该过程保证了当前环境只有一个实例。
(3)将创建节点的函数和管理单例的函数糅合
var createSingleDom = createSingle(domFun)
(4)最后,在点击按钮的时候,进行实例的创建
var loginBtn = document.querySelector('.login')
loginBtn.onclick = function () {
var loginDom = createSingleDom()
console.log(loginDom)
loginDom.style.display = 'block'
}
该过程实现了只有在点击登录按钮的时候才创建节点,是惰性的。
整个过程,将创建惰性实例的过程进行了分解,更易于修改和维护,如果,创建的不是div节点,而是,image图片、iframe嵌套网页、倒计时等其他内容,只需要替换步骤(1)中的内容即可。
这里的例子,我们严格的强调一个实例的事儿。
二、普通单例模式
在vue中的应用:我们知道vue
是一个渐进式框架,主要实现视图的渲染,其他的功能可以可以通过第三方插件按需引入,比如路由插件vue-router
和全局状态管理vuex
。
- 路由
vue-router
的使用
import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);
- 状态
vuex
的使用
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
vue
通过Vue.use(Vuex)
的方式进行vue-router
和vuex
的安装,Vue.use
的代码如下:
Vue.use = function (plugin: Function | Object) {
const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
if (installedPlugins.indexOf(plugin) > -1) {
return this
}
// 去掉参数列表中的第一个
const args = toArray(arguments, 1)
// 将Vue作为this推入到参数的首位
args.unshift(this)
if (typeof plugin.install === 'function') {
plugin.install.apply(plugin, args)
} else if (typeof plugin === 'function') {
plugin.apply(null, args)
}
installedPlugins.push(plugin)
return this
}
可以看出,首次执行vue.use(xxx)
的时候,会将该插件推入到数组installedPlugins
中去,再次执行vue.use(xxx)
的时候,installedPlugins.indexOf(plugin) > -1
为true
,则终止后续逻辑的执行。也就说,vue.use(xxx)
只会让该插件执行一次install
的安装。
再看 const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
,是不是发现,这里也是单例模式的影子,当this._installedPlugins
不存在时为其赋值为[]
,当前存在时直接返回。
单例模式,去掉具体的例,就剩单模式。就像当前例子中,install只执行一次,this._installedPlugins只初始化一次一样,就体现了一个单字。那这算不算单(例)模式呢?
总结
单例模式是不是可以去实例,只留单呢?这样,很多只执行一次的逻辑也就和单例模式能搭上关系了。仁者见仁智者见智,能不能去,纯属个人想法。因为,优秀的单例模式,是经过无数的程序案例得出的经验性汇总。
以上就是JavaScript单例模式能不能去实例只留单原理解析的详细内容,更多关于JavaScript单例模式去实例的资料请关注编程网其它相关文章!