2

I ran into a problem with my JavaScript code.

I have a class MyClass and added function myFunction to its prototype.

MyClass.prototype.myFunction = function(file){
    if(some condition){
       fs.exists("./" + file, function(exists){
           if(exists)
               console.log(this.someValue);
               /* lot of other code */
           else
               /* do something else */
    });
    }else{
        /* do something */
    }
}

My problem is the scoping of this.someValue (as an example I want to just print it). Every time exists equals true the console logs undefined but it is not. If I would print it outside of fs.exists() then it has a value so I guess it is a scoping problem.

How can I access this.someValue in this sample?

3 Answers 3

4

You have to .bind your inner function

MyClass.prototype.myFunction = function(file){
    if(some condition){
       fs.exists("./" + file, function(exists){
           if(exists)
               console.log(this.someValue);
               /* lot of other code */
           else
               /* do something else */
    }.bind(this));
    }else{
        /* do something */
    }
}

This can be rewritten to be cleaner

MyClass.prototype.myFunction = function myFunction(file){
  if(some condition){
    fs.exists("./" + file, this.doSomething.bind(this));
  }
  else{
    // do something else
  }
}

MyClass.prototype.doSomething = function doSomething(exists) {
  if(exists) {
    console.log(this.someValue);
    // lot of other code
  }
  else {
    // do something else
  }
}

I personally like this solution because it allows you to maintain excellent code composition and prevents you from nesting function(){ function(){ function(){ ... }}}. It also prevents you from having a bunch of var that = this; or var self = this; variables floating around having you wonder which scope is which.

.bind is slower, yes, but as minitech points out, it's certainly not going to be your bottleneck when compared to file access.

Sign up to request clarification or add additional context in comments.

8 Comments

Binding is one of the slowest ways of passing scope pointer into another function. And has slightly different application purpose.
@MaksimsMihejevs: Slow relative to file access? Don’t micro-optimize…
Not relative to file operation, but slow for such simple operation. In fact it is dramatic difference, please check out here: jsperf.com/bind-vs-closure-setup/6
@MaksimsMihejevs the original question, and this answer, both use it in the context of a fs.exists() callback. If it was in the middle of a tight loop, I'd agree with you, but when it's mixed in with file I/O the performance penalty background noise at worst, and .bind() does result in more easily understandable code (this all the way down).
i like your solution too. in fact it is much more readable for this use case :) I'll test it too but I think it is not that nice for bigger functions because of scrolling :)
|
3
MyClass.prototype.myFunction = function(file){
  var that = this;
  // some lines of code later...
       console.log(that.someValue);
}

Comments

2

As this - is keyword that is defined by scope of function and responds to owner or caller of a function. So you might store its pointer in another variable:

MyClass.prototype.myFunction = function(file) {
  if(some condition) {
    var self = this; // create variable with pointer to 'this'
    fs.exists("./" + file, function(exists) {
      if(exists) {
        console.log(self.someValue); // we can access it to parent scope variables
        /* lot of other code */
      } else {
        /* do something else */
      }
    });
  } else {
    /* do something */
  }
}

As well check out this brilliant topic: How does the "this" keyword work?

1 Comment

{ location: London" is invalid, fwiw

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.