Pro Javascript Design Patterns errata?

800 Views Asked by At

Can anyone confirm that these samples from Chapter 3 of Pro Javascript Design Patterns are flawed and, if so, how fundamentally - are they more than a typo or two away from producing the intended goal of 'class' constants in JavaScript? Thanks.

var Class = (function() {

  // Constants (created as private static attributes).
  var UPPER_BOUND = 100;

  // Privileged static method.
  this.getUPPER_BOUND() {//sic
    return UPPER_BOUND;
  }

  ...

  // Return the constructor.
  return function(constructorArgument) {
    ...
  }
})();

/* Usage. */

Class.getUPPER_BOUND();

/* Grouping constants together. */

var Class = (function() {

  // Private static attributes.
  var constants = {
    UPPER_BOUND: 100,
    LOWER_BOUND: -100
  }

  // Privileged static method.
  this.getConstant(name) {//sic
    return constants[name];
  }

  ...

  // Return the constructor.
  return function(constructorArgument) {
    ...
  }
})();


/* Usage. */

Class.getConstant('UPPER_BOUND');
6

There are 6 best solutions below

3
On BEST ANSWER

The code can be trivially fixed as

var Class = {
  UPPER_BOUND: 100
};

The rest of the code is over engineered or plain wrong and should be ignored.

If you care about being read only then set the writable flag to false (note the default is false).

var Class = {};
Object.defineProperty(Class, "UPPER_BOUND", {
  value: 100,
  enumerable: true,
  configurable: true
});
0
On

How about do it this way?

/* Grouping constants together. */
var Class = (function() {
  // Private static attributes.
  var constants = {
     UPPER_BOUND: 100,
     LOWER_BOUND: -100
  }

  // Return the constructor.
  return new function(constructorArgument) {
     // Privileged static method.
     this.getConstant = function(name) {//sic
       return constants[name];
     }
   }
})();

console.log(Class.getConstant("LOWER_BOUND"));
3
On

Got this to work, but not sure if this was what the authors intended it to be.

var Class = (function()
{
    // Constants (created as private static attributes).
    var constants =
    {
        UPPER_BOUND: 100,
        LOWER_BOUND: -100
    };

    // Return the method(s).
    return {
        getConstant: function(name)
        {
            return constants[name];
        }
    }
}());

console.log(Class.getConstant('UPPER_BOUND')); // shows "100" in console
1
On

I think, this is wrong. As mentioned previously, "this" refers to the window object and the code also has a syntax error. The following code should accomplish the required goal:

var Class = (function () {

    // Private static attributes.

    var constants = {
        UPPER_BOUND: 100,
        LOWER_BOUND: -100
    };            

    var sc = function (constructorArgument) {

    };

    // Privileged static method.
    sc.getConstant = function (name) {
        return constants[name];
    };

    // Return the constructor.
    return sc;
})();

alert(Class.getConstant('UPPER_BOUND'));
0
On

Be wary of anything claiming to be "Pro" whatever. I haven't read the book, but my take on the code is as follows:

> var Class = (function() {
> 
>   // Constants (created as private static attributes).

The word "attributes" is wrong, it should be either "properties" or "variables" because they are variables, which can also be described as properties of the local activation/variable object.

>   var UPPER_BOUND = 100;
> 
>   // Privileged static method.  
>   this.getUPPER_BOUND() {//sic

The code will be executed in a global context where this is the window/global object. So if there is a global *getUPPER_BOUND* function, it will be called with no arguments. It is followed by a curly brace ({) which opens a block in a place where a block can't be, so that is a syntax error.

I presume the following was intended:

    this.getUPPER_BOUND = function() {

which creates a getUPPER_BOUND property of the global/window object that is assiged the anonymous function on the RHS when the code is run.

>     return UPPER_BOUND;   }
> 
>   ...
> 
>   // Return the constructor.
>   return function(constructorArgument) {

This is the function that is assigned to the global variable "Class".

>     ... 
>   }
>  })();

With fixes it may "work", but not elegantly. Any book with such glaring errors in the code has not been carefully written and certainly hasn't been properly reviewed before being published.

Use reputable online resources and continue to ask questions about anything you don't understand or think is in error. There are other forums for discussing javascript that can provide far more detailed answers for technical questions.

9
On

Check this out as a good alternative: http://www.klauskomenda.com/code/javascript-programming-patterns/

and for immutable public properties, as was suggested, use Object.freeze and John Resig's great advice: http://ejohn.org/blog/ecmascript-5-objects-and-properties/

and for a way to not clobber your global scope, add namespaces to jQuery: Is it possible to create a namespace in jQuery?