This might be a vague question (or even answered before, if so just cast a close vote and I'm happy with the point in the right direction), and if I just read up on the different scopes of JavaScript a few more times I might be wiser, but seeing as I've done that over several years and still get perplexed by the way JavaScript scopes work - some of you might have a good/proper explanation of why the below snippet works in the way it does:
(I understand that there's scope/context involved, or maybe mutable variable types, but can't figure out the difference in the below code snippet and why it's illogical)
class test {
    constructor() {
        this.obj = document.createElement('div');
        let style = {'padding' : '5px'};
        this.obj.innerHTML = '<h3>Click the button:</h3>';
        for (let key in style) {
            this.obj.style[key] = style[key]; 
        }
        this.some_var = 55;
        this.update_state.call(this, 'test');
        this.update_state_working.call(this, 'test');
    }
    update_state(state) {
        if (state == 'test') {
            const frame = document.createElement('div');
            frame.innerHTML = '<input style="background-color: #00FF00;" type="submit" value="Not working" />';
            frame.onclick = function(event) {
                console.log('You pressed: ' + this.some_var);
            };
            this.obj.appendChild(frame);
        }
    }
}
This will fail, logging You pressed: undefined. Which to me coming from other language backgrounds, is a bit confusing.
update_state(state) {
    let test_var = this.some_var;
    if (state == 'test') {
        const frame = document.createElement('div');
        frame.innerHTML = '<input style="background-color: #00FF00;" type="submit" value="Working" />';
        frame.onclick = function(event) {
            console.log('You pressed: ' + test_var);
        };
        this.obj.appendChild(frame);
    }
}
While this on the other hand will work.
I assume it's because test_var is a block scope locally defined in update_state and some how gets frozen in to the event function? But I don't get  why the difference? The context in my mind would be the same since the event is bound to a certain DOM object or outer class scope/instance?
I found What is the scope of variables in JavaScript? which has a pretty good explanation of what the different scopes are in practical examples, and I thought that this.some_var would be accessible according to example #6. And this question, scope of variable inside an event listener callback function - hints that this.index should be accessible inside a onclick function, which to me - it isn't?
What is the best practice method in solving this context issue? Because I rarely see anyone solving it by doing let declarations, but maybe I've just missed something obvious?
I'm looking for an explanation (or a resource describing the pickle) to why this locally declared variable works, why the context of the test instance can't be used as a variable source like the link above suggested, and what the appropriate solution to this might be (if not declaring by block scope local variable).
JsFiddle: https://jsfiddle.net/2cbfhzt5/
