0

I thought I understood how javascript scope worked until now. This is what I have

function MFCommentsHandler(node, type, item) {
    this.get = function(returnType){
        ...
    }

    function getButton(){
        var button = document.createElement('button'),
            get = this.get;
        button.innerHTML = 'Load more comments';
        button.onclick = function(){
            console.log(get);
            get('html');
        }
        return button;
    }

}

I use inner functions to append the element generated by getButton to the document, but when I click it I get get is not a function. Why is get undefined inside of the onclick function?

4
  • Are you making get global? Commented Jan 16, 2014 at 22:35
  • because this is whatever context you're calling MFCommentsHandler in. Unless you're constructing a new object using new. Commented Jan 16, 2014 at 22:36
  • In your case I would just use var get = function... Commented Jan 16, 2014 at 22:36
  • @StephenThomas– this has nothing to do with "context", it is set entirely by how a function is called or by bind. Commented Jan 16, 2014 at 22:40

3 Answers 3

2

this depends only on how you call a function. It can be implicit, but in your case, you lost the context. You need to cache this in the upper scope:

function MFCommentsHandler(node, type, item) {
    var self = this;
    this.get = function(returnType){
        ...
    }
    function getButton(){
        self.get(); // cached reference
        ...
    }
}

Or you can explicitly pass the context when you call getButton:

function MFCommentsHandler(node, type, item) {
    this.get = function(returnType){
        ...
    }
    function getButton(){
        this.get();
        ...
    }
    getButton.call(this); // explicit context
    ...
Sign up to request clarification or add additional context in comments.

3 Comments

Ah.. Such a simple mistake.. Thank you sir.
"this depends only how you call a function". Exactly. "but in your case, you lost the context". Which conflicts with the first statement. What you mean is this isn't set to the required value in the call.
What I mean is that this isn't what it was before so "you lost context", but technically, yes, it's because this is not set in the call. But the call can be implicit, as in obj.method(), but you can call the function without dot notation, thus you "lose context". That's how I'd explain it.
2

The referant of this changes with context. Try this instead:

function MFCommentsHandler(node, type, item) {
    var get = function(returnType){
        ...
    }

    function getButton(){
        var button = document.createElement('button');
        button.innerHTML = 'Load more comments';
        button.onclick = function(){
            console.log(get);
            get('html');
        }
        return button;
    }

}

2 Comments

but then I won't be able to call get from the outside
@php_nub_qq That's true. In that case go with elclanrs's answer.
1

The getButton() function you defined inside the MFCommentsHandler() function you defined is a closure. Closures have access to the variables and arguments (but not the arguments object) of their outer function. They however, do not have access to the this value of their outer function. To have access to this value, just store a reference of it in a variable so it can be accessed from the inner function.

function MFCommentsHandler(node, type, item) {
    var that = this; //reference to the invocation context
    //that can be accessed anywhere within this function

    this.get = function(returnType){
        ...
    }

    function getButton(){
        ...
        that.get('html');
    }

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.