javascript - CoffeeScript:对象初始化器中的 Getter/Setter

标签 javascript oop coffeescript getter-setter ecmascript-5

ECMAScript 允许我们如下定义 getter 或 setter:

[文本/javascript]

var object = {
  property: 7,
  get getable() { return this.property + 1; },
  set setable(x) { this.property = x / 2; }
};

如果我使用的是,我可以变通:

[文本/coffeescript]

"use strict"

Function::trigger = (prop, getter, setter) ->
      Object.defineProperty @::,
              get: getter
              set: setter               

class Class
      property: ''

      @trigger 'getable', ->
               'x'

      member: 0

但是如果我想直接在对象上定义触发器 - 使用defineProperty/-ies。我想做类似的事情(那样行不通):

[文本/x-伪 CoffeeScript ]

object =
  property: 'xhr'
  get getable: 'x'

它在 JavaScript 中运行没有任何问题,我不希望我的脚本在使用 CoffeeScript 时退化。有没有办法像在 JavaScript/ECMAScript 中那样轻松地做到这一点?谢谢。

最佳答案

不,暂时不会:(

来自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.

关于 getter 和 setter 语法的一些 GitHub 问题:#64 , #451 , #1165 (在最后一个中有一些很好的讨论)。

我个人认为,既然 definePropertypart of the ECMAScript standard,拥有 getter 和 setter 文字语法将是 CoffeeScript 的一个不错的选择加入功能. JavaScript 中对 getter 和 setter 的需求可能值得怀疑,但您不会仅仅因为它们存在就被迫使用它们。


无论如何,如您所见,实现调用 Object.defineProperty 进行类声明的便捷包装函数并不难。我个人会使用 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

或者,也许创建两种不同的方法:

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 ;))作为 Jason proposed .也许将其包装在一个小函数中:

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

关于javascript - CoffeeScript:对象初始化器中的 Getter/Setter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11587231/

相关文章:

javascript - 单击字段后,IE失去焦点

javascript - 如何在 Fabric.js 中为文本添加 CSS 属性

c++ - 同时为类及其成员继承和多态(shared_ptr,C++11)

Java类继承自引用类

Javascript OOP 和继承技术

python - 如何在 Python 包的 distutils 安装的构建阶段编译 CoffeeScript?

javascript - jquery如何统计子李

javascript - Angular:一种识别服务调用者的方法

Javascript 代理 : node-proxy, 和谐,混合对象与神奇的 getter 和 setter ......在 Coffeescript 中?

haskell - 在 CoffeeScript 中处理无限列表