Skip to content

Instantly share code, notes, and snippets.

@aseemk
Created May 14, 2013 06:21
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aseemk/5574052 to your computer and use it in GitHub Desktop.
Save aseemk/5574052 to your computer and use it in GitHub Desktop.
A homegrown convention for shorthand static access syntax in CoffeeScript.

One of CoffeeScript's best features is the @ shorthand for this -- perfect for accessing instance methods and properties:

class Rectangle
  constructor: (@width, @height) ->
  getArea: ->
    @width * @height

But there's no similar shorthand for accessing static members, e.g. @@. So instead, you're forced to either hardcode class names, or type out the long constructor reference to be generic:

class BaseView
  @TYPE: 'base'
  toString: ->
    "#{@constructor.TYPE} view"

class ListView
  @TYPE: 'list'

Here's a homegrown convention to address this: since class bodies are executable, add a snippet at the bottom of each class (this could be a one-line call or include) that adds instance proxies for static members.

Unfortunately, the @ character isn't allowed in identifiers, but $ is. So this convention simply adds a $ prefix to all proxies. The result:

class BaseView
  @TYPE: 'base'
  toString: ->
    "#{@$TYPE} view"

class ListView
  @TYPE: 'list'

The helper code to put at the bottom of class bodies:

for prop of @
  proxy = '$' + proxy
  Object.defineProperty @::, proxy, do (prop) ->
    get: -> @constructor[prop]
    set: (val) -> @constructor[prop] = val

Feedback/thoughts/suggestions welcome!

@aseemk
Copy link
Author

aseemk commented May 14, 2013

It'd be nice to prevent overwrites of existing instance properties that happen to have $-prefixed names. (E.g. a Backbone view might store a jQuery element reference on instances with the same name as a static method?)

Thought about adding a continue if Object.getOwnPropertyDescriptor @::, proxy into the loop to address this, but this only checks one level of the prototype. Is there a way to check the whole property chain? (Edit: am I overthinking, and just continue if proxy of @:: would work?)

Though if there are collisions in naming, that makes the entire convention less useful, since you won't be able to tell at a glance whether something is a static reference or e.g. an instance jQuery element one.

Are there other characters besides $ that could make sense as a proxy prefix?

@chaosim
Copy link

chaosim commented May 25, 2013

It could be simpler as below:

class BaseView
    @TYPE: 'base'
    toString: -> "#{@$$.TYPE} view"
    Object.defineProperty @::, '$$', get: ->@constructor

class ListView extends BaseView
    @TYPE: 'list'

@$$.TYPE will be clearer than @$TYPE
And this line can be put at the begin of class body, too:
Object.defineProperty @::, '$$', get: ->@constructor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment