CoffeeScript: Getter/Setter in Object Initializers

No, not for now 🙁

From the CoffeeScript FAQ:

Q: Will you add feature X where feature X depends on a platform?

A: No, implementation-specific features are not allowed as a policy. Everything that you write in CoffeeScript should be supported and runnable on any current JavaScript implementation (in practice, this means the lowest common denominator is IE6). Thus, features such as the following will not be implemented: getters & setters, yield.

Some GitHub issues about getter & setter syntax: #64, #451, #1165 (there is some nice discussion in the last one).

I personally think that having getter & setter literal syntax would be a nice opt-in feature for CoffeeScript now that defineProperty is part of the ECMAScript standard. The need for getters & setters in JavaScript can be questionable, but you’re not forced to use them just because they exist.


Anyway, as you noticed, it’s not that hard to implement a convenient wrapper function that calls Object.defineProperty for class declarations. I personally would use the approach suggested in here:

Function::property = (prop, desc) ->
  Object.defineProperty @prototype, prop, desc

class Person
  constructor: (@firstName, @lastName) ->
  @property 'fullName',
    get: -> "#{@firstName} #{@lastName}"
    set: (name) -> [@firstName, @lastName] = name.split ' '

p = new Person 'Robert', 'Paulson'
console.log p.fullName # Robert Paulson
p.fullName="Space Monkey"
console.log p.lastName # Monkey

Or, maybe create two different methods:

Function::getter = (prop, get) ->
  Object.defineProperty @prototype, prop, {get, configurable: yes}

Function::setter = (prop, set) ->
  Object.defineProperty @prototype, prop, {set, configurable: yes}

class Person
  constructor: (@firstName, @lastName) ->
  @getter 'fullName', -> "#{@firstName} #{@lastName}"
  @setter 'fullName', (name) -> [@firstName, @lastName] = name.split ' '

For plain objects you can just use Object.defineProperty (or Object.defineProperties 😉 ) on the object itself as Jason proposed. Maybe wrap that in a little function:

objectWithProperties = (obj) ->
  if obj.properties
    Object.defineProperties obj, obj.properties
    delete obj.properties
  obj

rectangle = objectWithProperties
  width: 4
  height: 3
  properties:
    area:
      get: -> @width * @height

console.log rectangle.area # 12
rectangle.width = 5
console.log rectangle.area # 15

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)