Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I do understand the difficulty of testing private code in tools like jasmine when you use private variables based on publicly unreachable scopes. When I have to do this, I add a debug object with references to the code. Generally, this code should affect publicly accessible methods and those are more important to test. If they fail, decent in-browser tools like breakpoints and watch lists should reveal the error.

I'm not completely ready to call this an anti-pattern. There's no reason to expose local methods of an Object to the parent scope if they aren't needed. I'm sure that in some cases this could cause the memory footprint of an Object to be larger than desired by preventing garbage collection. Anyway, I would have factored your code more like this:

  var PseudoClass = function(_args){
      // guarantee that "this" is what we expect
      if( this === window ){ // use global for non-browser    implementations
         return new PseudoClass(_args);
      }
      // private variables are local
      var private = function() {;
             this.value = 2; 
          };
      // public variables are on prototype 
      this.constructor.prototype.value = 1; // I'd prolly use a local var and a getter for this
      this.constructor.prototype.public = function(){
          private.call(this); // force scope for private methods
      };
      // testing access (only added when necessary)
      this.constructor.prototype.privateMembers = {
          "private":function(){ private.call(this) }
      };
    };
There's no "self" here, but there are two pieces of insurance around scope. First is the condition that forces the "new" keyword. (This could be written to test against instanceof the function name, but generally problems occur when users forget new, not when they force the scope to be wrong. Last I checked, this is how jQuery tests it too.) Second is calling the private methods with the call() method of the function, allowing us to keep the scope from defaulting to global/window. Sure, you are forced to put these in to avoid errors, but this is programming. If you would like it to throw an error when this === window within private(), just add it. I didn't because a) I'm lazy and b) once the PseudoClass private methods are all called, I would end up removing the un-thrown errors and the privateMembers property before compressing for staging/production to keep size down.

Using a variable like "self" is quite clear in this context and I've seen it done thousands of times. I just wanted to show that using "this" is still possible.

Javascript is a funny language. I often find myself wondering if this was the intended structure of the language as it takes advantage of many of the key elements (closure scopes & prototype) while abstractly appearing like simple Java (or C#). Sure in a perfect world, the wrangling of "this" wouldn't need to be done. I'd say the unpredictable value of "this" in different contexts is the biggest fail of Javascript. I programmed ActionScript (including AS1) for many years and this (pun intended) is the biggest mindf*ck I've come across when regarding them in comparison (considering they're both based on ECMA script). Hope there was something helpful to you in this.



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: