javascript私有函数访问公共变量

时间:2012-05-23 11:15:12

标签: javascript class private public

我有这堂课:

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公共变量?

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

提前致谢!

5 个答案:

答案 0 :(得分:17)

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

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

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

答案 1 :(得分:12)

函数与实例无关,因此,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";
    }
}

答案 2 :(得分:2)

另一种选择是使用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);
}

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

答案 3 :(得分:2)

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作为属性公开,那么您需要bind func2到您在构造函数中创建的对象实例:

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并且您不想使用垫片(如上面的链接所示),您可以再次利用这些闭包:

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不太优雅。

答案 4 :(得分:0)

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

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