【问题标题】:Javascript modify public properties from private functionsJavascript 从私有函数修改公共属性
【发布时间】:2017-02-05 05:38:33
【问题描述】:

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

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

【问题讨论】:

  • 大概是this的范围。在MyClass 函数的顶部(可能是this.tabs = []; 上面的行)创建一个变量var self = this; 并使用self 代替您要访问公共属性的this
  • 哦,太好了!你是对的,它奏效了!非常感谢

标签: javascript class oop properties private-functions


【解决方案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
...

【讨论】:

    【解决方案2】:

    this keyword。使用箭头函数是防止许多此类问题的好方法:

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

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

    【讨论】:

      【解决方案3】:

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

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

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

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-04-02
          • 2018-05-09
          • 1970-01-01
          • 2012-10-25
          • 2012-05-29
          • 1970-01-01
          • 1970-01-01
          • 2015-04-27
          相关资源
          最近更新 更多