Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

js设计模式-单例模式 #26

Open
aermin opened this issue Feb 23, 2018 · 0 comments
Open

js设计模式-单例模式 #26

aermin opened this issue Feb 23, 2018 · 0 comments

Comments

@aermin
Copy link
Owner

aermin commented Feb 23, 2018

单例模式:

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

例子:单击登录按钮的时候,页面中会出现一个登录浮窗,而这个登录浮窗是唯一的,无论单击多少 次登录按钮,这个浮窗都只会被创建一次,那么这个登录浮窗就适合用单例模式来创建。

实现思路:用一个变量来标志当前是否已经为某个类创建 过对象,如果是,则在下一次获取该类的实例时,直接返回之前创建的对象。

image

以上是接近传统面向对象语言中的实现,单例对象从 “类”中创建而来。

JavaScript 其实是一门无类(class-free)语言,也正因为如此,生搬单例模式的概念并无 意义。在 JavaScript 中创建对象的方法非常简单,既然我们只需要一个“唯一”的对象。

js版本定义:保证一个全局对象仅有一个实例,提供给全局访问。

全局变量不是单例模式,但在 JavaScript 开发中,我们经常会把全局变量当成单例来使用。 例如:

var a = {};

当用这种方式创建对象 a 时,对象 a 确实是独一无二的。如果 a 变量被声明在全局作用域下, 则我们可以在代码中的任何位置使用这个变量,全局变量提供给全局访问是理所当然的。这样就 满足了单例模式的两个条件。

但是全局变量存在很多问题,它很容易造成命名空间污染。在大中型项目中,如果不加以限 制和管理,程序中可能存在很多这样的变量。JavaScript 中的变量也很容易被不小心覆盖,相信 每个 JavaScript 程序员都曾经历过变量冲突的痛苦,就像上面的对象 var a = {};,随时有可能被 别人覆盖。

以下几种方式可以相对降低全局变量带来的命名污染:

1.使用命名空间

适当地使用命名空间,并不会杜绝全局变量,但可以减少全局变量的数量。
最简单的方法依然是用对象字面量的方式:

var namespace1 = { 
    a: function(){ 
        alert (1); 
    }, 
    b: function(){ 
        alert (2); 
    } 
};

2.使用闭包封装私有变量
这种方法把一些变量封装在闭包的内部,只暴露一些接口跟外界通信:

var user = (function(){
    var __name = 'sven',
     __age = 29;
    return { getUserInfo: function(){ 
                    return __name + '-' + __age; 
                    } 
                }
})();

我们用下划线来约定私有变量__name 和__age,它们被封装在闭包产生的作用域中,外部是 访问不到这两个变量的,这就避免了对全局的命令污染。

  1. 单例模式的实际运用 (惰性单例,抽离单例管理)

code

//抽象出创建单例的方法
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'; 
};

内容整理自 《JavaScript设计模式与开发实践》

@aermin aermin changed the title js设计模式(外带全局变量污染解决方法) js设计模式-单例模式(外带全局变量污染解决方法) Feb 23, 2018
@aermin aermin removed the http label Feb 27, 2018
@aermin aermin changed the title js设计模式-单例模式(外带全局变量污染解决方法) js设计模式-单例模式 Jan 9, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant