单例模式的定义是:保证一个类仅有一个实例,并提供一个访问他的全局访问点。
    单例模式是一种常见的模式,有一些对象我们往往只需要一个,比如线程池,全局缓存,浏览器中的window对象….
    在 JavaScript 开发中,单例模式的用途同样的非常广泛。
    例如,当用户单击登录按钮时,页面中就会出现一个登录浮框,而这个登录浮框应该是唯一的,无论单击多少次登录按钮,这个浮框都只会被创建一次。此时的这个场景就适合使用单例模式来创建。
    要实现一个标准的单例模式,并不复杂,无非就是用一个变量来标志当前是否已经为某个类创建过对象,如果是,则在下一次获取该类的实例时,直接返回之前创建的对象。

    示例代码如下:

    1. // 返回能够创建单例的构造函数
    2. function getSingle(fn) {
    3. var instance = null;
    4. // 返回一个新的构造函数
    5. return function () {
    6. if (instance !== null) {
    7. // 如果已经存在实例对象,直接返回该实例对象
    8. return instance;
    9. }
    10. // 没有进入上面的 if,说明是第一次实例化对象
    11. // arguments 是调用这个新的构造函数所传入的参数 { '0': '张三', '1': 18 }
    12. // 方式一:
    13. // instance = new fn(...arguments);
    14. // return instance;
    15. // 思考:上面的 return instance 不写会怎么样?
    16. // 答案:会输出 undefined 张三 false
    17. // 原因:当外界 new 这个 function 的时候,会产生一个 {}(假设这个名字叫 A),然后隐式的返回这个对象 A
    18. // 然而你的这个 A 对象啥都没有,所以外界访问 p1.name 的时候,拿到的是 undefined
    19. // 而第二次之所以有值,是因为返回的是 instance,instance 的值存储的是 new fn(...arguments) 返回的对象
    20. // 方式二:this 是 new 这个 function 的时候会产生的一个对象,默认为空
    21. fn.apply(this, arguments);
    22. instance = this; // 将创建出来的实例对象赋值给 instance,下一次直接进入 if 然后 return
    23. // return this; // 隐式调用语句
    24. // return { name: 'xiejie' }; // 如果显式的返回一个对象,那么外界拿到的值是这个对象
    25. // 思考:书写 return { name: 'xiejie' } 后,外面依次打印出什么?
    26. // 答案:xiejie 张三 false 张三 false true
    27. // 原因:第一次 new 这个 function 的时候,instance 没有值,new 会生成一个空的 {}(假设这个名字叫 A)
    28. // fn.apply(this, arguments) 会执行 Person 里面的每一条语句,只不过 this 指向的是 A
    29. // 接下来将 A 这个对象赋值给 instance,然后本来该隐式返回 A 这个对象的,结果你显式返回了一个 {name: 'xiejie'}
    30. // 所以第一次 var p1 = new singlePerson('张三', 18) 拿到的是 {name: 'xiejie'} 这个对象
    31. // 然后第二次以及第三次 new singlePerson 的时候,因为 instance 里面有值了,所以直接返回 instance 存储的值
    32. // instance 存储的是 {name : '张三'}
    33. }
    34. }
    35. // 人类构造函数
    36. var Person = function (name, age) {
    37. this.name = name;
    38. this.age = age;
    39. }
    40. // 获取新的构造函数
    41. var singlePerson = new getSingle(Person);
    42. // 测试
    43. var p1 = new singlePerson('张三', 18);
    44. console.log(p1.name); // 张三
    45. var p2 = new singlePerson('李四', 20);
    46. console.log(p2.name); // 张三
    47. console.log(p1 === p2); // true
    48. // 书写了 return { name: 'xiejie' } 后进行测试
    49. // var p3 = new singlePerson('王五', 22);
    50. // console.log(p3.name); // 张三
    51. // console.log(p1 === p3); // false
    52. // console.log(p2 === p3); // true

    我们来测试一下
    image.png
    image.png
    我们可以看到我们单列模式创建成功了,此时这个singlePerson类我们只能创建一个,再次创建的话还是指向第一个实例创建的。

    —————————————-其实在学到这里的,有一些不懂的地方搞懂了
    比如apply是改变this执行的,第一个参数是this的指向,第二个参数是类数组或者数组
    apply后面那个this在没有实例化之前执行win,实例化了之后指向实例化的对象