【问题标题】:JavaScript closure question with counter example [duplicate]带有反例的 JavaScript 闭包问题 [重复]
【发布时间】:2021-11-07 04:34:56
【问题描述】:

假设我们已经跟随 sn-ps:

function Counter() {
  let count = 0
  
  function inc() {
    count += 1
  }
  
  function dec() {
    count -= 1
  }
  
  function getCount() {
    return count
  }
  
  return { getCount, inc, dec, count }
}

const counter = Counter()
counter.inc()
counter.inc()

console.log(counter.getCount()) // 2
console.log(counter.count) // 0

我想知道为什么使用函数getCount() 并直接返回count 变量会显示不同的结果。在我看来,它们都引用了相同的count 地址,在inc() 调用之后,它的值应该相应地改变。

【问题讨论】:

  • 没有。一个引用变量,另一个引用属性(在使用值0 创建它后从未更新)。
  • return { count } 不返回“变量”,而是返回当时的

标签: javascript closures


【解决方案1】:

return { getCount, inc, dec, count }:

  1. 创建一个新对象
  2. 复制这四个变量的当前值到同名属性中
  3. 返回该对象

当您更改 count 变量的值时,您不会更改 count 属性的值。

【讨论】:

  • 谢谢,我正在考虑这个例子:let x = 0; y = x; x = 1;。将x 的值更改为1 后,y 仍然保持为0,因为它一直存储初始x 存储的值,而不是存储引用。我认为这就是理解我对我的问题的困惑的关键
【解决方案2】:

原因是当您执行counter.count 时,您从返回的新对象中获取计数值。该计数实际上是创建时值的副本,并且永远不会更新。

如果您创建一个类并改用this.count,它会一直更新。

class Counter {
  constructor() {
    this.count = 0;
  }
  
  inc() {
    this.count += 1;
  }
  
  dec() {
    this.count -= 1;
  }
  
  getCount() {
    return this.count;
  }
}

const counter = new Counter();
counter.inc()
counter.inc()

console.log(counter.getCount()) // 2
console.log(counter.count) // 2

或者,如果你想用更老式的方式来做:

function Counter() {
  this.count = 0
  
  function inc() {
    count += 1
  }
  
  function dec() {
    count -= 1
  }
  
  function getCount() {
    return count
  }
  
  this.inc = inc;
  this.dec = dec;
  this.getCount = getCount;
  
  return this;
}

const counter = Counter()
counter.inc()
counter.inc()

console.log(counter.getCount()) // 2
console.log(counter.count) // 2

或者,您可以将 count 和对象设置为可以更新的值:

function Counter() {
  let count = { value: 0 }
  
  function inc() {
    count.value += 1
  }
  
  function dec() {
    count.value -= 1
  }
  
  function getCount() {
    return count.value
  }
  
  return { getCount, inc, dec, count }
}

const counter = Counter()
counter.inc()
counter.inc()

console.log(counter.getCount()) // 2
console.log(counter.count.value) // 2

虽然最后一个对于这个特定的用例来说有点傻。

【讨论】:

  • 你不需要创建一个类(甚至构造函数)来创建一个具有访问this.count的方法的对象。工厂函数返回的对象字面量就足够了。
  • 如果你使用counter.getCount(),对象字面量就足够了,是的。但是如果你想直接访问一个计数变量,没有直接的方法。他们有效使用的模式使count 成为私有的,并且返回的对象字面量有一个单独的、不变的计数副本。我给了他们三种可能的方法来调整它,使 count 成为一个实时值。
  • 是的,但是您忽略了第四个,更简单的一个 :-) 您的句子“如果相反,您创建一个类并改用this.count,它将始终被更新。 i>”应该只是“如果你使用this.count”,没有提到类。只需{ count: 0, getCount() { return this.count; }, inc() { this.count++; }, dec() { this.count--; } }
【解决方案3】:

主要是因为您从函数返回的count 是变量的副本(value 更准确)而getCount 是一个函数,它指的是count 的引用多变的。更多你可以了解here

【讨论】:

    【解决方案4】:

    因为在 getCount() 内部,您正在重新分配 count 的值,即 count = count + 1

    【讨论】:

      猜你喜欢
      • 2011-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 1970-01-01
      相关资源
      最近更新 更多