4

i have a simple Javascript "class" im testing right now. I noticed that "this" in my private functions do not point to the object itself, instead, its pointing to the global scope (window).

Why?

Info: i want to keep mode private, so i used var mode instead of this.mode. I also want to keep both internal functions private, so user has no access to it. I basically use .prototype to add public functions to myStorage accessing private members with this.

My code:

var myStorage = function(mymode) {
    var mode = mymode;
    function privateFunctionA() {
      // access this.mode to read mymode from constructor but 
      // this is pointing to window
    };

    function privateFunctionB() {
      // access this.mode to read mymode from constructor but 
      // this is pointing to window
    };

    // check for indexeddb, websql and localstorage
    if(mymode == 'A') {
      privateFunctionA();
    } else {
      privateFunctionB();
    }
};
myStorage.prototype.publicFunc = function() {
  console.log(this.mode); // does this work?
}

var data = new myStorage();
NovumCoder
  • 4,349
  • 9
  • 43
  • 58
  • The [`this` context](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) does have nothing to do with scope, it would point to the object whose *properties* you can access. `mode` however is a local *variable* - private to the constructor. So NO - you cannot access it from the prototype function. – Bergi Jan 20 '14 at 18:03
  • `this` references the owner object of a function that is currently executing. Strictly speaking in this case it's the prototype object and not `myStorage`. – tiguchi Jan 20 '14 at 18:04

2 Answers2

6

this is always function scoped in JavaScript (unless you pass in a context explicitly using call() or apply(). Therefore, in your private functions, this no longer refers to the same this as in the parent scope. An idiomatic way of handling this in JavaScript is to assign this to a self var in the parent scope. E.g.,

var myStorage = function(mymode) {
    var self = this;
    var mode = mymode;
    function privateFunctionA() {
        console.log(self);
    };
    ...
};

Regarding this snippet:

myStorage.prototype.publicFunc = function() {
    console.log(this.mode); // does this work?
}

You will need to assign mode to this back in your constructor (instead of as a var). So, the constructor would now become:

var myStorage = function(mymode) {
    var self = this;
    this.mode = mymode;
    function privateFunctionA() {
        // works
        console.log(self.mode);
    };
    ...
};

And this.mode will also work in your .publicFunc() in this case.

As one more stylistic note, constructor functions in JavaScript usually use proper camel case (i.e., MyStorage).

jmar777
  • 38,796
  • 11
  • 66
  • 64
  • +1, You might also want to note that the private functions *can* access the local *variables* (`mymode`, `var mode`) – Bergi Jan 20 '14 at 18:08
  • Sounds good, but there is no way to keep this.mode or var mode private so the object user does not see it? – NovumCoder Jan 21 '14 at 07:15
  • strange, how do i call my private function from my public prototyped function? self.privateFunctionA and this.privateFunctionA does not work. – NovumCoder Jan 21 '14 at 07:26
  • ok i had to move my prototyping inside the myStorage function instead of heaving it outside, then i called my private functions with privateFunctionA.call(this, data).... – NovumCoder Jan 21 '14 at 07:52
0

I dont think you can access the object itself with this when using prototype, because the scope changes and you loose the reference to the primary object itself, so this becomes the window instead.

Check this other question in order to get some more info:

Use of 'prototype' vs. 'this' in JavaScript?

Hope this helps.

Community
  • 1
  • 1
taxicala
  • 21,408
  • 7
  • 37
  • 66
  • 1
    Scope never changes. Context (`this`) does change, but is correct when called as `data.publicFunc()`. – Bergi Jan 20 '14 at 18:06