不,暂时没有:(
来自CoffeeScript 常见问题解答:
问:您会在功能 X 依赖于平台的情况下添加功能 X 吗?
答:不可以,不允许将特定于实现的功能作为策略。您在 CoffeeScript 中编写的所有内容都应该在任何当前的 JavaScript 实现上得到支持和运行(实际上,这意味着最低的公分母是 IE6)。因此,将不会实现以下功能:getter & setter、yield。
一些关于 getter 和 setter 语法的 GitHub 问题:#64、#451、#1165(最后一个有一些很好的讨论)。
我个人认为拥有 getter 和 setter 文字语法对于 CoffeeScript 来说是一个不错的选择加入功能,因为它defineProperty
是ECMAScript 标准的一部分。JavaScript 中对 getter 和 setter 的需求可能值得怀疑,但您不会因为它们存在而被迫使用它们。
无论如何,正如您所注意到的,实现一个调用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 ' '
对于普通对象,您可以按照Jason 的建议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