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

    2020-02-22 10:46:21
    JS单例模式 (Singleton) 单例模式的核心是确保 一个特定类只有一个实例,并提供这个实例的全局访问 在构造函数的静态属性中缓存该实例 function Sington() { if(typeof Sington.instance === 'object') { return...

    JS单例模式 (Singleton)

    单例模式的核心是确保 一个特定类只有一个实例,并提供这个实例的全局访问

    1. 在构造函数的静态属性中缓存该实例

      function Sington() {
          if(typeof Sington.instance === 'object') {
              return Sington.instance
          }
          Sington.instance = this
          return this
      }
      
      var a = new Sington()
      var b = new Sington()
      console.log(a === b)	// true
      

      这种方式的缺点在于: instance 属性是公开可访问的属性,在外部代码中可能会修改该属性。

    2. 把实例封装在闭包中

      function Sington() {
          var instance = this
          // 重写构造函数
          Sington = function() {
              return instance
          }
      }
      
      var a = new Sington()
      var b = new Sington()
      console.log(a === b)	// true
      

      当第一次调用构造函数时,它正常返回 this ,然后在以后调用时,它将会执行重写构造函数,这个构造函数通过闭包访问了私有 instance 变量,并且简单的返回了该 instance

      这样可以保证该实例的私有性并且保证该实例不会在构造函数之外被修改,代价是带来了额外的闭包开销。

    3. 有时候对于单例对象需要延迟创建,所以在单例中还存在一种延迟创建的形式( 惰性单例)

      var Singleton = (function() {
        var instance
        Singleton = function() {
          if (instance) return instance
          return instance = this
        }
        return Singleton
      })()
      
      var a = new Singleton('a')
      var b = new Singleton('b')
      console.log(a===b)
      

      这种方法有缺点:不符合单一职责原则,这个对象其实负责了两个功能:单例和创建对象

    4. 改进版惰性单例

      var Singleton = function(Obj) {
      	var instance
      	Singleton = function(...args) {
      		if (instance) return instance
      		return (instance = new Obj(...args))
      	}
      	return Singleton
      }
      
      var People = function(name, age) {
          this.name = name
          this.age = age
      }
      
      var peopleSingleton = Singleton(People)
      
      var a = new peopleSingleton('a', 12)
      var b = new peopleSingleton('b', 11)
      console.log(a)	// People { name: 'a', age: 12 }
      console.log(b)	// People { name: 'a', age: 12 }
      console.log(a === b)	// true
      
    5. 单例模式应用场景 – 页面弹框

      <!DOCTYPE html>
      <html lang="en">
      	<head>
      		<meta charset="UTF-8" />
      		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
      		<title>Document</title>
      	</head>
      	<body>
      		<button id="loginBtn">click me</button>
      		<script>
      			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'
      				div.style.border = '1px solid #ccc'
      				document.body.appendChild(div)
      				return div
      			}
      			var createSingleLoginLayer = getSingle(createLoginLayer)
      			document.getElementById('loginBtn').onclick = function() {
      				var loginLayer = createSingleLoginLayer()
      				loginLayer.style.display = 'block'
      			}
      		</script>
      	</body>
      </html>
      
    展开全文
  • js 单例模式

    2018-04-09 16:12:44
    js 单例模式 顾名思义: 只能生成一个 实例对象 &lt;!DOCTYPE html&gt; &lt;html lang="en"&gt; &lt;head&gt; &lt;meta charset="UTF-8"&gt; &lt;...

    js 单例模式

    顾名思义: 只能生成一个 实例对象

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>js_singleton_pattern_edition02(improvement)</title>
        <style>
            div {
                color: red;
            }
        </style>
    </head>
    <body>
        <button id="login">login</button>
        <script>
            // 单例模式实现: 通过一个 标志来判定 实例是否只生成了一次
            // 依旧是通过闭包保存一个 非全局变量 result 
            var getSingle = function (fn) {
                var result; // 这里用一个 flag 就可以了 , 来标志是否是单例
                return function () {
                    return result || (result = fn.apply(this, arguments))
                };
            }
            // 生成 单例函数
            var createDiv = getSingle(function (){
                var div = document.createElement('div');
                div.innerHTML = "我是登录悬浮框";
                div.style.display = 'none';
                document.body.appendChild(div);
                return div;
            });
    
            document.getElementById('login').onclick = function () {
                var odiv = createDiv();
                odiv.style.display = 'block';
            }
    
            // 将上述管理单例的逻辑抽离出来
            // 创建实例对象的职业 和 管理单例职责 相互独立
            var getSingle = function (fn) {
                var result;
                return function () {
                    return result || (result = fn.apply(this.arguments))
                }
            }
        </script>
    </body>
    </html>
    展开全文
  • JS单例模式

    2020-03-09 20:02:31
    单例模式 把判断单例的逻辑封装在 getSingle函数内部,创建对象的方法 fn 被当成参数动态传入 getSingle 函数:(想要获得特定的元素只需要传入对应的fn就可以了,而无需改变getSinglel函数) var getSingle = ...

    单例模式

    把判断单例的逻辑封装在 getSingle函数内部,创建对象的方法 fn 被当成参数动态传入 getSingle 函数:(想要获得特定的元素只需要传入对应的fn就可以了,而无需改变getSinglel函数)

    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('loginBtn').onclick = function () {
        var loginLayer = createSingleLoginLayer();
        loginLayer.style.display = 'block';
    };
    

    这种单例模式的用途远不止创建对象,比如我们通常渲染完页面中的一个列表之后,接下来要给这个列表绑定 click 事件,如果是通过 ajax 动态往列表里追加数据,在使用事件代理的前提下, click 事件实际上只需要在第一次渲染列表的时候被绑定一次,

    var bindEvent = getSingle(function() {
        document.getElementById("div1").onclick = function() {
            alert("click");
        };
        return true;
    });
    var render = function() {
        console.log("开始渲染列表");
        bindEvent();
    };
    render();
    render();
    render();
    
    展开全文
  • JS 单例模式

    2017-12-14 02:22:08
    1. 单例模式 单例模式 (Singleton) 的实现在于保证一个特定类只有一个实例,第二次使用同一个类创建新对象的时候,应该得到与第一次创建对象完全相同的对象。当创建一个新对象时,实际上没有其他对象与其类似,因为...
        

    1. 单例模式

    单例模式 (Singleton) 的实现在于保证一个特定类只有一个实例,第二次使用同一个类创建新对象的时候,应该得到与第一次创建对象完全相同的对象。
    当创建一个新对象时,实际上没有其他对象与其类似,因为新对象已经是单例了 {a:1} === {a:1} // false

    但是如何在对构造函数使用 new 操作符创建多个对象的时候仅获取一个单例对象呢。

    2. 静态属性中的实例

    在构造函数的静态属性中缓存该实例,缺点在于 instance 属性是公开可访问的属性,在外部代码中可能会修改该属性。

    function Universe() {
        if (typeof Universe.instance === 'object') {        // 判断是否已经有单例了
            return Universe.instance
        }
        Universe.instance = this
        return this
    }
    var uni1 = new Universe()
    var uni2 = new Universe()
    uni1 === uni2            // true

    3. 闭包中的实例

    可以把实例封装在闭包中,这样可以保证该实例的私有性并且保证该实例不会在构造函数之外被修改,代价是带来了额外的闭包开销。

    function Universe() {
        var instance = this
        Universe = function() {    // 重写构造函数
            return instance
        }
    }
    var uni1 = new Universe()
    var uni2 = new Universe()
    uni1 === uni2         // true

    当第一次调用构造函数时,它正常返回 this ,然后在以后调用时,它将会执行重写构造函数,这个构造函数通过闭包访问了私有 instance 变量,并且简单的返回了该 instance

    4. 惰性单例

    有时候对于单例对象需要延迟创建,所以在单例中还存在一种延迟创建的形式,也有人称之为惰性创建

    const LazySingle = (function() {
      let _instance              // 单例的实例引用
     
      function Single() {        // 单例构造函数
        const desc = '单例'        // 私有属性和方法
        return {                   // 暴露出来的对象
          publicMethod: function() {console.log(desc)},
          publickProperty: '1.0'
        }
      }
      
      return function() {
        return _instance || (_instance = Single())
      }
    })()
    
    console.log(LazySingle()===lazySingle())        // true
    console.log(LazySingle().publickProperty)       // 1.0

    5. 改进

    之前在构造函数中重写自身会丢失所有在初始定义和重定义之间添加到其中的属性。在这种情况下,任何添加到 Universe() 的原型中的对象都不会存在指向由原始实现所创建实例的活动链接:

    function Universe() {
        var instance = this
        Universe = function() {
            return instance
        }
    }
    Universe.prototype.nothing = true
    var uni1 = new Universe()
    Universe.prototype.enthing = true
    var uni2 = new Universe()
    console.log(uni1 === uni2) // true
    
    uni1.nothing // true
    uni2.nothing // true
    uni1.enthing // undefined
    uni2.enthing // undefined
    uni1.constructor.name // "Universe"
    uni1.constructor === Universe // false

    之所以 uni1.constructor 不再与 Universe() 相同,是因为uni1.constructor仍然指向原始的构造函数,而不是重定义之后的那个构造函数。
    可以通过一些调整实现原型和构造函数指针按照预期的那样运行:

    function Universe() {
        var instance
        Universe = function Universe() {
            return instance
        }
        Universe.prototype = this // 保留原型属性
        instance = new Universe()
        instance.constructor = Universe // 重置构造函数指针
        instance.start_time = 0 // 一些属性
        instance.big = 'yeah'
        return instance
    }
    Universe.prototype.nothing = true
    var uni1 = new Universe()
    Universe.prototype.enthing = true
    var uni2 = new Universe()
    console.log(uni1 === uni2) // true
    
    uni1.nothing & uni2.nothing & uni1.enthing & uni2.enthing // true
    uni1.constructor.name // "Universe"
    uni1.constructor === Universe // true
    uni1.big    // "yeah"
    uni2.big    // "yeah"

    本文是系列文章,可以相互参考印证,共同进步~

    1. JS 抽象工厂模式
    2. JS 工厂模式
    3. JS 建造者模式
    4. JS 原型模式
    5. JS 单例模式
    6. JS 回调模式
    7. JS 外观模式
    8. JS 适配器模式
    9. JS 利用高阶函数实现函数缓存(备忘模式)
    10. JS 状态模式
    11. JS 桥接模式
    12. JS 观察者模式

    网上的帖子大多深浅不一,甚至有些前后矛盾,在下的文章都是学习过程中的总结,如果发现错误,欢迎留言指出~

    参考:
    《JavaScript模式》 P143
    《Javascript 设计模式》 - 张荣铭
    设计模式之单例模式
    展开全文
  • 什么是单例模式 定义:1.只有一个实例。...js单例模式优点:1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理首页页面缓存)。 2、避免对资源的多重占用(比如写文...

空空如也

空空如也

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

js单例模式