CoffeeScript 中的方法调用语法

发布于 2024-12-01 21:33:18 字数 1558 浏览 0 评论 0原文

我是 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 #;没有方法 '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()

I'm new to CoffeeScript, and I seem to be having trouble with the syntax for calling methods.

Here's the Card model:

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

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

And the relevant portion of the template:

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

which is giving me the error Uncaught TypeError: Object #<Object> has no method 'rows'

Specifically, I'm wondering if I'm using incorrect syntax for the rows method of Card or if I'm just misunderstanding something. Thanks in advance!

Update:

For some reason, @card.property always works fine, but @card.any_method() never does. I've gotten around this at the moment by using properties, but I'd love it if someone was able to explain this behavior. Thanks again!

Update 2:

I'm using http://brunchwithcoffee.com if it's a help to anyone, and here's the main.coffee file to show how the @card instance is being created and passed to the view.

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()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情仇皆在手 2024-12-08 21:33:18

您的方法调用语法是正确的。 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 类的实例。

Your method calling syntax is correct. The relevant rules for CoffeeScript are:

  • Parenthesis are optional for method calls invoked with arguments ie

    object.method 1,2 
    

    or

    object.method(1,2)
    
  • Parenthesis are required for method calls invoked with no arguments ie

    object.method()
    

To see how this works try running the following code on the 'Try CoffeeScript' editor on the CoffeeScript site:

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

(new A()).method();

Since your method call syntax is correct it seems likely that the problem is that the @card variable is not an instance of the exports.Card class.

許願樹丅啲祈禱 2024-12-08 21:33:18

问题是 pip 不是 Card 实例的属性;它是 Card::defaults 的属性,因此 Backbone 将其设为 Card 实例的属性,而不是属性嗯>。 访问 pip 属性

card.get 'pip'

您可以使用或直接

card.attributes.pip

。这种区别的原因是,在 JavaScript 中,无法监视属性的更改,而 Backbone 需要执行此操作才能分派事件。 (例如,如果您使用 card.set 'pip' 修改 pip,则 Backbone 会触发 “change” 事件。)

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

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

注意:某些 JS 环境支持 Getters/setters,这将允许你绘制地图card.pip = ...card.set 'pip', ... 请参阅 John Resig 的文章 这里。Backbone 不使用这种方法,因为它的目标是与所有现代浏览器兼容。)

The problem is that pip isn't a property of the Card instance; it's a property of Card::defaults, so Backbone then makes it an attribute of the Card instance—not a property. You can access the pip attribute with

card.get 'pip'

or directly as

card.attributes.pip

The reason for this distinction is that, in JavaScript, there's no way to monitor a property for changes, which Backbone needs to do in order to dispatch events. (If you modify pip with card.set 'pip', then Backbone fires a "change" event, for instance.)

So, your code should work fine if you just change the last line of the rows method:

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

(Note: Getters/setters are supported in some JS environments, which would allow you to map card.pip = ... to card.set 'pip', ... See John Resig's article on it here. Backbone doesn't use this approach because it aims to be compatible with all modern-ish browsers.)

回忆躺在深渊里 2024-12-08 21:33:18

终于弄清楚了——我忘记了模板中引用的 @card 变量并非源自 main.coffee 文件——它实际上被转换为 JSON在 CardView 中:

cardTemplate = require('templates/card')

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

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

现在可以理解为什么只有变量起作用而不是方法了 - @card 实际上是模型实例的 JSON 表示形式。

感谢大家的所有建议/澄清——很抱歉犯了愚蠢的错误:P

Finally figured it out--I forgot that the @card variable referenced in the template didn't originate from the main.coffee file--it was actually being converted into JSON in the CardView here:

cardTemplate = require('templates/card')

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

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

Now it makes sense why only variables were working and not methods -- @card was actually a JSON representation of the model instance.

Thanks for all the suggestions/clarifications guys--sorry for the dumb mistake :P

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文