【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);
相关推荐
大家的林语冰1 小时前
👍 尤大重学 Webpack,Vite 8.1 再进化,打包模式复活!
前端·javascript·vite
张元清1 小时前
React useIsomorphicLayoutEffect:修掉 SSR 下的 useLayoutEffect 警告(2026)
前端·javascript·面试
PBitW2 小时前
直接让GPT每日训练我!!!😕😕😕
前端·javascript·面试
拾年2753 小时前
我用 30 行代码,搞懂了大模型是怎么"读"中文的
javascript·人工智能·llm
竹林8183 小时前
从 ethers.js 到 viem:我在一个 DeFi 看板项目中踩过的所有坑与最终方案
前端·javascript
bonechips3 小时前
Tool Use:从"缸中大脑"到 AI Agent 的技术真相
javascript·agent
秋天的一阵风4 小时前
Vue 3 里被严重低估的 API:InjectionKey
前端·javascript·vue.js
kisshyshy4 小时前
从递归到迭代,一文吃透二叉树的核心知识与 JavaScript 实现
javascript·算法·代码规范
铁皮饭盒4 小时前
Bun 多线程有多快?postMessage 传输字符串比 Node.js 快 400 倍!
前端·javascript·后端
To_OC15 小时前
LC 49 字母异位词分组:想到哈希表很简单,选对 key 才是精髓
javascript·算法·leetcode