公司项目中使用到了单例模式,于是撰文一篇。
单例模是Gof提出的一个简单的设计模式。

在前端项目中用到单例模式,给整个前端工程带来的优势是节省了浏览器的CPU的使用,在占用内存方面未必占有优势
从算法的角度看来,算是以空间换时间的一个经典的例子。

常见的地方一般使用在,前端创建需要大量重复使用的一段具有类似功能DOM的时候。
例如微博中的转发的弹框。

让我们先来看看创建了这么一个转发弹框的基本流程。
a). 构建HTML
b). 拼装模板(插入一些动态数据)
c). 绑定自定义事件
d). 插入文档流
顺序可以改变。

这些流程的操作是需要消耗系统的CPU资源的。
让我们考虑在这个弹框足够复杂的情况下。
如果你使用的是chrome神器,自然不会感觉到速度上的差异。但是如果你使用的是IE6之流的老古董,会体验到明显的感觉到差异。
作为一个苦逼的前端,如果你开发的是像google,taobao那样的产品,那么恭喜你。你可以横着脑袋,翘着二郎腿对用户说“赶紧给老子去升级你的浏览器,否则滚蛋!”。
不过我相信98%的前端同学面临的选择题都是:要么用户留下,要么你滚蛋。
那你会选哪个捏?

开个玩笑,言归正传。
实现前端开发中的单例模式的方式有很多种,但是总体来说都是有着类似的思路。
即,在页面上执行一次需要的逻辑(例如上边所说的a, b, c步骤),将执行的结果进行缓存在一个闭包的变量中(防止污染全局变量)。而后,每次的调用只需要执行d步骤就可以了,如果有额外的逻辑,可能还要在d步骤之后或者之前再加上个b步骤(如果每次的展示界面略有差异的话)。

巴巴儿地扯了半天,就像我们浏览某榴网站一样,有些同学可能要抱怨了 —— “没代码你说个j8!“
于是,借花献佛的引用了在腾讯AlloyTeam【Javascript设计模式1】-单例模式中的代码。

var singleton = function( fn ){
  var result;
  return function(){
    return result || ( result = fn .apply( this, arguments ) );
  }
}

这是采用了高阶函数的方式来实现单例模式。
按照这篇文章原作者的思路(可理解为伪代码),调用的方式为。

var createMask = singleton( function(){
  return document.body.appendChild( document.createElement('div') );
})

按照我们所讲的a, b, c, d的四四中执行方式来讲,d步骤和b步骤进行了合并。这种方式并不是太好。
私下认为可以把调用方式改为如下,可能会更加形象。

var getMask = singleton(function() {

  // 执行a, b, c步骤。
  var mask = document.createElement('div');
  console.log('A div has created for once !');
  return mask;
});

var blankMask = getMask();
document.body.appendChild(blankMask);

window.setTimeout(function() {
  blankMask.parentNode.removeChild(blankMask);

  window.setTimeout(function() {
    document.body.appendChild(getMask());
  }, 1000);
}, 1000);

结语:
而前端环境的局限性在于变量的生存周期再一次页面的重新加载中。
而不像后台语言中能做到的那样,一次创建,随意使用。
使用单例模式,能使得代码更易于维护,再者算是满足了程序猿们的小小精神洁癖吧,哈哈,何乐而不为呢?

Enjoy it !
转载请注明出处
botobe.net
本文Github链接

2013.11.06
一切安好。
Merci !