跳至主要內容

笔记

Mr.LRH大约 7 分钟

笔记

工具

  • nodemonopen in new window : 自动重启node应用的工具,当监听的文件或监听目录下的文件发生修改时,自动重启应用。
  • Parcel 打包支持浏览器允许 ts 文件 : npm install parcel-bundler --save-dev

单例设计模式

定义

一个类对外有且仅有一个实例【只提供一个实例】

  • 某个类对外始终只提供一个对象【实例】,并且在该类的内部提供了一个外部访问该对象的方法或该对象属性
  • 一个类的任何外部,通过访问类提供的某个方法或某个属性,始终只能获取该类一个对象【实例】

应用场景:实际开发中,外部访问某个类的对象【实例】时,确保只能访问该类的唯一对象时才能保证逻辑的正确性时

  • Vuex,React-Redux 中的全局状态管理容器 store 对象在整个项目被设计成唯一的对象【实例】,把 store 对象所在 的类设计成单例设计模式将是最好的设计方案
  • 前端项目需要进行客户端本地数据存储时,都会考虑使用 localStorage,localStorage只要在相同的协议、相同的主机名、相同的端口下,就能读取/修改到同一份 localStorage 数据
  • 项目日志记录是一个项目中必不可少的环节,当我们为一个项目编写一个日志文件类,用来保存日志和阅读日志信息时

示例:

export default class LocalStorage {
  static localstorage: LocalStorage;
  constructor() {}
  public static getInstance() {
    if (!this.localstorage) {
      this.localstorage = new LocalStorage();
    }
    return this.localstorage;
  }

  public setItem(key: string, value: any) {
    window.localStorage.setItem(key, JSON.stringify(value));
  }

  public getItem(key: string) {
    let value = window.localStorage.getItem(key);
    return value !== null ? JSON.parse(value) : null;
  }
}

TypeScript 类 - 静态属性/方法

  • 外部通过类名直接调用静态成员。格式:类名.静态属性类名.静态方法

  • 类中静态方法可以通过 this 获取静态成员

  • 类中静态方法不能访问到原型对象上的方法或对象属性。同时,类中原型对象上的方法或对象属性也不能访问类中的静态属性

  • 类中的对象不能访问静态成员

  • 一个静态方法改变了某个静态属性,其他静态方法或者类外部任何地方访问这个属性都会发生变化

  • 任何一个 TypeScript 类中的静态成员存储在内存的静态区。运行一个 TypeScript 类,TypeScript 优先为静态成员开辟内存空间,任何一个对象创建之前 TypeScript 就已经为静态成员分配好了空间。

    • 无论是否创建对象,创建多少个对象,是否调用该静态方法或静态属性,TypeScript 都会为这个静态方法或静态属性分配内存空间,注意:静态成员和对象无关
    • 一旦为静态方法或静态属性分配好空间,就一直保存到内存中,直到服务器重启或者控制台程序执行结束才被释放。
  • JavaScript 中 new 一个类(构造函数)内部定义的对象方法或静态方法,但 TypeScript 已屏蔽 new 一个类中的方法。TypeScript 类可以访问 prototype 原型对象属性,但无法在 prototype 原型对象属性增加新的方法或属性。只能在类的内部定义方法,防止回到 ES5 从前非面向类和对象的写法。

  • 原型对象空间上的方法和属性,用来提供给该类的所有对象变量共用的方法或属性,没有对象和对象变量,而静态方法或静态属性属于类,可以通过类来直接访问。任何一个对象创建之前 TypeScript 就已经为静态成员分配好了空间,但一个静态方法或静态属性只会分配一个空间,而每一个对象都有自己独立的空间。

  • 静态方法内部不能通过 this 来访问对象属性和方法,但可以通过调用静态方法时把对象变量传递给静态方法来使用。

    // 将 JavaScript 的 Object 构造函数看成一个 Obejct 类,创建 Object 类的对象
    let obj01 = new Object({ username: "lrh", age: 23 })
    let obj02 = { username: "wangwu", age: 23 }
    
    // 将 obj 对象变量赋值给 keys 静态方法,obj 对象变量作为 keys 静态方法测参数
    Object.keys(obj02)
    

