0

我用 JavaScript 编写了一个类,我试图在一个私有函数中修改我的一个公共属性。

这是我的代码示例:

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
[]

为什么我无法从回调函数中看到我的修改?

4

4 回答 4

1

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

有很多方法可以避免它:您可以保存this到变量,如上所述。它适用于 100% 的情况。

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

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

于 2016-09-27T14:43:00.347 回答
1

因为_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
...
于 2016-09-27T15:01:43.200 回答
1

看到这个关键字。使用箭头函数是防止许多这些问题的好方法:

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

然而,你仍然需要意识到这一点。

于 2016-09-27T14:30:07.817 回答
1

_doStuf通过类似的函数调用时

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

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

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();

于 2016-09-27T14:47:07.310 回答