我上了这个班,打算以单身人士的身份工作,

export class SingletonClass {

    public static instance: SingletonClass | undefined;
    public name: string | undefined | null;

    static getInstance() {
        if (SingletonClass.instance == null || SingletonClass.instance == undefined)
            SingletonClass.instance = new SingletonClass();

        return SingletonClass.instance;
    }

    static destroy() {
        SingletonClass.instance = undefined;
    }
}

一个组件类有这样的代码,

  export class TestComponent implements OnInit {

    SingletonObject1: SingletonClass | undefined | null = SingletonClass.getInstance();
    SingletonObject2: SingletonClass | undefined | null;

    ngOnInit(): void {

      this.SingletonObject1!.name = "Name1";
      SingletonClass.destroy();

      this.SingletonObject2 = SingletonClass.getInstance();
      this.SingletonObject2.name = "Name2";
    }
  }

我希望SingletonObject1SingletonObject2都引用同一个单例对象,因此在运行这段代码后,两个对象的name属性的值都应该是"Name2".但是这里发生的是SingletonObject1.name有"Name1",SingletonObject2.name有"Name2"作为它们的值.

如果我删除SingletonClass.destroy();它会像预期的那样工作.因此,即使在调用SingletonClass.instance = undefined;之后,SingletonObject1也会保留对先前创建的对象的引用.

有人能解释一下为什么当它将instance设置为undefined时会创建两个变量实例,以及如何修改destroy方法以删除整个单例对象并保持两个变量对同一位置的引用.

推荐答案

这并不是静态类、单例或Angular 类所特有的.将引用设置为undefined不会删除/销毁/释放底层对象实例,而只是清除对它的引用.包含对该对象的引用的任何其他变量仍将看到原始对象:

// Create the first instance.
let obj = { foo: 'bar' };

// Capture a reference to the first instance.
const a = obj;

// Forget the reference to the first instance.
// NOTE: this does not destroy the first instance,
// it just removes obj's reference to the first
// instance.
obj = undefined;

// Create the second instance.
obj = { foo: 'baz' };

// Capture a reference to the second instance.
const b = obj;

// Log the instances (Prints 'bar' and 'baz' respectively). 
console.log(a.foo);
console.log(b.foo);

为什么你不打destroy()就能用?因为这两个引用仍然指向同一个实例:

// Create the first instance.
let obj = { foo: 'bar' };

// Capture a reference to the first instance.
const a = obj;

// Update a property on the first instance.
obj.foo = 'baz';

// Capture a second reference to the first instance.
const b = obj;

// Log the instances (Prints 'bar' and 'baz' respectively). 
console.log(a.foo);
console.log(b.foo);

那么,你如何获得你想要的行为呢?销毁实例后,请确保重新分配引用:

class SingletonClass {

    static #instance;
    name;
    
    static getInstance() {
        if (SingletonClass.#instance == undefined)
            SingletonClass.#instance = new SingletonClass();
        
        return SingletonClass.#instance;
    }

    static destroy() {
        SingletonClass.#instance = undefined;
    }
}

// This has to be 'let' now since we're going
// to be reassigning our reference to point to the
// new instance.
let a = SingletonClass.getInstance();
a.name = 'Foo';

SingletonClass.destroy();

// We know we've destroyed the first instance so we
// should update our stored references to point to
// the new instance instead.
a = SingletonClass.getInstance();

const b = SingletonClass.getInstance();
b.name = 'Bar';

console.log(a.name);
console.log(b.name);

或者让变量具有对实例的动态引用.这确实意味着您在每次try 访问实例时都有函数调用,但您始终可以保证获得最新的实例:

class SingletonClass {

    static #instance;
    name;
    
    static getInstance() {
        if (SingletonClass.#instance == undefined)
            SingletonClass.#instance = new SingletonClass();
        
        return SingletonClass.#instance;
    }

    static destroy() {
        SingletonClass.#instance = undefined;
    }
}

const a = () => SingletonClass.getInstance();
a().name = 'Foo';

SingletonClass.destroy();

const b = () => SingletonClass.getInstance();
b().name = 'Bar';

console.log(a().name);
console.log(b().name);

Javascript相关问答推荐

容器如何更改默认插槽中子项的显示?

Next.js Next/Image图像隐含性有任何类型-如何修复?

如何修复内容安全策略指令脚本-SRC自身错误?

从PWA中的内部存储读取文件

传递一个大对象以在Express布局中呈现

为什么这个JS模块在TypeScript中使用默认属性导入?""

如何从URL获取令牌?

你怎么看啦啦队的回应?

正则表达式,允许我匹配除已定义的子字符串之外的所有内容

在Matter.js中添加从点A到另一个约束的约束

有效路径同时显示有效路径组件和不存在的路径组件

使用Document.Evaluate() Select 一个包含撇号的HTML元素

将相关数据组合到两个不同的数组中

在渲染turbo流之后滚动到元素

如何压缩图像并将其编码为文本?

如何在加载页面时使锚定标记成为焦点

在使用JavaScript以HTML格式显示Google Drive中的图像时遇到问题

不允许在对象文本中注释掉的属性

MUI-TABLE:MUI表组件中交替行的不同 colored颜色 不起作用

在ReactJS上挂载组件时获得多个身份验证请求