【ES6】使用Proxy实现单例模式

前言

由于JS没有private关键字,无法私有化构造器,所以下面代码无法限制:

javascript 复制代码
class Person {
  constructor() {
    console.log("Person created");
  }
}

const p1 = new Person();
const p2 = new Person();

console.log(p1 === p2); // false

实现

通过 Person.getInstance() 生成对象

javascript 复制代码
class Person {
  constructor() {
    console.log("Person created");
  }
  static _ins = null
  static getInstance() {
    if (!this._ins) {
      this._ins = new Person();
    }
    return this._ins;
  }
}

const p1 = Person.getInstance();
const p2 = Person.getInstance();

console.log(p1 === p2);

但是如果创建对象时使用new Person(),仍无法实现单例模式。

下面封装一个函数,把任何类传入,将其变为单例模式:

javascript 复制代码
function singleton(className) {
  let ins
  return class {
    constructor(...args) {
      if (!ins) {
        ins = new className(...args)
      }
      return ins
    }
  }
}
class Person {
  constructor() {
    console.log("Person created");
  }
}

// const p1 = new Person();
// const p2 = new Person();
const SingletonPerson = singleton(Person);
const p1 = new SingletonPerson();
const p2 = new SingletonPerson();

console.log(p1 === p2);

但是这种实现方式仍有缺陷,并不能添加原型方法

javascript 复制代码
const SingletonPerson = singleton(Person);
const p1 = new SingletonPerson();
const p2 = new SingletonPerson();
SingletonPerson.prototype.say = function () {
  console.log("hello world");
}
p1.say();

下面使用 Proxy 实现,不返回一个新类,而是代理,给代理对象的原型上加方法等于直接给该对象的原型加方法。

javascript 复制代码
function singleton(className) {
  let ins
  return new Proxy(className, {
    construct(target, args) {
      if (!ins) {
        ins = new target(...args);
      }
      return ins
    }
  })
}
class Person {
  constructor() {
    console.log("Person created");
  }
}
const SingletonPerson = singleton(Person);
const p1 = new SingletonPerson();
const p2 = new SingletonPerson();
SingletonPerson.prototype.say = function () {
  console.log("hello world");
}
p1.say();
console.log(p1 === p2);
相关推荐
CodeClimb2 小时前
【华为OD-E卷 - 第k个排列 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
光头程序员4 小时前
grid 布局react组件可以循数据自定义渲染某个数据 ,或插入某些数据在某个索引下
javascript·react.js·ecmascript
fmdpenny5 小时前
Vue3初学之商品的增,删,改功能
开发语言·javascript·vue.js
小美的打工日记5 小时前
ES6+新特性,var、let 和 const 的区别
前端·javascript·es6
涔溪5 小时前
有哪些常见的 Vue 错误?
前端·javascript·vue.js
程序猿online6 小时前
前端jquery 实现文本框输入出现自动补全提示功能
前端·javascript·jquery
Turtle8 小时前
SPA路由的实现原理
前端·javascript
HsuYang8 小时前
Vite源码学习(九)——DEV流程中的核心类(下)
前端·javascript·架构
小王子10248 小时前
设计模式Python版 单例模式
python·单例模式·设计模式
傻小胖8 小时前
React 中hooks之useInsertionEffect用法总结
前端·javascript·react.js