【问题标题】:Do we change states when setting new values in weakmaps?在weakmaps中设置新值时我们会改变状态吗?
【发布时间】:2020-06-05 23:48:12
【问题描述】:

假设我们有以下代码:

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
  }
}

在此示例中,我们尝试使用弱图向最终用户隐藏一些信息。 根据调用的方法,我们更改两个弱图中的值。 当我们重新分配变量时,我们会改变状态。

let x = 0;
x = 10

编辑:


作为最佳实践,我们不应该在 JS 中改变对象或更改状态

但是,我们不要在更新 Weakmap 中的值时更改状态,就像我们在以防万一时所做的那样变量?使用需要可重写的私有道具时,“最佳做法”是什么?

任何澄清都非常感谢!

【问题讨论】:

  • x=10 不也是状态变化吗?也忽略“最佳实践”。
  • 请阅读我更新的问题。正如我所指出的,这确实是一种状态变化。
  • 是的。它是。那么谁说变量赋值是一种不好的做法呢? “作为最佳实践,我们不应该在 JS 中改变对象或更改状态”在没有上下文的情况下确实是零意义
  • @PieterT2000 请您提供更多上下文或解释吗?以这种方式使用 Wea​​kMap 存储变量值对我来说似乎很不寻常。我可能希望使用实例变量。
  • @Ben 这是一个非常简化的代码示例。在实际代码中,我使用弱映射来存储私有变量,目的是使最终用户无法访问它们。 (抽象)我只是想知道当你必须像上面的例子一样在整个程序中更新它们的值时使用弱图是否正确。

标签: javascript oop javascript-objects es6-class weakmap


【解决方案1】:

要回答您关于WeakMaps 的问题,我认为您是在谈论副作用。使用 Wea​​kMap 时,您可以想象设置值没有用户空间副作用,因为 WeakMaps 反转了项目和集合之间的通常关系。在 WeakMap 中,出于垃圾回收的原因,项目维护到集合的隐藏链接(而不是集合维护对项目的引用),因此我们可以假装没有副作用。

但是,这个问题也与 JavaScript 中的隐私有关。

碰巧的是,JavaScript 始终提供了一种出色的(据我所知是难以理解的 - 与 C# 等语言中的私有字段不同)的强大隐私机制:闭包。只是大多数开发者都来自于基于类的面向对象背景,需要花时间学习“JavaScript 方式”。

也就是说,用于将类上的字段标记为私有的语法目前位于功能开发过程的Stage 3,并且由转译器支持。

所以答案是:有多种方法可以确保隐私,具体取决于具体的用例和您的团队使用的代码风格。

使用类的团队可能会使用# 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 和模块也可以使用。有关更多详细信息,请参阅下面的链接。

请注意,您还可以使用带有闭包的类来确保变量保持私有。

请参阅alsoand

【讨论】:

  • 哇,这很全面。非常感谢您回答我的问题!
猜你喜欢
  • 1970-01-01
  • 2018-04-23
  • 1970-01-01
  • 2022-01-21
  • 1970-01-01
  • 2021-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多