JavaScript 设计模式 之旅
设计模式开篇
日常开发中,我们都很注重开发技巧,好的开发 技巧可以事半功倍解决此刻的问题。
那么这些技巧如何来得呢?
我的理解:经过不断踩坑,解BUG,总结出来一些处理对应问题解决方案,这就所谓的 技巧。
说起设计模式,其实我们日常开始中也经常用到,只是你不知道用的解决方案方案对应的设计模式名称.
学习设计模式的作用
在软件设计中,模式是一些经过了大量实际项目验证的优秀解决方案。熟悉这些模式的程序员,对某些模式的理解也会自然的形成条件反射。当遇到合适的场景出现时,可以快速找到对应的模式来处理当前的问题。
单例模式
定义: 保证 类 仅有 一个实例,并可以全局访问这个实例.
全局变量 不是 单例模式,但是在JavaScript 中, 我们经常把单例模式当作全局变量使用。
因为它满足单例模式的两点:
- 创建的全局变量是独一无二的
- 它可以全局访问这个变量实例
// login.js var loginInfo = { username: '', token: '', ....... } //login.vue import logins from './login.js' logins.name = this.username
但是它也有缺点,容易造成命名空间污染。
定义的全局变量多了, 会覆盖掉之前定义的全局变量,这样会造成不必要的BUG.
如何处理命名空间污染呢?
如何处理呢?
- 1.使用命名空间
- 2.使用闭包封装私有变量
命名空间
对象自变量的形式:
// login.js export default var loginInfo = { names:'' , token: '', setName: function (name) { this.names = name }, getName: function () { return this.name } } //login.vue import logins from './login.js' logins.token = this.token
使用闭包封装私有变量
把一些变量封装在闭包内部,只暴露一些接口跟外界通信。
外界是访问不到 内部定义的私有变量的,这样就避免了全局命令污染。
var user = (function () { //外界是访问不了 _name _age var _name = '张三', _age = 22; return { //这块留给外界通信用 getUserInfo: function () { console.log(`姓名为:${_name},年龄为:${_age}`) } } })() user.getUserInfo()
通用的惰性单例模式
在该执行的情况下,执行操作步骤 / DOM.
优点:节约了性能。
场景1
有时候,例如登陆弹窗,在加载首页的同时,它会渲染这个页的全部DOM,如果首页DOM 内容多,加载速度也会相应的很慢,有很多不需要DOM提前渲染。
这时,可以通过惰性单例模式来解决此问题,例如单击了登陆按钮,才会创建登陆弹窗的DOM,并且记录此次点击状态,如果下次还要打开,只是更改 DOM 的 style 的 display 属性即可。 这样节约了首页加载时间,提升页面性能。
// 定义全局通用单例模式 var getSingle = function (fn) { var result; return function () { return result || (result = fn.apply(this, arguments)); } } // 创建登陆窗口 var createLoginLayer = function() { var div = document.createElement('div') div.innerHTML = '登陆框' div.style.display = 'none' document.body.appendChild(div) return div } // 创建单例模式 登陆框 var createSingleLoginLayer = getSingle(createLoginLayer); document.getElementById('btn').onclick = () => { // 获取单例模式中 返回得登陆框 var loginLayer = createSingleLoginLayer(); // 改变样式 loginLayer.style.display = 'block' }
场景2
创建唯一的 iframe 用于加载第三方页面
var createSingleIframe = getSingle( function() { var iframe = document.createElement('iframe'); document.body.appendChild(iframe) return iframe }) document.getElementById('redirect').onclick = () => { var iframeLayer = createSingleIframe(); iframeLayer.src = 'http://www.baidu.com' }