在 weakmaps 中设置新值时我们会改变状态吗?
Do we change states when setting new values in weakmaps?
假设我们有以下代码:
const _timeStamp = new WeakMap();
const _running = new WeakMap();
export class Stopwatch {
constructor() {
_timeStamp.set(this, 0);
_running.set(this, false);
}
start() {
// start stopwatch
_running.set(this, true)
_timeStamp.set(this, Date.now())
}
stop() {
// stop stopwatch
_running.set(this, false);
return (Date.now() - _timeStamp.get(this))/1000
}
}
在这个例子中,我们试图使用 weakmaps 向最终用户隐藏一些信息。
根据调用的方法,我们更改两个 weakmaps 中的值。
当我们重新分配变量时,我们改变了状态。
let x = 0;
x = 10
编辑:
作为最佳实践,我们不应该在 JS 中改变对象或改变状态
但是,我们在更新 weakmaps 中的值时不会像在变量的情况下那样改变状态吗? 'best practice' 使用需要可重写的私有 props 是什么?
非常感谢任何澄清!
为了回答您关于 WeakMaps 的问题,我认为您是在谈论副作用。使用 WeakMap 时,您可以想象设置值不会对用户空间产生副作用,因为 WeakMap 颠倒了项目和集合之间的通常关系。在 WeakMap 中,出于垃圾回收的原因,项目维护一个隐藏的 link 到集合(而不是集合维护对项目的引用),所以我们可以假装没有副作用。
但是,这个问题也与 JavaScript 中的隐私有关。
碰巧,JavaScript 一直提供一种出色的(据我所知是难以理解的——与 C# 等语言中的私有字段不同)强大的隐私机制:闭包。只是大多数开发人员来自基于 class 的面向对象背景,并花时间学习 "JavaScript way".
也就是说,用于将 classes 上的字段标记为私有的语法目前处于功能开发过程的 Stage 3 中,并且受转译器支持。
所以答案是:有多种方法可以确保隐私,具体取决于具体的用例和您的团队使用的代码风格。
使用 classes 的团队可能会使用 # private class field syntax。
class MyClass {
#myPrivateField = 'foo'
bar(s) {
return this.#myPrivateField + s
}
}
使用函数的团队将使用 closures。
function createObject() {
let myPrivateVariable = 'foo'
return {
bar(s) {
return myPrivateField + s
}
}
}
你可以吹毛求疵地说 bar
的函数对象是在每个实例的基础上创建的。在绝大多数情况下,这无关紧要。
Symbols 有时会被使用,尽管这些提供较少的隐私,因为它们可以通过反射查看。
function createObject() {
let secretSymbol = Symbol('secret')
return ({
[secretSymbol]: 'foo',
bar(s) {
return this[secretSymbol] + s
}
})
}
WeakMaps和模块也可以使用。有关详细信息,请参阅下面的 link。
请注意,您还可以使用带闭包的 class 来确保变量保持私有。
参见 also, 。
假设我们有以下代码:
const _timeStamp = new WeakMap();
const _running = new WeakMap();
export class Stopwatch {
constructor() {
_timeStamp.set(this, 0);
_running.set(this, false);
}
start() {
// start stopwatch
_running.set(this, true)
_timeStamp.set(this, Date.now())
}
stop() {
// stop stopwatch
_running.set(this, false);
return (Date.now() - _timeStamp.get(this))/1000
}
}
在这个例子中,我们试图使用 weakmaps 向最终用户隐藏一些信息。 根据调用的方法,我们更改两个 weakmaps 中的值。 当我们重新分配变量时,我们改变了状态。
let x = 0;
x = 10
编辑:
但是,我们在更新 weakmaps 中的值时不会像在变量的情况下那样改变状态吗? 'best practice' 使用需要可重写的私有 props 是什么?
非常感谢任何澄清!
为了回答您关于 WeakMaps 的问题,我认为您是在谈论副作用。使用 WeakMap 时,您可以想象设置值不会对用户空间产生副作用,因为 WeakMap 颠倒了项目和集合之间的通常关系。在 WeakMap 中,出于垃圾回收的原因,项目维护一个隐藏的 link 到集合(而不是集合维护对项目的引用),所以我们可以假装没有副作用。
但是,这个问题也与 JavaScript 中的隐私有关。
碰巧,JavaScript 一直提供一种出色的(据我所知是难以理解的——与 C# 等语言中的私有字段不同)强大的隐私机制:闭包。只是大多数开发人员来自基于 class 的面向对象背景,并花时间学习 "JavaScript way".
也就是说,用于将 classes 上的字段标记为私有的语法目前处于功能开发过程的 Stage 3 中,并且受转译器支持。
所以答案是:有多种方法可以确保隐私,具体取决于具体的用例和您的团队使用的代码风格。
使用 classes 的团队可能会使用 # private class field syntax。
class MyClass {
#myPrivateField = 'foo'
bar(s) {
return this.#myPrivateField + s
}
}
使用函数的团队将使用 closures。
function createObject() {
let myPrivateVariable = 'foo'
return {
bar(s) {
return myPrivateField + s
}
}
}
你可以吹毛求疵地说 bar
的函数对象是在每个实例的基础上创建的。在绝大多数情况下,这无关紧要。
Symbols 有时会被使用,尽管这些提供较少的隐私,因为它们可以通过反射查看。
function createObject() {
let secretSymbol = Symbol('secret')
return ({
[secretSymbol]: 'foo',
bar(s) {
return this[secretSymbol] + s
}
})
}
WeakMaps和模块也可以使用。有关详细信息,请参阅下面的 link。
请注意,您还可以使用带闭包的 class 来确保变量保持私有。
参见 also,