精华内容
下载资源
问答
  • JavaScript单例模式

    2019-05-03 19:36:50
    单例模式:一个类只有惟一的一个实例,并且提供全局访问。 一个简单的单例模式如下 //单例模式简单实现 // 单例模式就是保证一个类只有一个实例 function Single(name){ this.name=name; if (!Single...

    单例模式:一个类只有惟一的一个实例,并且提供全局访问。

    一个简单的单例模式如下

        	//单例模式简单实现
        	// 单例模式就是保证一个类只有一个实例
        	function Single(name){
        		this.name=name;
        		if (!Single.instance) {//undefined取非为true
        			Single.instance=this;
        		}
        		return Single.instance
        	}
        	
        	var my1=new Single("tom");
        	var my2=new Single("jack");
        	console.log(my1===my2)//true
        	// console.log(Single.instance)

    惰性单例:单例模式的重点,只有需要的时候才创建实例

    应用场景:曾经在项目中应用过惰性单例。大概需求是这样的:进入主页面,在不点击按钮就弹出一个图片div,点击按钮时才弹出。当时的开发过程(以前还是小白的时候)经历了以下:利用display属性做切换,点击按钮的时候设为block其他时间为none,潜在问题:

    • 用户可能根本不会点击按钮,白白浪费了DOM节点

    好了,我就来动态添加你不就行了吗!用的$(".box").append(..html...),又出现问题了:

    • 用户点击了按钮,叮~弹出了我们的内容框,但是哎呀我不小心手抖了又点了一次???叮 ...又弹出来一个一模一样的....用户“excuse me?”

    这显然是不符合需求的,好的,我再改,判断这个节点存不存在,存在的话我先remove掉再新建一个不就行了嘛!又出问题了:

    • remove节点以及创建节点这样的DOM操作显然会拖慢页面加载速度影响用户体验的

    好的,完美主义者一定要坚持到最后!此时就是用的我们的惰性单例模式使用的时候再创建,且只创建一次。

        var createDiv=(function(){
        		var div;
        		return function(){
        		if (!div) {
        		    $('.box').append(" <p id='myId'>Hello world!</p>");
        			div=document.getElementById("myId");
    	    	}
    	    		return div;
        	}
        })();

     

    展开全文
  • Javascript单例模式

    2019-03-06 19:11:02
    一、什么是单例模式 单例模式的定义是:保证一个类仅有一个实例,并提供一个访问它的全局访问点。 单例模式的实现原理是:用一个变量来标识当前类是否已经创建了实例,如果创建了就直接返回该实例,如果没有创建就...

    一、什么是单例模式

    单例模式的定义是:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

    单例模式的实现原理是:用一个变量来标识当前类是否已经创建了实例,如果创建了就直接返回该实例,如果没有创建就创建新的实例。

    二、实现单例模式

    1.简单的单例模式

    let Singleton = function (name) {
      this.name = name
    }
    
    Singleton.prototype.say = function () {
      console.log(this.name)
    }
    
    Singleton.getInstance = (function () {
      let instance = null
      return function (name) {
        if (!instance) {
          return new Singleton(name)
        }
        return instance
      }
    })()
    
    let s1 = Singleton.getInstance('jack')
    let s2 = Singleton.getInstance('rose')
    
    console.log(s1 === s1) // true
    

    这里我们通过Singleton.getInstance来获取Singleton的唯一对象,但是这种获取对象的方式有些别扭,与传统的new Singleton有些区别,这样就增加了这个类的“不透明性”,即使用必须知道这是一个单例模式,需要通过Singleton.getInstance来获取Singleton的唯一对象。

    2.透明的单例模式

    let CreateDiv = (function (params) {
      let instance
      let CreateDiv = function (html) {
        if (instance) {
          return instance
        }
        this.html = html
        this.init()
        return instance = this
      }
      CreateDiv.prototype.init = function () {
        let div = document.createElement('div')
        div.innerHTML = this.html
        document.body.appendChild(div)
      }
      return CreateDiv
    })()
    let a = new CreateDiv('a')
    let b = new CreateDiv('b')
    console.log(a==b) // true
    

    这样我们就创建了一个透明的单例模式,但是构造函数CreatedDiv看起来有些奇怪,它调用了init方法并保证了只创建一个对象,所以这样不符合单一职责原则。

    所以我们引入代理类:

    let CreateDiv = function (html) {
      this.html = html
      this.init()
    }
    CreateDiv.prototype.init = function () {
      let div = document.createElement('div')
      div.innerHTML = this.html
      document.body.appendChild(div)
    }
    let ProxySingle = (function () {
      let instance
      return function (html) {
        if (!instance) {
          instance = new CreateDiv(html)
        }
        return instance
      }
    })()
    let a = ProxySingle('a')
    let b = ProxySingle('b')
    console.log(a===b) // true
    

    这样我们把负责管理单例的逻辑移到了代理类ProxySingle上,这样CreateDiv类就只负责创建元素,变成了一个普通的类。

    3、JavaScript的单例模式

    javascript是一门没有类的语言,所以在我们创建一个唯一的对象的时候,不需要像传统的语言一样先声明一个类。

    javascript中虽然全局变量不是单例模式,但是在实际开发中我们经常会把全局变量当作单例模式来使用。因为当我们在全局变量下创建一个对象确实是独一无二的,并且该全局变量提供给全局访问,满足了确保只有一个实例,并提供全局访问的核心思想。

    但是全局变量确实也存在诸多的问题,比如在大型项目中全局变量过多往往会造成命名空间的污染。所以我们应该避免使用过多的全局变量,我们可以使用命名空间闭包的来解决全局变量污染的问题。

    3.1、惰性单例

    惰性单例是指在需要的时候才创建对象实例。比如我们前面的instance实例总是在调用Singleton.getInstance才被创建。

    let createLoginLayer = (function () {
        let div
        return function () {
            if(!div) {
                div = document.createElement('div')
            }
            return div
        }
    })()
    document.getElementById('btn').onclick = function () {
        let loginLayer = createLoginLayer()
        loginLayer.style.display = 'block'
    }
    

    3.1、通用的惰性单例

    上面的例子任然违反了单一职责模式,因为创建对象和管理对象单例逻辑的代码都放在createLoginLayer,而却代码的复用性不强,如果我们需要创建的不是一个div而是其他东西就需要把一样的代码重新写一遍。所以我们需要把创建对象和管理单例逻辑的代码分开

    首先我们创建一个管理单例的函数:

    let getSingle = function (fn) {
        let res
        return function () {
            return res || (res = fn.apply(this, arguments))
        }
    }
    

    接下来我们将创建对象的函数作为参数传入getSingle中,之后我们返回一个函数,并且用一个变量resfn的返回结果保存起来。因为res在自身的变量中,所以永远不会被销毁。在之后的请求中如果res已经被赋值则直接返回该值。

    使用:

    // 创建DIV
    let createLoginLayer = function () {
        let div = document.createElement('div')
        return div
    }
    let createSingleLoginLayer = getSingle(createLoginLayer)
    document.getElementById('btn').onclick = function () {
        let loginLayer = createLoginLayer()
        loginLayer.style.display = 'block'
    }
    // 创建script
    let createScript = function () {
        let script = document.createElement('script')
        return script
    }
    let createSingleScript = getSingle(createScript)
    document.getElementById('btn1').onclick = function () {
        let scriptDom = createSingleScript()
        doument.body.appenChild(scriptDom)
    }
    

    总结

    单例模式是一种简单但非常实用的模式,特别是惰性单例,只在需要的时候才创建对像,并且只创建唯一的一个。更奇妙的是,创建对象和管理单例逻辑的职责被分布在两个不同的方法中,这两个方法组合起来才具有单例模式的威力,提高的代码的复用性。

    展开全文
  • javascript 单例模式

    2019-07-07 16:05:12
    javascript里的单例模式单例模式的好处就不做介绍了,只是写出js的单例写法! <!DOCTYPE ...

         javascript里的单例模式,单例模式的好处就不做介绍了,只是写出js的单例写法!

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>JS单例模式</title> <style type="text/css"> div{height:100px; width:100px; background:#CCC; border:#000 1px solid;} </style> <script type="text/javascript"> my = new function yangbin() { this.name = "我是单例funnyzak!"; }; function yangbin1(){ this.name = "我是funnyzak!"; } function myname(){ var u = new yangbin1(); alert(u.name); } </script> </head> <body> <div οnclick="alert(my.name);">你是?(单例)</div> <div οnclick="myname();">你是?(普通)</div> </body> </html>

    运行代码

                 

     

    转载于:https://www.cnblogs.com/leonn/archive/2010/04/08/1707879.html

    展开全文
  • JavaScript 单例模式

    2018-01-15 12:43:00
    单例模式使用的场景 比如线程池、全局缓存等。我们所熟知的浏览器的window对象就是一个单例,在JavaScript开发中,对于这种只需要一个的对象,我们的实现往往使用单例。 实现单例模式 (不透明的) 一般我们是这样...

    定义

    确保一个类仅有一个实例,并提供一个访问它的全局访问点。

    单例模式使用的场景

    比如线程池、全局缓存等。我们所熟知的浏览器的window对象就是一个单例,在JavaScript开发中,对于这种只需要一个的对象,我们的实现往往使用单例。

    实现单例模式 (不透明的)

    一般我们是这样实现单例的,用一个变量来标志当前的类已经创建过对象,如果下次获取当前类的实例时,直接返回之前创建的对象即可。代码如下:

    // 定义一个类
    function Singleton(name) {
        this.name = name;
        this.instance = null;
    }
    // 原型扩展类的一个方法getName()
    Singleton.prototype.getName = function() {
        console.log(this.name)
    };
    // 获取类的实例
    Singleton.getInstance = function(name) {
        if(!this.instance) {
            this.instance = new Singleton(name);
        }
        return this.instance
    };
    
    // 获取对象1
    var a = Singleton.getInstance('a');
    // 获取对象2
    var b = Singleton.getInstance('b');
    // 进行比较
    console.log(a === b);
    

    我们也可以使用闭包来实现:

    function Singleton(name) {
        this.name = name;
    }
    // 原型扩展类的一个方法getName()
    Singleton.prototype.getName = function() {
        console.log(this.name)
    };
    // 获取类的实例
    Singleton.getInstance = (function() {
        var instance = null;
        return function(name) {
            if(!this.instance) {
                this.instance = new Singleton(name);
            }
            return this.instance
        }       
    })();
    
    // 获取对象1
    var a = Singleton.getInstance('a');
    // 获取对象2
    var b = Singleton.getInstance('b');
    // 进行比较
    console.log(a === b);
    

    这个单例实现获取对象的方式经常见于新手的写法,这种方式获取对象虽然简单,但是这种实现方式不透明。知道的人可以通过 Singleton.getInstance() 获取对象,不知道的需要研究代码的实现,这样不好。这与我们常见的用 new 关键字来获取对象有出入,实际意义不大。

    实现单例模式 (透明的)

    var Singleton = (function(){
        var instance;
        var CreateSingleton = function (name) {
            this.name = name;
    
            if(instance) {
                return instance;
            }
            // 打印实例名字
            this.getName();
    
            // instance = this;
            // return instance;
            return instance = this;
        }
        // 获取实例的名字
        CreateSingleton.prototype.getName = function() {
            console.log(this.name)
        }
    
        return CreateSingleton;
    })();
    // 创建实例对象1
    var a = new Singleton('a');
    // 创建实例对象2
    var b = new Singleton('b');
    
    console.log(a===b);
    
    

    这种单例模式我以前用过一次,但是使用起来很别扭,我也见过别人用这种方式实现过走马灯的效果,因为走马灯在我们的应用中绝大多数只有一个。

    这里先说一下为什么感觉不对劲,因为在这个单例的构造函数中一共干了两件事,一个是创建对象并打印实例名字,另一个是保证只有一个实例对象。这样代码量大的化不方便管理,应该尽量做到职责单一。

    我们通常会将代码改成下面这个样子:

    // 单例构造函数
    function CreateSingleton (name) {
        this.name = name;
        this.getName();
    };
    
    // 获取实例的名字
    CreateSingleton.prototype.getName = function() {
        console.log(this.name)
    };
    // 单例对象
    var Singleton = (function(){
        var instance;
        return function (name) {
            if(!instance) {
                instance = new CreateSingleton(name);
            }
            return instance;
        }
    })();
    
    // 创建实例对象1
    var a = new Singleton('a');
    // 创建实例对象2
    var b = new Singleton('b');
    
    console.log(a===b);
    
    

    这种实现方式我们就比较熟悉了,我们在开发中经常会使用中间类,通过它来实现原类所不具有的特殊功能。有的人把这种实现方式叫做代理,这的确是单例模式的一种应用,稍后将在代理模式进行详解。

    说了这么多我们还是在围绕着传统的单例模式实现在进行讲解,那么具有JavaScript特色的单例模式是什么呢。

    JavaScript单例模式

    在我们的开发中,很多同学可能并不知道单例到底是什么,应该如何使用单例,但是他们所写的代码却刚好满足了单例模式的要求。如要实现一个登陆弹窗,不管那个页面或者在页面的那个地方单击登陆按钮,都会弹出登录窗。一些同学就会写一个全局的对象来实现登陆窗口功能,是的,这样的确可以实现所要求的登陆效果,也符合单例模式的要求,但是这种实现其实是一个巧合,或者一个美丽的错误。由于全局对象,或者说全局变量正好符合单例的能够全局访问,而且是唯一的。但是我们都知道,全局变量是可以被覆盖的,特别是对于初级开发人员来说,刚开始不管定义什么基本都是全局的,这样的好处是方便访问,坏处是一不留意就会引起冲突,特别是在做一个团队合作的大项目时,所以成熟的有经验的开发人员尽量减少全局的声明。

    而在开发中我们避免全局变量污染的通常做法如下:

    • 全局命名空间

    • 使用闭包

    它们的共同点是都可以定义自己的成员、存储数据。区别是全局命名空间的所有方法和属性都是公共的,而闭包可以实现方法和属性的私有化。

    惰性单例模式

    说实话,在我下决心学习设计模式之前我并不知道,单例模式还分惰性单例模式,直到我看了曾探大神的《JvaScript设计模式与开发实践》后才知道了还有惰性单例模式,那么什么是惰性单例模式呢?在说惰性单例模式之前,请允许我先说一个我们都知道的lazyload加载图片,它就是惰性加载,只当含有图片资源的dom元素出现在媒体设备的可视区时,图片资源才会被加载,这种加载模式就是惰性加载;还有就是下拉刷新资源也是惰性加载,当你触发下拉刷新事件资源才会被加载等。而惰性单例模式的原理也是这样的,只有当触发创建实例对象时,实例对象才会被创建。这样的实例对象创建方式在开发中很有必要的。

    就如同我们刚开始介绍的用 Singleton.getInstance 创建实例对象一样,虽然这种方式实现了惰性单例,但是正如我们刚开始说的那样这并不是一个好的实现方式。下面就来介绍一个好的实现方式。

    遮罩层相信大家对它都不陌生。它在开发中比较常见,实现起来也比较简单。在每个人的开发中实现的方式不尽相同。这个最好的实现方式还是用单例模式。有的人实现直接在页面中加入一个div然后设置display为none,这样不管我们是否使用遮罩层页面都会加载这个div,如果是多个页面就是多个div的开销;也有的人使用js创建一个div,当需要时就用将其加入到body中,如果不需要就删除,这样频繁地操作dom对页面的性能也是一种消耗;还有的人是在前一种的基础上用一个标识符来判断,当遮罩层是第一次出现就向页面添加,不需要时隐藏,如果不是就是用前一次的添加的。

    实现代码如下:

    // html
    
    <button id="btn">click it</button>
    
    // js
    var createMask = (function() {
        var mask;
        return function() {
            if(!mask) {
                // 创建div元素
                var mask = document.createElement('div');
                // 设置样式
                mask.style.position = 'fixed';
                mask.style.top = '0';
                mask.style.right = '0';
                mask.style.bottom = '0';
                mask.style.left = '0';
                mask.style.opacity = '';
                mask.style.display = 'none';
                document.body.appendChild(mask);
            }
    
            return mask;
        }       
    })();
    
    document.getElementById('btn').onclick = function() {
        var maskLayer = createMask();
        maskLayer.style.display = 'block';
    }
    

    我们发现在开发中并不会单独使用遮罩层,遮罩层和弹出窗是经常结合在一起使用,前面我们提到过登陆弹窗使用单例模式实现也是最适合的。那么我们是不是要将上面的代码拷贝一份呢?当然我们还有好的实现方式,那就是将上面单例中代码变化的部分和不变的部分,分离开来。

    代码如下:

    var singleton = function(fn) {
        var instance;
        return function() {
            return instance || (instance = fn.apply(this, arguments));
        }
    };
    // 创建遮罩层
    var createMask = function(){
        // 创建div元素
        var mask = document.createElement('div');
        // 设置样式
        mask.style.position = 'fixed';
        mask.style.top = '0';
        mask.style.right = '0';
        mask.style.bottom = '0';
        mask.style.left = '0';
        mask.style.opacity = 'o.75';
        mask.style.backgroundColor = '#000';
        mask.style.display = 'none';
        mask.style.zIndex = '98';
        document.body.appendChild(mask);
        // 单击隐藏遮罩层
        mask.onclick = function(){
            this.style.display = 'none';
        }
        return mask;
    };
    
    // 创建登陆窗口
    var createLogin = function() {
        // 创建div元素
        var login = document.createElement('div');
        // 设置样式
        login.style.position = 'fixed';
        login.style.top = '50%';
        login.style.left = '50%';
        login.style.zIndex = '100';
        login.style.display = 'none';
        login.style.padding = '50px 80px';
        login.style.backgroundColor = '#fff';
        login.style.border = '1px solid #ccc';
        login.style.borderRadius = '6px';
    
        login.innerHTML = 'login it';
    
        document.body.appendChild(login);
    
        return login;
    };
    
    document.getElementById('btn').onclick = function() {
        var oMask = singleton(createMask)();
        oMask.style.display = 'block';
        var oLogin = singleton(createLogin)();
        oLogin.style.display = 'block';
        var w = parseInt(oLogin.clientWidth);
        var h = parseInt(oLogin.clientHeight);
    }
    
    

    在上面的实现中将单例模式的惰性实现部分提取出来,实现了惰性实现代码的复用,其中使用apply改变改变了fn内的this指向,使用 || 预算简化代码的书写。

    设计模式相关文章

    展开全文
  • javascript单例模式

    2017-04-02 23:05:47
    单例模式javascript中特别常用,在javascript中什么叫做单例模式?通过确保单例对象只存在一个实例,你就可以确信自己的所有的代码使用的多是同样的全局资源。 单例模式的实现: 1.直接定义全局对象 (function(){ //...
  • 主要为大家详细介绍了JavaScript单例模式,帮助大家轻松掌握JS单例模式,感兴趣的小伙伴们可以参考一下
  • 主要介绍了javascript单例模式的简单实现方法,以javascript创建唯一实例的形式分析了javascript单例模式的简单实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下
  • 主要介绍了原生javascript单例模式的应用,结合实例形式分析了JavaScript单例模式的基本功能、原理、应用及操作注意事项,需要的朋友可以参考下
  • 主要介绍了javascript 单例模式详解及简单实例的相关资料,需要的朋友可以参考下

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,179
精华内容 471
关键字:

javascript单例模式

java 订阅