【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);
相关推荐
浪裡遊3 小时前
Nivo图表库全面指南:配置与用法详解
前端·javascript·react.js·node.js·php
課代表3 小时前
JavaScript 二维数组的三种定义与初始化方法
javascript·初始化·二维数组·多维数组·动态数组·循环遍历·数组合并
鸡吃丸子3 小时前
Next.js 入门指南
开发语言·javascript·next.js
罚时大师月色4 小时前
Vue+ts 如何实现父组件和子组件通信
javascript·vue.js·ecmascript
漂流瓶jz4 小时前
快速定位源码问题:SourceMap的生成/使用/文件格式与历史
前端·javascript·前端工程化
fury_1234 小时前
vue3:数组的.includes方法怎么使用
前端·javascript·vue.js
宁&沉沦4 小时前
Cursor 科技感的登录页面提示词
前端·javascript·vue.js
Dragonir5 小时前
React+Three.js 实现 Apple 2025 热成像 logo
前端·javascript·html·three.js·页面特效
古一|5 小时前
Vue3中ref与reactive实战指南:使用场景与代码示例
开发语言·javascript·ecmascript
peachSoda76 小时前
封装一个不同跳转方式的通用方法(跳转外部链接,跳转其他小程序,跳转半屏小程序)
前端·javascript·微信小程序·小程序