13

我有这堂课:

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

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

提前致谢!

4

5 回答 5

17

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

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

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

于 2012-05-23T11:18:03.313 回答
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";
    }
}
于 2012-05-23T11:25:21.963 回答
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);
}

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

于 2012-05-23T11:30:43.513 回答
2

JS 中没有私有这样的东西,但是您可以使用闭包来使用范围。

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

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

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

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

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

如果您想var1作为属性公开,那么您需要绑定 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并且您不想使用 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 不那么优雅。

于 2012-05-23T11:33:46.613 回答
0
function ctest() {
    this.var1 = "haha";
    this.func1 = function() {
        alert(this.var1);
        func2(this);
        alert(this.var1);
    }
    var func2 = function(obj) {
        obj.var1 = "huhu";
    }
}

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

于 2012-05-23T11:19:01.020 回答