There's been plenty of discussion in the CoffeeScript community about the value and viability of adding getter and setter syntax for Object
properties.
For the Javascript background, see the MDN articles on the get
and set
operators and their guide to working with objects.
On the CoffeeScript side, see the discussion in issues #64, #451, and #1165.
The gist of this discussion is that syntactic support is unlikely in
CoffeeScript. However, there are ways to implement similar functionality using
Object.defineProperty
.
What follows is a light edit of a stackoverflow answer I came across that demonstrates how you might do so. Hat tip to @epidemian!
It's not that hard to implement a convenient wrapper function that calls Object.defineProperty
for class declarations. Here's one approach:
Function::property = (prop, desc) ->
Object.defineProperty @prototype, prop, desc
class Name
constructor: (@first, @last) ->
@property 'name',
get: -> "#{@first} #{@last}"
set: (name) -> [@first, @last] = name.split ' '
{ok} = require 'assert'
p = new Name 'Bob', 'Jones'
ok p.name is 'Bob Jones'
p.name = 'Bob Smith'
ok p.last is 'Smith'
Alternatively, 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 Name
constructor: (@first, @last) ->
@getter 'name', -> "#{@first} #{@last}"
@setter 'name', (name) -> [@first, @last] = name.split ' '
For plain objects you can just use Object.defineProperty
(or Object.defineProperties
) on the object itself or wrap it in a utility 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
ok rectangle.area is 12
rectangle.width = 5
ok rectangle.area is 15