11

I'm learning CoffeeScript, and I've got one minor headache I haven't quite been able to figure out. If I create an object to do certain things, I occasionally need an instance variable for that object to be shared between methods. For instance, I'd like to do this:

testObject = 

  var message # <- Doesn't work in CoffeeScript.

  methodOne: ->
    message = "Foo!"

  methodTwo: ->
    alert message

However, you can't use var in CoffeeScript, and without that declaration message is only visible inside methodOne. So, how do you create an instance variable in an object in CoffeeScript?


Update: Fixed typo in my example so the methods are actually methods :)

4
  • BTW I'm aware that I could do message = "", but I really just want the variable to be null so I can set behavior based on existence rather than a more complex check to see if it's not "blank" etc. Commented Apr 12, 2012 at 21:25
  • You can also set message = null which is what you want no? Commented Apr 12, 2012 at 21:34
  • When I try message = null I get ParseError Unexpected 'TERMINATOR' Commented Apr 12, 2012 at 21:41
  • Oh yea, like the correct answer mentioned, you were assigning testObject to an object = and not a function = ()-> Commented Apr 12, 2012 at 22:02

4 Answers 4

12

You can't like that. To quote the language reference:

Because you don't have direct access to the var keyword, it's impossible to shadow an outer variable on purpose, you may only refer to it. So be careful that you're not reusing the name of an external variable accidentally, if you're writing a deeply nested function.

However what you're trying to do wouldn't be possible in JS either, it would be equivalent to

testObject = {
    var message;
    methodOne: message = "Foo!",
    methodTwo: alert(message)
}

which isn't valid JS, as you can't declare a variable in an object like that; you need to use functions to define methods. For example in CoffeeScript:

testObject =
    message: ''
    methodOne: ->
        this.message = "Foo!"
    methodTwo: ->
        alert message

You can also use @ as a shortcut for 'this.', i.e. @message instead of this.message.

Alternatively consider using CoffeeScript's class syntax:

class testObject
    constructor: ->
        @message = ''

    methodOne: ->
        @message = "Foo!"

    methodTwo: ->
        alert @message
Sign up to request clarification or add additional context in comments.

Comments

5

Just to add to @Lauren's answer, what you wanted is basically the module pattern:

testObject = do ->

  message = null

  methodOne = ->
    message = "Foo!"

  methodTwo = ->
    alert message

  return {
    methodOne
    methodTwo
  }

Where message is a "private" variable only available to those methods.

Depending on the context you could also declare message before the object so that it's available to both methods (if executed in this context):

message = null

testObject = 
  methodOne: -> message = "Foo!"
  methodTwo: -> alert message

2 Comments

Correct, but your code is a bit buggy: do will simply create a closure, you therefore cannot define properties but should use vars instead (methodOne = ->... etc.) Also, the return statement should probably be {methodOne:methodOne, methodTwo:methodTwo}. Of course you could put your method definitions right into the return statement instead...
@JulianD. copy&pasta :) The return statement is using destructuring assignment.
1

You can define the property with:

message: null

But, you aren't currently defining methods -- you need -> for that.

Then, to refer to instance properties within the methods, prefix the property names with @.

testObject = 

  message: null

  methodOne: ->
    @message = "Foo!"

  methodTwo: ->
    alert @message

4 Comments

-> is not required: see my fixed version
@KristofferSHansen your version isn't fixed; as you can see by pressing 'Run' on that page, it would show an alert dialog immediately, and that is probably not what Andrew is after, more likely he wants to defer its execution until that method is called.
@KristofferSHansen It is for function/methods. Without it, methodTwo is set to the result of calling alert, not a function that in turn calls alert.
Thanks for catching the typo, I fixed it. My real code had the ->.
0

Use @ to point to this

testObject = 

  methodOne: ->
    @message = "Foo!"

  methodTwo: ->
    alert @message

fixed version on coffeescript.org

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.