javascript单例模式及开发实践

作者: Searchen | 来源:发表于2018-04-06 20:40 被阅读31次

    定义:

    保证一个对象(类)仅有一个实例,并提供一个访问它的全局访问点;

    实现原理:

    利用闭包来保持对一个局部变量的引用,这个变量保存着首次创建的唯一的实例;

    主要用于:

    全局缓存、登录浮窗等只需要唯一一个实例的时候;

    Part1、命名空间的管理员
    开发中经常会遇到不同的人定义的变量使用的单词可能会重复,此时就需要用到命名空间来约束每个人定义的变量来解决这类问题。比如小明的代码,他可以定义一个xiaoZhang的空间。同样,我们平时使用的vue定义use()方法我们可以通过vue.use()来访问

    假如小张想实现这样一个效果,点击按钮正方形的背景变成红色

    <style>
       .squareStyle {
        width: 100px;
        height: 100px;
        background-color: yellow;
    }
    </style>
    <body>
    <button id="btn">变黄</button>
    <div id="square" class="squareStyle"></div>
    </body>
    <script>
    var Zhang = {
        a: function (id) {
            return document.getElementById(id)
        }, //获取正方形
        b: function (id, key, value) {
            this.a(id).style[key] = value
        } //这里为什么用this?a,b方法都在单例对象Zhang 中,而当前对象中的this指代当前对象,所以我们还可以在b方法中通过this.a()来使用Zhang单例对象中的a方法
    } //创建空间
    document.getElementById('btn').onclick = function () {
        Zhang.b('square', 'backgroundColor', 'red')
    }
    </script>
    

    this在javascript中的运用详细可以看https://www.jianshu.com/p/041c683f6031这篇文章

    Part2、惰性单例
    需要的时候才被创建对象实例,就是需要的时候才动态调用,而不是页面加载好的时候就创建

    方式一:页面加载好的时候调用,只不过是隐藏状态
        var createLoginAlert = (function () {
          console.log('创建了')
           var div = document.createElement('div')
          div.innerHTML = '我是弹窗'
          div.style.display = 'none'
          document.body.appendChild(div)
           return div
    })()  //自执函数
    
    document.getElementById('btn').onclick = function () {
        createLoginAlert.style.display = 'block'   //点击的时候显示
    }
    

    现在有个问题,就是用户可能只是浏览页面,并不需要弹窗内容,接下来方式二是对方式一的优化

    方式二:点击的时候才创建实例
    <button id="btn">提交</button>
    
     var createLoginAlert = function () {
        var div = document.createElement('div')
        div.innerHTML = '我是弹窗'
        div.style.display = 'none'
        document.body.appendChild(div)
        return div
    }   
    //    点击提交时候创建实例
    document.getElementById('btn').onclick = function () {
        var popUp = createLoginAlert()
        popUp.style.display = 'block'
    }
    

    每一次点击的时候重新创建实例,虽然我们可以在点击浮窗上的关闭按钮时(此处未实现)把这个浮 窗从页面中删除掉,但这样频繁地创建和删除节点明显是不合理的,也是不必要的

    方式三:用一个变量来判断是否已经创建过登录浮窗,没有-->创建,有-->复用
     var createLoginAlert = (function () {
            var div;  //变量
            return function () {
                if (!div) {
                    console.log('没有DIV')
                    div = document.createElement('div')
                    div.innerHTML = '我是弹窗'
                    div.style.display = 'none'
                    document.body.appendChild(div); 
                    return div
                }
                return div
            }
        })()
    
    //    点击提交时候创建实例
    document.getElementById('btn').onclick = function () {
        var popUp = createLoginAlert()
        popUp.style.display = 'block'
    }
    

    Part 3 对象池

    对象池维护一个装载着空闲对象的池子,如果需要对象的时候,不是直接new,而是从对象池中取出,如果对象池中没有空闲对象,则新建一个空闲对象。对象池技术的使用非常广泛,http连接池和数据库连接池都是其代表。在web前端中,对象池使用最多的使得DOM有关的操作。

    对象池的实现

    var objectPoolFactory=function(createObjFn){
    var pool=[],
        create=function(){
            var obj=pool.length>0?pool.shift():createObjFn.apply(this,arguments);            
            return obj;
        },
        recover=function(obj){
            pool.push(obj);
        };
    return {
        create:create,
        recover:recover,
    };
    

    };

    Part 4、 变量缓存

    如果ret不是基本变量,而是一个对象,则可以用来实现缓存,在jQuery的源代码中有很多这样的例子。

    var cache={};//一般定义为一个全局变量
    var tmp=cache[key]||fn(key);
    

    查阅文献:
    《javascript设计模式》《javascript设计模式及开发实践》
    分享文档:
    链接: https://pan.baidu.com/s/1Twpu1hM2YaPsNEqgiXsAZQ 密码: i8jf
    仅限知识分享,请勿商业使用,谢谢

    相关文章

      网友评论

        本文标题:javascript单例模式及开发实践

        本文链接:https://www.haomeiwen.com/subject/bucdqftx.html