Javascript 从私有函数修改 public 属性

Javascript modify public properties from private functions

我在 JavaScript 中编写了一个 class,我正试图在私有函数中修改我的 public 属性之一。

这是我的代码示例:

MyClass = function(callback){

    this.tabs = [];
    var tabs_callback = function(){};

    this.setTabsCallback = function(callback) {
        tabs_callback = callback;
    }

    var _doStuff = function(callback) {

        // doing stuff

        this.tabs = [1, 2, 3];

        console.log("Inside doStuff");
        console.log(this.tabs);

        tabs_callback();
    }

    this.doStuff = function() {
        _doStuff();
    }
}


var myObject = new MyClass();

myObject.setTabsCallback(function () {

    console.log("Inside callback");
    console.log(myObject.tabs);
});

myObject.doStuff();

这是我在控制台中得到的:

Inside doStuff
[ 1, 2, 3 ]
Inside callback
[]

为什么我在回调函数中看不到我的修改?

参见this keyword。使用箭头函数是防止这些问题的好方法:

var _doStuff = (callback) => { ...

不过你还是要注意一下。

默认情况下,JS不使用词法上下文绑定,当你调用普通函数时,this默认为window(如果是严格模式则为null)。

有很多方法可以避免它:您可以将 this 保存到变量,如上所述。它在 100% 的情况下都有效。

您还可以使用 Function#bind 方法将 _doStuff 显式绑定到上下文:在初始化后执行类似 _doStuff = _doStuff.bind(this) 的操作,或者您可以将其称为 _doStuff.bind(this)()。 IE9 之前的 IE(也许还有其他一些浏览器,我不太确定)不支持 bind.

最后,你可以使用箭头函数,正如上面也提到的:他们使用词法绑定,this 将与你期望的相同。箭头函数自 ES6 以来可用,但是,我想,如果你正在制作这样的构造函数,它不是 ES6。

当通过

这样的函数调用_doStuf
this.doStuff = function() {
                 _doStuff();
               }

_doStuff 绑定到全局对象。因此,您应该将其定义绑定到 this 或在调用 _doStuff 函数时使用 .call(this)。因此,按如下方式修改您的代码会有所帮助;

MyClass = function(callback){

    this.tabs = [];
    var tabs_callback = function(){};

    this.setTabsCallback = function(callback) {
        tabs_callback = callback;
    }

    var _doStuff = function(callback) {

        // doing stuff

        this.tabs = [1, 2, 3];

        console.log("Inside doStuff");
        console.log(this.tabs);

        tabs_callback();
    } // <<< you can either use .bind(this) here 

    this.doStuff = function() {
        _doStuff.call(this);  // <<< or use .call(this) here to bind _doStuff to the this
    }
}


var myObject = new MyClass();

myObject.setTabsCallback(function () {

    console.log("Inside callback");
    console.log(myObject.tabs);
});

myObject.doStuff();

因为 _doStuff 被定义为一个函数,它有自己的 this 上下文,这就是为什么你不能访问你在私有函数之外定义的 this.tabs

有两种简单的方法可以解决这个问题。

首先,您可以简单地创建一个私有变量,它在函数外保存对 this 的引用:

...
var that = this;
var _doStuff = function(callback) {
    // inside _doStuff, use "that" instead of "this"
...

或者,其次,您可以改用箭头函数。箭头函数是对 Javascript 的一个相对较新的补充。它们不会创建具有自己的 this 引用的单独上下文,因此当您使用 this 对象时,它仍将引用与函数外部相同的对象,因此您的函数将正常工作:

....
var _doStuff = (callback) => {
    // now _doStuff doesn't create a new "this" object, so you can still access the one from outside
...