0

[更新]我的问题可能不够清楚......进一步澄清我想要完成的事情:

我检索这样的对象:

p =
  name:
    first: 'alan'
    last: 'smith'

并希望创建一个结构(一个类,多个类?)最终能够编写这样的东西:

person.name # alan smith
person.name.toCap() #Alan Smith
person.name.first # alan
person.name.first.toCap() # Alan
person.name.last # smith
person.name.last.toCap() # Smith
...

所以 :

  1. 有没有办法同时拥有 person.name 和 person.name.first ?
  2. 有没有更好的方法来使用方法扩展对象属性而不是扩展像String这样的原生类型?

[原来的]

在咖啡中寻找正确的方法:

console.log person.name.last #smith
console.log person.name.last.capitalize() # SMITH
console.log person.name.last.initial() # S

我想出了以下解决方案,但想确保这是要走的路...

String::toCap = (remainingToLower=false) -> 
  @[0].toUpperCase() + if remainingToLower then @[1..-1].toLowerCase() 
                                           else @[1..-1]
Number::random = (percent) ->
  offset = @ * percent / 100
  parseInt(Math.floor(Math.random() * 2 * offset) + @ - offset)

class Name
  constructor: (@first, @last) ->

class Person
  constructor: (@name, @age) ->
  toString: () => "#{@name.first.toCap(true)} #{@name.last.toCap(true)} 
                  (#{@age.random(25)})"

# GO --------------------------->

p = new Person(new Name, 18)
p.name.first = 'alaN'
p.name.last = 'smith'

console.log "#{p.toString()}"

感谢您的反馈意见。

戳这里

4

1 回答 1

0

上下文
我有这个原始数据:

data =
  name:
    first: 'alan'
    last: 'smith'  
  age: 18  
  address: [  
    {  
      name: 'work'  
      street: '1600 amphitheatre parkway'  
      city: 'mountain view'  
      zip: 'CA 94043'  
    },{  
      name: 'home'  
      street: '1 infinite loop'  
      city: 'cupertino'  
      zip: 'CA 95014'  
    }]  

并想创建一个结构来操纵我的数据,如下所示:

p = New Person(data)
console.log """
  #{p}                        # alan smith (18), 2 address lines
  #{p.name},                  # alan smith
  #{p.name.first},            # alan
  #{p.address}                # 2 address lines
  #{p.address.work}           # 1600 amphitheatre parkway, mountain view, CA 94043
  #{p.address.work.street}    # 1600 amphitheatre parkway
"""

此外,我希望能够将自定义方法应用于任何成员。例如,假设 toCap() 是一个将 String 的每个单词大写的方法:

console.log """
  #{p.name.toCap()},                # Alan Smith
  #{p.name.first.toCap()}           # Alan
  #{p.address.work.toCap()}         # 1600 Amphitheatre Parkway, Moutain View, CA 94043
  #{p.address.work.street.toCap()}  # 1600 Amphitheatre Parkway  
"""

解决方案(请参阅此Plunk以获取完整代码)

  • 使用嵌套类

    class Person
      constructor: (data) ->
        @name = new Name(data.name)
        @address = new AddressList(data.address)
    
  • 动态创建成员

    class AddressList
      constructor: (list) ->    
        @[addr.name] = new Address(addr) for addr in list    
    
  • 包装您的属性或使用基类而不是扩展本机对象

    class StringProperty
      constructor: (@_value) ->
      toString: => 
        @_value
      toCap: (remainingToLower=false) =>
        _words = @_value.split ' '
        (@_toCap(w,remainingToLower) for w in _words).join ' '     
      _toCap : (s, r) ->
        s[0].toUpperCase() + if r then s[1..-1].toLowerCase() else s[1..-1]
    

    ...并直接使用它们...

    class Name
      constructor: (name) ->
        @first = new StringProperty(name.first)
        @last = new StringProperty(name.last)
      toString: =>
        "#{@first} #{@last}"
      toCap: =>
        "#{@first.toCap()} #{@last.toCap()}"
    

    ...或动态创建成员:

    @[k] = new StringProperty(data[k]) for k of data when k in Address.fields
    
  • 不要忘记像上面那样覆盖 toString()

于 2013-02-11T22:21:59.850 回答