【问题标题】:JavaScript confusion with closure while trying to create private function [duplicate]尝试创建私有函数时JavaScript与闭包混淆[重复]
【发布时间】:2025-12-09 23:30:01
【问题描述】:

我正在尝试创建一个类似类的方式来访问具有公共和私有函数/变量的对象,但我有点困惑为什么这个简单的测试代码不起作用。

// Class type object with just one value.

function Play(arg) { // Constructor.
    var test = arg;

// Private, as not declared with "this." Obviously more complex in the future.
    private_settest = function( val ) {
        test = val;
    }

// Public.
    this.settest = function( val ) {
        private_settest(val);
    }

    this.gettest = function() {
        return test;
    }
}

var a = new Play(1);
var b = new Play(2);
a.settest(100);
console.log(a.gettest());
console.log(b.gettest());

我希望输出为 1 2,但实际输出为 1 100。

我认为这是一个关闭问题,有人愿意解释我缺少什么吗?

单步执行 this.settest() 时: test 的闭包值为 1(这是正确的)。

进入 private_settest() 时: test 的闭包值为 2,这是错误的,应该是 1。

退出 private_settest() 时,闭包值再次回到 1。我猜这是被弹出的闭包。

我们将不胜感激!

谢谢。

【问题讨论】:

  • private_settest = function( val ) { test = val; } 应该是function private_settest( val ) { test = val; }
  • 对了,你不希望输出是 100 2 吗?
  • 始终使用严格模式!

标签: javascript scope closures


【解决方案1】:
private_settest = function(val) {
    test = val;
}

这隐式定义了一个全局变量private_settest,当你构造new Play()时,每次都会覆盖全局,引用Play的最后一个初始化实例的作用域,在本例中为b。正如您所观察到的,这就是“私有”函数访问第二个实例范围的原因。这应该改为

function private_settest(val) {
    test = val;
}

为了在每个实例的范围内正确声明一个函数。

// Class type object with just one value.

function Play(arg) { // Constructor.
  var test = arg;

  // Private, as not declared with "this." Obviously more complex in the future.
  function private_settest(val) {
    test = val;
  }

  // Public.
  this.settest = function(val) {
    private_settest(val);
  }

  this.gettest = function() {
    return test;
  }
}

var a = new Play(1);
var b = new Play(2);
a.settest(100);
console.log(a.gettest());
console.log(b.gettest());

这会产生预期的输出 100 2(不是 1 2)。

【讨论】:

    【解决方案2】:

    问题在于private_settest 是一个全局变量。您没有使用 varletconstfunction)来声明具有本地范围的函数变量。因此,每次调用构造函数时,该函数的先前版本都会被覆盖。

    当您随后调用a.setttest 时,您实际上(通过该方法)调用了修改私有变量test 的单个全局函数,该私有变量实际上是b 实例的私有变量(最后一个创建的)。

    如果您使用"use strict",您将收到一条错误消息。

    【讨论】: