【问题标题】:javascript private function access public variablejavascript私有函数访问公共变量
【发布时间】:2012-05-29 22:24:27
【问题描述】:

我有这门课:

function ctest() {
    this.var1 = "haha";
    this.func1 = function() {
        alert(this.var1);
        func2();
        alert(this.var1);
    }
    var func2 = function() {
        this.var1 = "huhu";
    }
}

并称之为:

    var myobj = new ctest();
    myobj.func1();

不应该第二个警报会弹出“huhu”吗? func2 是私有的,不能访问 var1 的公共变量吗?

如果私有函数无法访问公共变量,我该怎么办?

提前致谢!

【问题讨论】:

标签: javascript class private public


【解决方案1】:

您需要提供调用func2的上下文:

this.func1 = function() {
    alert(this.var1);
    func2.call(this);
    alert(this.var1);
}

如果没有上下文,调用将使用全局对象(即window) - 当您运行当前代码时,您应该会看到在两个警报之间创建了window.var1

【讨论】:

  • 如果我按照您的建议进行操作,则表明 func2() 不是函数
  • @MIrrorMirror 啊,嗯,是的 - 等等!
  • 那行不通:func2 是私有变量,而不是属性。
  • @xdazz 现已修复 - 您必须使用 .call 将上下文添加到本地范围的函数。
  • @MIrrorMirror 否,.call 的第一个参数设置函数内隐含的this 值。
【解决方案2】:

函数与实例无关,因此您对 func2 的调用最终会导致 this 没有指向预期实例的调用。

您可以修复调用以包含上下文:

function ctest() {
    this.var1 = "haha";
    this.func1 = function() {
        alert(this.var1);
        func2.call(this);
        alert(this.var1);
    }
    var func2 = function() {
        this.var1 = "huhu";
    }
}

或者您可以保留一个带有所需对象引用的变量:

function ctest() {
    var that = this;
    this.var1 = "haha";
    this.func1 = function() {
        alert(this.var1);
        func2();
        alert(this.var1);
    }
    var func2 = function() {
        that.var1 = "huhu";
    }
}

【讨论】:

【解决方案3】:

另一种选择是使用Function.bind

function ctest() {
    this.var1 = "haha";
    this.func1 = function() {
        alert(this.var1);
        func2();
        alert(this.var1);
    }
    var func2 = function() {
        this.var1 = "huhu";
    }.bind(this);
}

请注意,浏览器对此的支持并不完美。

【讨论】:

  • 为什么要同时使用that .bind()
  • @Alnitak:糟糕的复制和粘贴
【解决方案4】:

在 JS 中没有私有这样的东西,但是你可以使用 closures 来玩作用域。

例如,假设在您的示例中,您不需要将 var1 公开为公共财产。您可以轻松地重写您的代码,如下所示:

function ctest() {
    var var1 = "haha";

    this.func1 = function() {
        alert(var1);
        func2();
        alert(var1);
    }

    var func2 = function() {
        var1 = "huhu";
    }
}

因为func1func2 共享相同的范围——它们在相同的函数中定义,ctest——它们可以访问相同的变量。当然,在这种情况下你没有暴露var1,所以:myobj.var1 将是undefined

如果你想让var1作为属性公开,那么你需要bindfunc2到你在构造函数中创建的对象实例:

function ctest() {
    this.var1 = "haha";
    this.func1 = function() {
        alert(this.var1);
        func2();
        alert(this.var1);
    }
    var func2 = function() {
        this.var1 = "huhu";
    }.bind(this);
}

否则func2 将具有不同的上下文对象 (this)。如果浏览器不支持 bind 并且您不想使用 shim(如上面的链接所示),您可以再次利用闭包:

function ctest() {
    this.var1 = "haha";
    this.func1 = function() {
        alert(this.var1);
        func2();
        alert(this.var1);
    }
    var context = this;
    var func2 = function() {
        context.var1 = "huhu";
    }
}

IMVHO 不那么优雅。

【讨论】:

    【解决方案5】:
    function ctest() {
        this.var1 = "haha";
        this.func1 = function() {
            alert(this.var1);
            func2(this);
            alert(this.var1);
        }
        var func2 = function(obj) {
            obj.var1 = "huhu";
        }
    }
    

    还有其他方法可以解决这个问题,请查看其他答案:)

    【讨论】:

    • @Alnitak 但这不会有问题,obj 是参数。
    猜你喜欢
    • 2011-12-03
    • 2015-04-02
    • 2016-01-09
    • 2013-12-31
    • 1970-01-01
    • 1970-01-01
    • 2013-10-08
    • 2012-12-28
    • 2011-07-22
    相关资源
    最近更新 更多