0

So, I have this code:

var exampleModule = (function() {
  var example = {};

  var self = this;

  example.test = function() {
    this.mousedown = function (e) {
      self.x1 = e.offsetX;
      self.y1 = e.offsetY;
    };

    this.mousemove = function(e) {
      // do something with x1 and y1 and e.offsetX and e.offsetY
    };
  };
})();

I'd like to have x1 and y1 only be scoped within example.test. Is there any way to do this with this or do I have to do something like example.test.x1 for each one? Currently they are scoped to the entire exampleModule and I would like to narrow this to just example.test.

I only somewhat understand the whole self/that = this; mantra. I know that Javascript has this bug where this when in a function in a function refers to the global scope instead, but what of when there are 3 functions like in the example above? What is this equal to when nested three or four functions down?

John Smith
  • 8,096
  • 11
  • 44
  • 66
  • *"I'd like to have x1 and y1 only be scoped within example.test"* What do you mean by that? You don't want them to be on `exampleModule` as well? – T.J. Crowder Sep 13 '15 at 18:31
  • @T.J.Crowder: correct! – John Smith Sep 13 '15 at 18:33
  • ES6 solves the local scope problem which previously was an issue with Js global scope and function scope. To use the new feature simply replace every var keyword with the keyword let. Let means your variables are scoped where they are declared, ie within the braces they are declared. Unfortunately you have to transpile your code using babel or similar as browsers don't fully support this. – Faktor 10 Sep 13 '15 at 19:23
  • How good is babel? I want my code to run on as many systems as possible. – John Smith Sep 13 '15 at 19:26

1 Answers1

4

You can use the intermediate scope you already have with the example.test() function and store the variables there:

var exampleModule = (function() {
  var example = {};

  var self = this;

  example.test = function() {
    var x1, y1;
    this.mousedown = function (e) {
      x1 = e.offsetX;
      y1 = e.offsetY;
    };

    this.mousemove = function(e) {
      // do something with x1 and y1 and e.offsetX and e.offsetY
    };
  };
})();

Note: this design pattern is often fraught with issues because this assumes you will always get a mousedown before a mousemove which is clearly not always the case. So, you will have code carefully in the mousemove handler so you are sure you are using an appropriate value that was previously set.

Separately, it doesn't look like the value of this in example.test is probably what you want it to be, but you haven't really included enough info about that part of your code for us to know what you intended.

this in Javascript is set by how a function is called and is set to a new value in every function call in ES5 (arrow functions in ES6 are an exception). So, inside of your mousedown handler, it will be set by how this method is called. There's a summary of the various ways that this is set in this answer.

Community
  • 1
  • 1
jfriend00
  • 580,699
  • 78
  • 809
  • 825
  • Ok so I just tried this again (because I had tried it before) and it doesn't seem to work. The value doesn't persist between `mousedown` and `mousemove`. I also thought this would work and don't know why it isn't. – John Smith Sep 13 '15 at 19:34
  • Ok I figured it out but the solution is a bit out of the scope of the question. The reason why it wasn't working was because in another file I was calling `new` on the function every time instead of pre-loading it into a dictionary so the value kept getting reset. – John Smith Sep 13 '15 at 20:25