何时将一个方法定义成静态方法或静态属性:

  • 单例设计模式。当外部不能创建对象,只能借助类内部的静态方法来获取类的对象。如果定义成原型对象属性的方法,就会导致外部无法被访问。只能定义这个方法为类的静态方法,因为外部根本不能创建对象,也就无法访问原型对象属性上的方法。

  • 当一个类中,某个方法没有任何必要使用任何对象属性时,而且使用了对象属性反而让这个方法的逻辑不正确,就应该禁止这个方法访问任何对象属性和其他的对象方法,这时可以把这个方法定义为静态方法。

    例如:一个顾客类的购买方法【 buy 方法】中,需要访问顾客姓名或其他顾客微信的对象属性,这样的方法就需要定义在原型对象属性上。但如果顾客类中的阅读顾客积分公告方法【 readNotice 方法】是针对全体顾客的公告方法,就应该定义为静态方法。

  • 当一个类中,某个方法只有一个或者 1-2个 对象属性,而创建这个类的对象毫无意义,只需要使用这个类的一个或者多方法就可以了,那么应该定义为静态方法。常见的工具类中的方法通常都应该定义为静态方法。比如 StringUtil, FileUtil 等。

    class FileUtil {
      // 从指定文件中,将数据读出来打印在控制台或页面上的静态方法
      public static readFile(readonly fileName: string) {
        fs.readFile(fileName, (err: any, data: any) => {
          console.log('fs.readFile:', data.toString());
        });
      }
      // 把键盘输入的数据或页面上获取的数据,写入到指定文件上的静态方法
      public static writeFile(fileName: string) {
        fs.writeFile(fileName, 'lrh', function (error) {
          if (error) {
            console.log('写文件失败');
          } else {
            console.log('写文件成功');
          }
        });
      }
    }
    FileUtil.readFile('./log.txt');
    FileUtil.writeFile('./log5.txt');
    

实现方式

  • 饿汉式单例设计模式:无论是否用到了对象【实例】,一开始就建立这个唯一的对象。实现步骤如下:

    • 构造器设置为私有的,不允许外部来创建类的实例【对象】
    • 建立一个静态引用属性,同时把这个静态引用属性直接指向一个对象 new MyLocalStorage()
    • 外部调用第二步提供的静态方法来获取一个对象
    class MyLocalStorage {
      // 对象属性【对象的基本类型属性和对象的引用属性】
      // 静态属性【静态的基本类型属性和静态的引用属性】
      static localstorage: MyLocalStorage = new MyLocalStorage();
      static count: number = 3;
      private constructor() {}
    
      public setItem(key: string, value: any) {
        window.localStorage.setItem(key, JSON.stringify(value));
      }
    
      public getItem(key: string) {
        let value = window.localStorage.getItem(key);
        return value != null ? JSON.parse(value) : null;
      }
    }
    
  • 懒汉式单例设计模式:等到需要使用对象时才创建对象,按需创建。实现步骤如下:

    • 构造器设置为私有的,不允许外部来创建类的实例【对象】
    • 至少应该提供一个外部访问的方法或属性,外部可以通过这个方法或属性来得到一个对象,将这个方法设置为静态方法
    • 外部调用第二步提供的静态方法来获取一个对象
    class MyLocalStorage {
      // 静态属性和对象属性[实例属性】是类中两大成员
      static localstorage: MyLocalStorage; // 引用静态属性
      private constructor() {}
      public static getInstance() {
        if (!this.localstorage) {
          this.localstorage = new MyLocalStorage();
        }
        return this.localstorage;
      }
    
      public setItem(key: string, value: any) {
        localStorage.setItem(key, JSON.stringify(value));
      }
    
      public getItem(key: string) {
        let value = localStorage.getItem(key);
        return value != null ? JSON.parse(value) : null;
      }
    }
    
上次编辑于:
贡献者: lingronghai