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!
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 justcontinue 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?