【问题标题】:Method Call Syntax in CoffeeScriptCoffeeScript 中的方法调用语法
【发布时间】:2011-08-27 09:03:23
【问题描述】:

我是 CoffeeScript 新手,我似乎在调用方法的语法方面遇到了问题。

这是卡片模型:

class exports.Card extends Backbone.Model
  defaults:
    pip:   '4'
    suit:  '♠'
    color: 'b'

  rows: ->
    rows =
      '4': [2, 0, 2]
    rows[@pip]

以及模板的相关部分:

<ul class="col cols-<%= @card.rows()[0] %>">

这给了我错误Uncaught TypeError: Object #&lt;Object&gt; has no method 'rows'

具体来说,我想知道我是否对 Card 的 rows 方法使用了不正确的语法,或者我只是误解了某些东西。提前致谢!

更新:

出于某种原因,@card.property 总是可以正常工作,但 @card.any_method() 永远不会。目前我已经通过使用属性解决了这个问题,但如果有人能够解释这种行为,我会很高兴。再次感谢!

更新 2:

如果它对任何人都有帮助,我会使用 http://brunchwithcoffee.com,这里是 main.coffee 文件,用于显示如何创建 @card 实例并将其传递给视图。

window.app = {}
app.routers = {}
app.models = {}
app.collections = {}
app.views = {}

Card = require('models/card_model').Card
MainRouter = require('routers/main_router').MainRouter
HomeView = require('views/home_view').HomeView
CardView = require('views/card_view').CardView

# app bootstrapping on document ready
$(document).ready ->
  app.initialize = ->
    app.routers.main = new MainRouter()
    app.views.home = new HomeView()
    app.views.card = new CardView(model: new Card(color: 'r', suit: '♥', pip: '7'))
    app.routers.main.navigate 'home', true if Backbone.history.getFragment() is ''
  app.initialize()
  Backbone.history.start()

【问题讨论】:

  • @card 是如何创建的?作为new exports.Card?是否通过@card instanceof exports.Card的测试?
  • 更新以显示@card 是如何创建的
  • 风格提示:你可以写{Card} = require 'models/card_model'而不是Card = require('models/card_model').Card

标签: javascript syntax backbone.js coffeescript


【解决方案1】:

您的方法调用语法是正确的。 CoffeeScript 的相关规则是:

  • 括号对于使用参数调用的方法调用是可选的,即

    object.method 1,2 
    

    object.method(1,2)
    
  • 无参数调用的方法调用需要括号

    object.method()
    

要查看其工作原理,请尝试在 CoffeeScript 网站上的“Try CoffeeScript”编辑器上运行以下代码:

class A
  method: ->
    console.log "A"

(new A()).method();

由于您的方法调用语法是正确的,问题似乎在于@card 变量不是exports.Card 类的实例。

【讨论】:

  • 嗯,我真的很困惑——@card 绝对是 Card 类的一个实例,因为我可以安全地访问视图中的前一行之一 &lt;%= @card.pip %&gt;跨度>
  • 你是对的——@card 实际上是我认为的 toJSON() 等价物
【解决方案2】:

问题是pip 不是Card 实例的属性;它是Card::defaults 的一个属性,因此Backbone 将它设为Card 实例的属性——而不是属性。您可以使用

访问pip属性
card.get 'pip'

或直接作为

card.attributes.pip

这种区别的原因是,在 JavaScript 中,没有办法监控属性的变化,而 Backbone 需要这样做才能调度事件。 (例如,如果您将 pip 修改为 card.set 'pip',则 Backbone 会触发 "change" 事件。)

因此,如果您只更改 rows 方法的最后一行,您的代码应该可以正常工作:

rows: ->
  rows =
    '4': [2, 0, 2]
  rows[@get 'pip']

(注意: 一些 JS 环境支持 Getter/setter,这将允许您将 card.pip = ... 映射到 card.set 'pip', ... 请参阅 John Resig 的文章@ 987654321@。Backbone 没有使用这种方法,因为它旨在与所有现代浏览器兼容。)

【讨论】:

  • 感谢对属性与属性的澄清,但在 @card 上调用任何方法时,我仍然收到“没有方法”错误
【解决方案3】:

终于弄明白了——我忘了​​模板中引用的@card变量不是来自main.coffee文件——它实际上是在CardView中转换成JSON的:

cardTemplate = require('templates/card')

class exports.CardView extends Backbone.View
  tagName:   'div'
  className: 'card'

  render: ->
    $(@el).html cardTemplate(card: @model.toJSON())
    @

现在,为什么只有变量起作用而不是方法起作用是有道理的——@card 实际上是模型实例的 JSON 表示。

感谢所有建议/澄清家伙-抱歉愚蠢的错误:P

【讨论】:

    猜你喜欢
    • 2015-06-18
    • 2011-12-23
    • 1970-01-01
    • 2014-11-05
    • 2011-10-22
    • 1970-01-01
    • 1970-01-01
    • 2013-07-14
    • 2012-05-07
    相关资源
    最近更新 更多