Difference between revisions of "JavaScript coding conventions"

From PKP Wiki
Jump to: navigation, search
(Added whitespace exception from Google style guide.)
(Added additional reading (books & recommended articles))
Line 95: Line 95:
  
 
You are obviously not supposed to use a member outside its scope even if the visibility is not enforced by closure. Please run <code>lib/pkp/tools/buildjs.sh</code> on your code to make sure that you have not overlooked anything. This is also true for protected object members. While they are named like public methods they must not be used outside of the inheritance hierarchy of the current class.
 
You are obviously not supposed to use a member outside its scope even if the visibility is not enforced by closure. Please run <code>lib/pkp/tools/buildjs.sh</code> on your code to make sure that you have not overlooked anything. This is also true for protected object members. While they are named like public methods they must not be used outside of the inheritance hierarchy of the current class.
 +
 +
 +
= Additional Resources =
 +
 +
== Recommended Books ==
 +
 +
* Ross Harmes and Dustin Diaz, "Pro JavaScript Design Patterns"
 +
* Douglas Crockford, "JavaScript: The Good Parts"
 +
 +
== Recommended Articles ==
 +
 +
* [http://joost.zeekat.nl/constructors-considered-mildly-confusing.html Constructors considered mildly confusing], an in-depth explanation of the <code>new</code> operator together with the prototypical inheritance approach
 +
* [http://jibbering.com/faq/notes/closures/ JavaScript Closures], an in-depth explanation of closures
 +
* [http://mckoss.com/jscript/object.htm Object Oriented Programming in JavaScript], a good overview over different inheritance approaches in JavaScript - not as good as the above books, though.
 +
* [http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml Google JavaScript Style Guide], especially the parts on closures, code formatting, JavaScript types and comments (for correct JsDoc) and tips and tricks.
 +
* [http://ejohn.org/blog/simple-javascript-inheritance/ Simple JavaScript Inheritance], an all-but-simple and IMO not-so-elegant idea to implement inheritance by John Resig, jQuery creator - just to test your knowledge. ;-)

Revision as of 14:51, 12 December 2010

Google Coding Conventions

We use Google's JavaScript style guide as a starting point for our own style guide.

Only deviations from the Google style guide will be documented here.

JsDoc Comments

We use class/member-level JsDoc comments as outlined in the Google style guide but we replace the file-level annotations by our usual annotations (@file, @brief, etc.).

Generally we encourage inline comments. These help readers of your code to understand the logic without having to understand every line of code. It's also a good practice to write inline comments before you write code so that you first think about the logic and semantics you want to implement and then about the syntax.

Whitespace

We generally use whitespace exactly as outlined in Google's JavaScript style guide except for indentation which we do with tabs rather than spaces.

Object Oriented Programming in JS

Inheritance

There are many ways to implement inheritance in JavaScript. We chose our approach for flexibility, simplicity and memory/execution performance.

We are using a (pseudo-)classical approach of inheritance rather than the purely prototypical or mixin approach:

// Define parent constructor.
Parent = function() { ... };
// Implement parent object.
Child.prototype.xyz = ...;

// Define child constructor.
Child = function() { ... };

// Let Child inherit from Parent - memory efficient version avoiding constructor side effects.
Temp = function() {};
Temp.prototype = Parent.prototype;
Child.prototype = new Temp();
// + a bit of sugar to fix the constructor property and allow access to the parent prototype...

// Implement child object.
Child.prototype.xyz = ...;

Compared with the 'purely' prototypical approach (parent = {...}; F = function() {}; F.prototype = parent; child = new F;):

  • It's easier to put in an intermediate object above the parent when we use constructors from the beginning.
  • It's easy to insert initialization code in the parent object if required at a later stage because we won't have to insert new everywhere in the code.
  • There's minimal overhead in using functions as parents if we make sure to not call the constructor (thereby avoiding potential side effects of the constructor and making a potentially big object) when letting a child inherit from the parent, see use of 'Temp' above.

Compared with the "Mixin" approach (used in jQuery and jQueryUI):

  • Easy access to superclass method implementations via our custom _parent static variable.
  • Using new is usually faster than manually copying mixins to new objects in a loop.
  • You cannot use the instanceof operator with Mixins.
  • Mixins are less memory efficient than inheritance via prototypes.


Visibility

All our object members are techically public.

We use the @constructor, @protected and @private markers that Google's JavaScript compiler understands and enforces.

We also put underscores in front of object members that are intended to be private.

Advantages over the 'closure + privileged method approach' (see e.g. Douglas Crockford, "JavaScript: The good parts") for private object members:

  • Reduced complexity for novice programmers who are not so familiar with the closure concept.
  • Approach is similar to our PHP4 compatible nomenclature for private methods in PHP.
  • Less probability to create memory leaks with closures, see http://code.google.com/speed/articles/optimizing-javascript.html
  • Better tool support (e.g. Eclipse JSDT)


Object vs. 'Class' members

There is no such thing as classes (or static methods) in JavaScript. We implement class members that do not need to be copied into each object instance (=static members) within the constructor object:

SomeConstructor = function() { ... };
SomeConstructor.staticMethod = function() { ... };

Thereby we make sure that on instantiation of that constructor with the new keyword, staticMethod will not be copied into the new object instance.

NB: Inheritance of 'static' object members is not supported!


Object member ordering

We group object members by visibility and singleton ('static') vs. instance membership in the following order in our object definitions:

  1. constructor (use @constructor annotation)
  2. private static variables (start with underscore, use @private annotation)
  3. private instance variabes (start with underscore, use @private annotation)
  4. protected instance variables (discouraged, better use private variables with protected accessors/mutators, use @protected annotation)
  5. no public static/instance variables - use public accessors/mutators instead!
  6. public static methods
  7. public methods
  8. protected static methods (use @protected annotation)
  9. protected methods (use @protected annotation)
  10. private static methods (start with underscore, use @private annotation)
  11. private methods (start with underscore, use @private annotation)

Sections are divided with a three line // style comment indicating the class member category.

You are obviously not supposed to use a member outside its scope even if the visibility is not enforced by closure. Please run lib/pkp/tools/buildjs.sh on your code to make sure that you have not overlooked anything. This is also true for protected object members. While they are named like public methods they must not be used outside of the inheritance hierarchy of the current class.


Additional Resources

Recommended Books

  • Ross Harmes and Dustin Diaz, "Pro JavaScript Design Patterns"
  • Douglas Crockford, "JavaScript: The Good Parts"

Recommended Articles