Search code examples
javascriptjquerydojoarcgis-js-api

Unexpected scope behaviour in Javascript objects


I tried my best to replicate the error outside my context but failed so, so I'll have to provide with it.

Code :

var view;

widget = {
    activated: false,
    close: function(){
        this.view.popupManager.enabled = false;
    }
}

view = new MapView({
}).then(function(){ //then is triggered when fully loaded;
    console.log(this.popupManager) //Object!
    widget.activated = true;
    widget.view = this;
}

console.log(view.popupManager) //Undefined, not loaded yet

$('#my_button').click(function(){
    if(widget.activated){
        widget.close() //this.view.popupManager is undefined
    }
})

This is using Esri's Javascript 4.3 API, but it doesn't seem to be the API, but some misuderstanding of my part on how scope works in Javascript.

As you can see, even though I only call widget.close if view is fully loaded, it still referencing the old, not fully loaded object

What am I missing?


Solution

  • The problem here is that this isn't always what you think it is. There are a couple of thiss in your code, and each is different.

    Welcome to JavaScript's often misunderstood this.

    In the code

    widget = {
        activated: false,
        close: function(){
            this.view.popupManager.enabled = false;
        }
    }
    

    this will refer to the widget.

    Now in the code inside the then callback, this will refer to the window object, so you're essentially saying widget.view = window. This this is probably the one which is catching you out.

    I suspect that what you mean is to set the widget's view to the new view, in which case you will need to update the code as follows:

    var view;
    
    widget = {
        activated: false,
        close: function (){
            this.view.popupManager.enabled = false;
        }
    }
    
    view = new MapView({
    }).then(function () {
        widget.activated = true;
        widget.view = view; // set the widget's view correctly
    });
    
    $('#my_button').click(function(){
        if(widget.activated){
            widget.close();
        }
    });