了解 JS 中静态属性的范围
Understanding the scope of static properties in JS
首先介绍一下我的情况...我有一个库,其中包含一些适用于我的应用程序的模型等,然后是一个电子应用程序,它添加了一些 UI,电子应用程序也会加载允许添加额外逻辑的自定义 JS 文件。
在我的工作区模型上,我使用单例模式(我知道,我知道)来存储工作区的实例。当应用程序启动时,它正在加载工作区,然后调用 document.head.appendChild 来加载我的自定义脚本。
在自定义脚本中,我需要相同的模型库来获取我的工作区 class。但是,Workspace.instance 返回 null,尽管它之前肯定不是 null。
相比之下,如果在加载脚本之前我执行 global.workspace = workspace,则脚本可以正常访问实例。所以谁能告诉我这是怎么回事?据我了解,静态属性和方法本质上具有全局范围,尽管这似乎表明并非如此。
在我的图书馆中:
export default class Workspace {
static instance: Workspace = null;
startupData: any;
constructor(startupData: any) {
this.startupData = startupData;
Workspace.instance = this;
}
}
在我的应用程序中:
import Workspace from 'mymodels';
const workspace = new Workspace(startupData);
global.workspace = workspace;
console.log(Workspace.instance); //Returns my workspace instance
const script = document.createElement('script');
script.onload = showUI;
script.src = 'file:///' + workspace.startupData.logic;
document.head.appendChild(script);
在我的自定义脚本中:
const mymodels = require('mymodels');
console.log(mymodels.Workspace.instance); //Returns null
console.log(global.workspace); //Returns my workspace instance
When the app starts up, it's loading the workspace, then calls document.head.appendChild to load my custom script.
如果使用本机模块就好了,但我怀疑您正在使用某种捆绑器(Webpack 等)。我怀疑您最终加载了两个不同的模块副本:一个作为初始应用程序包的一部分,另一个由浏览器的模块处理本地加载。由于这些是独立的模块(就浏览器而言),您最终会得到 Workspace
的两个副本,因此 instance
属性.
的两个副本
根据捆绑器的不同,通常会有一种方法告诉它处理这个问题,但细节因捆绑器而异。
But,回答范围问题:像你的 instance
这样的 public static 属性 可以在任何包含 class(构造函数)可以访问,因为它是该函数对象的 属性。
如果“作用域”指的是“生命周期”,那么静态 属性 在 class(构造函数)创建时创建,并在 class(构造函数)创建后释放功能)被释放(或通过 delete
从中删除 属性)。
请注意,您的 Workspace
class 不是单身人士。每次执行 new Workspace
时,都会创建一个新实例(并覆盖 Workspace.instance
中的先前值。要使其成为单例,您需要向构造函数添加检查:
constructor(startupData: any) {
if (Workspace.instance) {
return Workspace.instance; // Return the singleton
}
this.startupData = startupData;
Workspace.instance = this;
}
或者更好的是,通过简单地直接导出一个对象,使您的单例更加地道(从 JavaScript 的角度来看):
export default const workspace = {
// ...properties and methods...
};
或者如果您需要 class
私有字段等功能:
export default const workspace = new class Workspace {
// ...constructor (if desired), properties, and methods...
}();
首先介绍一下我的情况...我有一个库,其中包含一些适用于我的应用程序的模型等,然后是一个电子应用程序,它添加了一些 UI,电子应用程序也会加载允许添加额外逻辑的自定义 JS 文件。
在我的工作区模型上,我使用单例模式(我知道,我知道)来存储工作区的实例。当应用程序启动时,它正在加载工作区,然后调用 document.head.appendChild 来加载我的自定义脚本。
在自定义脚本中,我需要相同的模型库来获取我的工作区 class。但是,Workspace.instance 返回 null,尽管它之前肯定不是 null。
相比之下,如果在加载脚本之前我执行 global.workspace = workspace,则脚本可以正常访问实例。所以谁能告诉我这是怎么回事?据我了解,静态属性和方法本质上具有全局范围,尽管这似乎表明并非如此。
在我的图书馆中:
export default class Workspace {
static instance: Workspace = null;
startupData: any;
constructor(startupData: any) {
this.startupData = startupData;
Workspace.instance = this;
}
}
在我的应用程序中:
import Workspace from 'mymodels';
const workspace = new Workspace(startupData);
global.workspace = workspace;
console.log(Workspace.instance); //Returns my workspace instance
const script = document.createElement('script');
script.onload = showUI;
script.src = 'file:///' + workspace.startupData.logic;
document.head.appendChild(script);
在我的自定义脚本中:
const mymodels = require('mymodels');
console.log(mymodels.Workspace.instance); //Returns null
console.log(global.workspace); //Returns my workspace instance
When the app starts up, it's loading the workspace, then calls document.head.appendChild to load my custom script.
如果使用本机模块就好了,但我怀疑您正在使用某种捆绑器(Webpack 等)。我怀疑您最终加载了两个不同的模块副本:一个作为初始应用程序包的一部分,另一个由浏览器的模块处理本地加载。由于这些是独立的模块(就浏览器而言),您最终会得到 Workspace
的两个副本,因此 instance
属性.
根据捆绑器的不同,通常会有一种方法告诉它处理这个问题,但细节因捆绑器而异。
But,回答范围问题:像你的 instance
这样的 public static 属性 可以在任何包含 class(构造函数)可以访问,因为它是该函数对象的 属性。
如果“作用域”指的是“生命周期”,那么静态 属性 在 class(构造函数)创建时创建,并在 class(构造函数)创建后释放功能)被释放(或通过 delete
从中删除 属性)。
请注意,您的 Workspace
class 不是单身人士。每次执行 new Workspace
时,都会创建一个新实例(并覆盖 Workspace.instance
中的先前值。要使其成为单例,您需要向构造函数添加检查:
constructor(startupData: any) {
if (Workspace.instance) {
return Workspace.instance; // Return the singleton
}
this.startupData = startupData;
Workspace.instance = this;
}
或者更好的是,通过简单地直接导出一个对象,使您的单例更加地道(从 JavaScript 的角度来看):
export default const workspace = {
// ...properties and methods...
};
或者如果您需要 class
私有字段等功能:
export default const workspace = new class Workspace {
// ...constructor (if desired), properties, and methods...
}();