Skip to content

Instantly share code, notes, and snippets.

@joyrexus
Created June 25, 2014 21:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joyrexus/65cb3780a24ecd50f6df to your computer and use it in GitHub Desktop.
Save joyrexus/65cb3780a24ecd50f6df to your computer and use it in GitHub Desktop.
Getters and Setters for CS

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

Getters and Setters

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment