简体   繁体   English

CoffeeScript中的方法调用语法

[英]Method Call Syntax in CoffeeScript

I'm new to CoffeeScript, and I seem to be having trouble with the syntax for calling methods. 我是CoffeeScript的新手,似乎在调用方法的语法方面遇到麻烦。

Here's the Card model: 这是Card模型:

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' 这给了我错误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. 具体来说,我想知道是否对Card的rows方法使用了不正确的语法,还是只是误解了一些东西。 Thanks in advance! 提前致谢!

Update: 更新:

For some reason, @card.property always works fine, but @card.any_method() never does. 出于某种原因, @card.property始终可以正常工作,但是@card.any_method()永远无法工作。 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: 更新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. 我正在使用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()

Your method calling syntax is correct. 您的方法调用语法正确。 The relevant rules for CoffeeScript are: CoffeeScript的相关规则是:

  • 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: 要查看其工作原理,请尝试在CoffeeScript网站上的“ Try CoffeeScript”编辑器上运行以下代码:

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. 由于您的方法调用语法正确,因此问题似乎可能是@card变量不是exports.Card类的实例。

The problem is that pip isn't a property of the Card instance; 问题在于, pip不是Card实例的属性; it's a property of Card::defaults , so Backbone then makes it an attribute of the Card instance—not a property . 它是Card::defaults的属性,因此Backbone使其成为Card实例的属性 ,而不是property You can access the pip attribute with 您可以使用以下方式访问pip属性

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. 产生这种区别的原因是,在JavaScript中,无法监视属性的更改,而Backbone则需要这样做来更改事件。 (If you modify pip with card.set 'pip' , then Backbone fires a "change" event, for instance.) (例如,如果您使用card.set 'pip'修改了pip ,则Backbone会触发"change"事件。)

So, your code should work fine if you just change the last line of the rows method: 因此,如果您仅更改rows方法的最后一行,您的代码应该可以正常工作:

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.) 注意:某些 JS环境中支持card.pip = ... / setter方法,这将允许您将card.pip = ...映射到card.set 'pip', ...此处查看John Resig的文章card.set 'pip', ...不使用这种方法,因为它旨在与所有现代浏览器兼容。)

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: 最终弄清楚了-我忘记了模板中引用的@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())
    @

Now it makes sense why only variables were working and not methods -- @card was actually a JSON representation of the model instance. 现在就可以理解为什么只有变量而不是方法@card了- @card实际上是模型实例的JSON表示形式。

Thanks for all the suggestions/clarifications guys--sorry for the dumb mistake :P 感谢您的所有建议/澄清-很抱歉您的愚蠢错误:P

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM