CoffeeScript的:吸气/在对象初始化二传手(CoffeeScript: Getter/Se

2019-06-26 11:19发布

ECMAScript中允许我们定义的getter或固定架如下:

[文本/ 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的? 谢谢。

Answer 1:

不,不是现在:(

从CoffeeScript的常见问题 :

问:你们会添加功能X,其中特征X依赖的平台上?

答:不,实现特定的功能,不允许作为一个政策。 您在CoffeeScript中写的一切应该得到支持和可运行于任何现有的JavaScript实现(在实践中,这意味着最低的共同点是IE6)。 因此,功能,如以下将不被实施:吸气剂&setter方法,产率。

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

我个人认为有吸气和二传手文字语法将是一个不错的选择,在功能的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 ' '

对于普通的对象,你可以只使用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


Answer 2:

下面是定义在CoffeeScript的getter和setter维持一个相对干净的语法,而不添加任何全局函数原型(我宁愿不做)性能的另一种方法:

class Person
  constructor: (@firstName, @lastName) ->
  Object.defineProperties @prototype,
    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

它具有许多特性效果很好。 例如,下面是在的(X,Y,宽度,高度)来定义一矩形类,但是对于另一种表示(X1,Y1,X2,Y2)提供访问器:

class Rectangle                                     
  constructor: (@x, @y, @w, @h) ->
  Object.defineProperties @prototype,
    x1:
      get: -> @x
      set: (@x) ->
    x2:
      get: -> @x + @w
      set: (x2) -> @w = x2 - @x
    y1:
      get: -> @y
      set: (@y) ->
    y2:
      get: -> @y + @h
      set: (y2) -> @w = y2 - @y

r = new Rectangle 5, 6, 10, 11
console.log r.x2 # 15

下面是相应的JavaScript代码 。 请享用!



Answer 3:

您可以直接JSON对象使用Object.defineProperty为好。

obj = {}
Object.defineProperty obj, 'foo',
    get: ->
        return 'bar'

get / set方法符号并不在CoffeeScript中各种原因的工作。 编译器尚未建成考虑的get / set符号的最大福祉。

需要注意的是获取/设置不被所有的浏览器(特别是IE)的支持。 还要注意的是,新的ECMA标准(ECMAScript5)提到Object.defineProperty的定义与getter / setter方法属性的方式。



Answer 4:

像@curran,我宁愿不修改Function的原型。 这是我在我的项目之一做:

定义某处这对于一个给定的类返回2个功能,让您可以轻松地添加对类的原型getter和setter方法的效用函数:

gs = (obj) ->
  getter: (propName, getterFunction) ->
    Object.defineProperty obj.prototype, propName, 
      get: getterFunction
      configurable: true
      enumerable: true
  setter: (propName, setterFunction) ->
    Object.defineProperty obj.prototype, propName, 
      set: setterFunction
      configurable: true
      enumerable: true

GS代表对于G埃特和s埃特。

然后,你建立并导入配置类的程序有两个功能:

class Dog
  { getter, setter } = gs @

  constructor: (name, age) -> 
    @_name = name
    @_age = age

  getter 'name', -> @_name
  setter 'name', (name) -> 
    @_name = name
    return

  getter 'age', -> @_age
  setter 'age', (age) -> 
    @_age = age
    return


Answer 5:

另一种方法:

get = (self, name, getter) ->
  Object.defineProperty self, name, {get: getter}

set = (self, name, setter) ->
  Object.defineProperty self, name, {set: setter}

prop = (self, name, {get, set}) ->
  Object.defineProperty self, name, {get: get, set: set}

class Demo 
  constructor: (val1, val2, val3) ->
    # getter only
    get @, 'val1', -> val1
    # setter only
    set @, 'val2', (val) -> val2 = val
    # getter and setter
    prop @, 'val3', 
      get: -> val3
      set: (val) -> val3 = val


Answer 6:

由于之前已经走了别人。 非常普遍和简单的:

attribute = (self, name, getterSetterHash) ->
  Object.defineProperty self, name, getterSetterHash

class MyClass
  constructor: () ->
    attribute @, 'foo',
      get: -> @_foo ||= 'Foo' # Set the default value
      set: (who) -> @_foo = "Foo #{who}"

    attribute @, 'bar',
      get: -> @_bar ||= 'Bar'

    attribute @, 'baz',
      set: (who) -> @_baz = who


myClass = new MyClass()
alert(myClass.foo) # alerts "Foo"
myClass.foo = 'me' # uses the foo setter
alert(myClass.foo) # alerts "Foo me"


文章来源: CoffeeScript: Getter/Setter in Object Initializers