Нет, пока нет :(
Из часто задаваемых вопросов по CoffeeScript:
В: Будете ли вы добавлять функцию X, если функция X зависит от платформы?
О: Нет, функции, зависящие от реализации, не разрешены в качестве политики. Все, что вы пишете на CoffeeScript, должно поддерживаться и запускаться в любой текущей реализации JavaScript (на практике это означает, что наименьший общий знаменатель — IE6). Таким образом, не будут реализованы такие функции, как следующие: геттеры и сеттеры, yield.
Некоторые проблемы GitHub с синтаксисом геттера и сеттера: #64, #451, #1165 (в последнем есть хорошее обсуждение).
Лично я считаю, что наличие литерального синтаксиса getter & setter было бы неплохой возможностью для CoffeeScript теперь, когда defineProperty
часть стандарта ECMAScript. Необходимость геттеров и сеттеров в JavaScript может быть сомнительной, но вы не обязаны использовать их только потому, что они существуют.
В любом случае, как вы заметили, не так уж сложно реализовать удобную функцию-оболочку, которая вызывает Object.defineProperty
для объявлений классов. Лично я бы использовал подход, предложенный в здесь:
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
Или, возможно, создайте два разных метода:
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 ' '
Для простых объектов вы можете просто использовать Object.defineProperty
(или Object.defineProperties
; )) на самом объекте, как предложил Джейсон. Возможно, оберните это в небольшую функцию:
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
person
epidemian
schedule
21.07.2012