Kyle G
Kyle G

Reputation: 35

Coffeescript: Calling array functions from a function in the same object

I'm trying to write a package for the Atom text editor, and in my main class (init.coffee), I have an array inside of my module.exports:

servers: []

I want to access this array from a function in another part of the module.exports, but I'm having trouble.

Function:

stas: () ->
    dir = getFilePath()
    d = fs.statSync dir
    if !d.isDirectory()
        dirError dir
    else
        s = new Server dir
        s.init()
        @servers.push s
    return

I keep getting this error:

Uncaught TypeError: this.servers.push is not a function

I call the function like this:

@events.add atom.commands.add ".tree-view", {
  'atom-together:startServer': @stas
  'atom-together:startClient': @stac
  'atom-together:stopServer': @stos
  'atom-together:stopClient': @stoc
}

What is the correct way to call this array in coffeescript?

Upvotes: 0

Views: 120

Answers (1)

mu is too short
mu is too short

Reputation: 434615

The value of this (AKA @) inside a JavaScript/CoffeeScript function usually depends on how it is called, not where it is defined. Also, @stas is just a reference to the stas function and this will be whatever the caller wants it to be when that function gets called.

If you need a specific @ (AKA this) in a callback function, then either define it as a bound function:

stas: () => # Note the => instead of ->
  #...

or bind it using Function.prototype.bind when you pass it to the event system:

@events.add atom.commands.add ".tree-view", {
  'atom-together:startServer': @stas.bind(@)
  #...
}

Also, if you're defining servers: [] at the class level like this:

class C
  servers: []

then you are sharing that one servers array among all instances of your class and that might not be what you want. Things defined at the class level are shared through the prototype among all instances. For example:

class C
  a: [ ]

c1 = new C
c2 = new C
c1.a.push 11
console.log c1.a, c2.a

will put two [11]s in the console because c1.a and c2.a are the same array. You're generally better off defining mutable values in your constructor to avoid this sharing (unless you specifically want it to happen); this version:

class C
  constructor: (@a = [ ]) ->

c1 = new C
c2 = new C
c1.a.push 11
console.log c1.a, c2.a

would give you [11] and [] in the console and that's usually the behavior you're looking for.

Upvotes: 3

Related Questions