Javascript 如何防止克隆单例对象?

Javascript 如何防止克隆单例对象?,javascript,singleton,clone,Javascript,Singleton,Clone,我以以下方式实现了Singleton模式: class Singleton { static #instance_holder = []; constructor() { if (0 !== Singleton.#instance_holder.length) return Singleton.#instance_holder[0]; Singleton.#instance_holder.push(this); Object.preventExtensions(t

我以以下方式实现了Singleton模式:

class Singleton {
  static #instance_holder = [];
  constructor() {
    if (0 !== Singleton.#instance_holder.length) return Singleton.#instance_holder[0];
    Singleton.#instance_holder.push(this);
    Object.preventExtensions(this);
    console.log("You'll see me only once, when the object is first instantiated.");
  }
}
就定期申报/分配而言,这似乎很有效:

const s1 = new Singleton();
//OUTPUT: You'll see me only once, when the object is first instantiated.

const s2 = new Singleton(); //no additional instantiation, the existing one is assigned to s2

s1 instanceof Singleton //true
s2 instanceof Singleton //true
s1 === s2 //true
但是,仍然可以使用
Object.create
Object.assign
JSON.parse(JSON.stringify(s1))
克隆实例(
s1


如何防止对象以这些方式被克隆?

基本上,您不能。没有JS机制可以阻止克隆

如果某件事是单身是非常重要的,那么你真正关心的可能就是那门课上的某件事。在这种情况下,最好将它放在全局范围内,并让类引用它

const data = {};

class Singleton {
  // singleton setup

  doSomething() {
    return data.something();
  }
}
这将确保即使克隆了singleton,只要它使用相同的数据源,它仍然像singleton一样工作


也就是说。。。我真的不建议这样做。我真的想不出哪种情况下你真的需要强制执行一个真正的单身汉。如果有人对他们的代码做了傻事,那就是他们的问题。

基本上,你不能。没有JS机制可以阻止克隆

如果某件事是单身是非常重要的,那么你真正关心的可能就是那门课上的某件事。在这种情况下,最好将它放在全局范围内,并让类引用它

const data = {};

class Singleton {
  // singleton setup

  doSomething() {
    return data.something();
  }
}
这将确保即使克隆了singleton,只要它使用相同的数据源,它仍然像singleton一样工作


也就是说。。。我真的不建议这样做。我真的想不出哪种情况下你真的需要强制执行一个真正的单身汉。如果有人对他们的代码做了傻事,那就是他们的问题。

为什么克隆会有问题?因为这样会有两个单例实例,有效地将其转化为双例!你想阻止谁?让糟糕的开发人员搞乱他们自己的代码,而不是你的问题。好吧,这真的不可能做到。即使在Java或C中,也可以使用反射来绕过单例。针对多个实例进行保护没有多大意义,因为它们最终会带来不便,而不是问题。如果编写代码的人想给他们带来不便,甚至想花费额外的精力来给他们带来不便,那就让他们去做吧。而且,单例的实现是一种过分的手段。只需使用一个模块并导出一个实例或工厂(如果您想要一个池的话)。那么就不需要编写代码来阻止
new
工作。为什么克隆会有问题?因为这样会有两个单例实例,有效地将其转化为双例!你想阻止谁?让糟糕的开发人员搞乱他们自己的代码,而不是你的问题。好吧,这真的不可能做到。即使在Java或C中,也可以使用反射来绕过单例。针对多个实例进行保护没有多大意义,因为它们最终会带来不便,而不是问题。如果编写代码的人想给他们带来不便,甚至想花费额外的精力来给他们带来不便,那就让他们去做吧。而且,单例的实现是一种过分的手段。只需使用一个模块并导出一个实例或工厂(如果您想要一个池的话)。这样就不需要编写代码来阻止
new
工作。