1.单例模式

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

1.作者举了最简单的两个例子:

//首先在这里定义了一个构造函数,singleton的意思是单身汉。

  var Singleton  = function (name) {
    this.name = name;
    this.instance = null;
    //instance的意思是例子
  };

  Singleton.prototype.getName = function () {
    alert(this.name);
  };

//下面要注意,getInstance方法是直接写在Singleton身上的。

//而且,函数里面的this也是指向Singleton的。

//我读到这里的时候会下意识的这样想:不都是说构造函数中的this是指向实例的么?

//其实是这样的,大家常说的构造函数的this指向实例,是因为new的关系。

//new的内部实现,把构造函数apply给了实例,所以才会改变this的指向。

//所以下面的代码this.instance是可以取到的。

  Singleton.getInstance = function (name) {
    if (!this.instance) {
      this.instance = new Singleton(name)
    }
    return this.instance;
  }

  var a = Singleton.getInstance('cyw');
  var b = Singleton.getInstance('mn');

  /* 在这里,我们来看一下,这会产生什么效果? */
  console.log(a === b); // true
  a.getName();//'cyw'
  b.getName();//'cyw'

  /*
 我们发现,不管getInstance方法执行了几次,他都只是返回第一次构造的实例。
这是因为,this.instance充当了一个标记的角色。
它在第一次执行之后,就永远的被改写成了实例。
以后再怎么调用,都只是返回那个实例。
 */

再来看下一个例子,和第一个很像。

 var Singleton = function (name) {
    this.name = name;
  };

  Singleton.prototype.getName = function () {
    alert(this.name);
  };

  Singleton.getInstance = (function () {
    var instance = null;
    return function (name) {
      if (!instance) {
        instance = new Singleton(name);
      }
      return instance;
    }
  })();
  var a = Singleton.getInstance('cyw');
  var b = Singleton.getInstance('mn');
  console.log(a === b);// true
  /*
   * 这里的实现方式略有不用
    * 在第三个函数直接使用了一个立即执行函数进行包裹
    * 所以拿到的是里面那个匿名函数
    * 匿名函数又使用了立即执行函数里面的变量instance:这个就是一个闭包
  */
  • 读到这里我们学会了,判断 + 改写 + return可以实现这种效果。
  • 但是作者又说这种实现方式很不好
  • 这个构造函数的'透明性'差


    b8389b504fc2d5624fce51daef1190ef77c66cc7.jpg
  • 还要使用Singleton.getInstance方法才能获得实例。
新目标1:改写这个函数,要求直接使用构造函数就能获得单例
写一个在页面创建一个唯一的DIV的例子。 

var CreateDiv  =(function () {
   var instance;

   var CreateDiv = function (html) {
     if (instance) {
       return instance;
     }
     this.html = html;
     this.init();
     return instance = this;//这句话就是intance = this;return instance;
   };

   CreateDiv.prototype.init  = function () {
     var div = document.createElement('div');
     div.innerHTML = this.html;
     document.body.appendChild(div);
   };
   return CreateDiv;
 })();

  var a = new CreateDiv('hello');
  var b = new CreateDiv('world');
  console.log(a === b);
/*
 * 读这段代码,我们可以发现 ,就是把本来外面的方法,拿到构造函数里面了。
  * 还是利用的立即执行函数
  * 外面的函数名和里面的函数名字一样可能会带来理解上的误区,你当然可以把里面的换一个名字
  * 真正的构造函数写在里面 ,外面的构造函数拿到的是里面的构造函数的引用
  * 让 instance = this; 因为this就是实例 */
  • 读到这里,作者又觉得这个方法的实现有问题
  var CreateDiv = function (html) {
     if (instance) {
       return instance;
     }
     this.html = html;
     this.init();
     return instance = this;//这句话就是intance = this;return instance;
   };
这个函数同时做了两件事情:

1.创建对象和初始化init方法(我们可以注意到定义在原型上的init方法,是在构造函数中被调用的。)
2.确保了只有一个实例。

这违反了"单一职责原则",不方便复用,而且看起来很怪。
ps.注意大牛的思考方式,这是最重要的。

我们使用代理类的方式来解决这种情况:
  var CreateDiv = function (html) {
    this.html = html;
  };
  CreateDiv.prototype.init = function () {
    var div = document.createElement('div');
    div.innerHTML = this.html;
    document.body.appendChild(div);
  }
// 首先这就是一个普通的类,他是实现的是职责就是创建div
//现在我们来引入代理类,来实现单例模式

  var ProxySingletonCreateDiv = (function () {
    var instance;
    return function (html) {
      if (!instance) {
        return new CreateDiv(html);
      }
      return instance;
    }
  })()

 var a = new ProxySingletonCreateDiv('hello');
  var b = new ProxySingletonCreateDiv('world');
  console.log(a === b);//true

// 这几句代码写来写去,好像都在哪见过,但是从新的组合和设计确实实现了作者口中的优化。

javascript中的单例模式

在javascript中我们并不需要如此的依赖类的概念
其实
var a = {};
就是一个单例模式的例子。
首先它是独一无二的。
其次他还是全局可以访问的。
但是a这个引用太危险了,他随时可能在编程的过程中被改写。
  • 为了避免这种情况,我们可以使用下面两种小技巧。
1.命名空间
  var namespace = {
    a: function () {
      console.log(1);
    },
    b: function () {
      console.log(2);
    }
  }
我们把a和b写成对象的属性,这样就使其远离了全局作用域。

好玩的东西: 动态创建命名空间
 var MyApp = {};
  MyApp.namespace = function (name) {
    var current = MyApp;
    var parts = name.split('.');
    for (var i in parts) {
      if (!current[parts[i]]) {
        current[parts[i]] = {}
      }
      current = current[parts[i]];
    }
  };
  MyApp.namespace('one');
  MyApp.namespace('two.three.four');  
  MyApp.namespace('two.three.five'); 

  相当于:
  var MyApp = {
    one: {},
    two: {
      three: {
        four: {},
        five: {}
      }
    }
  }
2.使用闭包封装私有变量
var user = (function () {
  var _name = 'cyw';
  var _age = '25';
  return {
      getUserInfo: function () {
        return _age + '-' + _name;
      }
    }
})()
下划线'_'是私有变量的常用命名规则。

惰性单例

惰性的意思就是,需要的时候才创建实例

以创建登录窗口为例
我们把单例模式不变的逻辑单独提取出来
var getSingle = function (fn) {
  var result;
  return function () {
    return result || (result = fn.apply(this, arguments));
  }
}

//再写一个简单不过的创建div的方法。
var createLoginLayer = function () {
  var div = document.createElement('div');
  div.innerHTML = '我是登录窗口';
  div.style.display = 'none';
  document.body.appendChild(div);
  return div;
}

/* 两个方法都是单一职能,结合起来就形成了惰性单例模式 */
var createSingleLoginLayer = getSingle(createLoginLayer);
var div = createSingleLoginLayer();
  • 希望这个读书笔记可以坚持下来。
  • 写第一篇就有一种感受,现在的mvvm框架功能太强太。
  • 如果用框架来写,文中的好多技巧都无处发挥了。
  • 一个vue的v-if还用什么单例模式(也可能是我现在认识比较浅薄)
  • 虽然能看的懂代码,但我希望更能学会大牛的思考方式,希望能得到进步
  • 还要继续找工作,初级前端的工作太难找了。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容