javascript - 为什么我的单例模块似乎有两个实例?
问题描述
问题
我正在尝试创建一个 Singleton 来存储只能使用 Setter 和 Getter 访问的信息。我喜欢让我的代码尽可能简短和干净,所以我一直在寻找最短的编写方式。虽然这在大多数地方都有效,但在其他地方,我倾向于制造一些(对我来说)不太可解释的错误。
所以,.. 导入我的模块进行测试时,我使用:
const { ports, instance: activeConfig } = require('./activeConfig')
ports
应该是我的吸气剂。我想避免activeConfig.ports
在可能的情况下总是写出来。在我尝试重置我的值之前,我认为大部分情况下这在我的测试中是有效的。
我观察到的几件事:
- 当我运行时,
activeConfig.ports
我的吸气剂被激活。我可以在记录结果 1、2 和 3 之前看到这一点。 - 当我运行时,
ports
我的吸气剂没有被激活。我可以从日志结果 1a、2a 和 3a 中看到单例内部没有运行任何内容。但我仍然得到结果。 - 当我设置一个新值时,我可以在 Singleton 中看到我的值
_myPorts
确实发生了变化。这两种方法的结果也如我所料。
但是,在我重置我的值后,这种行为不再保持一致。虽然activeConfig.ports
提供了预期的结果,ports
但没有。我不确定日志 3a 从何处获得此结果以及为什么它与日志结果 3 不同。
我显然已经建立了某种不稳定因素,但我的 JavaScript 技能还不足以查明问题所在。我尝试搜索“JavaScript Singleton Getter Export”的所有变体,但似乎找不到涵盖我特定用例的示例。
如果有人可以帮助我修复我的代码,将不胜感激。此外,像正确的术语或高级示例的链接这样的小东西真的会很感激。:)
我的主要重点是能够在单个 require 命令中导入 getter!
我已经简化了这个例子,但我希望能够用 x 个吸气剂来做到这一点。
我不是在寻找解决方法,例如:
const activeConfig = require('./activeConfig')
const ports = activeConfig.ports
或者
const ports = require('./activeConfig').ports
这需要每个吸气剂一行,我试图避免这种确切的情况。(尤其是 10 多个吸气剂)
我真的很想知道是否有这样做的正确方法。:)
编码
'use strict'
let activeConfig = (function () {
const _defPorts = {
http: 80,
https: 443,
secure: false
}
let _myPorts = {..._defPorts}
let _setPorts = function (value) {
console.log('SP->', _myPorts)
if (value) {
Object.keys(value).forEach((key) => {
if (typeof _myPorts[key] !== 'undefined') {
_myPorts[key] = value[key]
}
})
}
console.log('SP=>', _myPorts)
}
let _resetConfig = function () {
console.log('RC->', _myPorts)
_myPorts = {..._defPorts}
console.log('RC=>', _myPorts)
}
return {
setPorts: _setPorts,
resetConfig: _resetConfig,
get instance() {
return activeConfig
},
get ports() {
console.log('GP->', _myPorts)
return _myPorts
},
set ports(value) {
return _setPorts(value)
}
}
})()
module.exports = activeConfig
测试代码
'use strict'
const {
ports,
instance: activeConfig
} = require('./activeConfig')
console.log('1 ->', activeConfig.ports)
console.log('1a->', ports)
activeConfig
.setPorts({
secure: true,
http: 8080
})
console.log('2 ->', activeConfig.ports)
console.log('2a->', ports)
console.log('RESET')
activeConfig.resetConfig()
console.log('3 ->', activeConfig.ports)
console.log('3a->', ports)
日志
GP-> { http: 80, https: 443, secure: false }
GP-> { http: 80, https: 443, secure: false }
1 -> { http: 80, https: 443, secure: false }
1a-> { http: 80, https: 443, secure: false }
SP-> { http: 80, https: 443, secure: false }
SP=> { http: 8080, https: 443, secure: true }
GP-> { http: 8080, https: 443, secure: true }
2 -> { http: 8080, https: 443, secure: true }
2a-> { http: 8080, https: 443, secure: true }
RESET
RC-> { http: 8080, https: 443, secure: true }
RC=> { http: 80, https: 443, secure: false }
GP-> { http: 80, https: 443, secure: false }
3 -> { http: 80, https: 443, secure: false }
3a-> { http: 8080, https: 443, secure: true }
解决方案
对象解构只是属性访问的语法糖:
const { port } = obj;
// equals
const port = obj.port;
因此,在您解构时,您确实可以访问 getter。更改port
会更改局部变量。它不会反映到对象上,因此不会触发 setter。
没有真正的方法以这种方式使用 getter / setter(好吧,让我们忘记吧with
)。
相反,您可以手动触发虚幻设置器:
const obj = {
port: { set(_v) { return this._v = _v; }, get() { return this._v; } }
};
const { port } = obj;
port.set(10);
推荐阅读
- php - PHP - 异步 foreach 循环
- python - TypeError: %d format: a number is required, not str 在创建端口监听时收到此错误
- javascript - 如何从作为输入传递给 Angular 组件的模板引用中获取元素引用
- react-native - 异步函数返回承诺而不是数组
- c++ - 使用 use_future 提升 Asio async_recieve_from 多播不能与 async_send_to 同时工作
- python-3.x - Discord.py 发送动态时间字符串
- javascript - 如何使我的 javascript 中的正弦波正常工作?
- javascript - 如果字符串的总长度大于指定值(for循环),则缩短数组 - JavaScript
- python - 在 Android 上部署 Kivy 时没有错误但加载屏幕后应用程序崩溃
- java - 为什么 public static void main 方法不会在实例化的类中自动运行?