0

I am playing around with CoffeeScript and the 'class' keyword, ended up with the following:

var Foo, foobar;

Foo = (function() {
  function Foo() {}

  Foo.bar = 7;

  return Foo;

})();

foobar = new Foo;

alert(foobar.bar);

after typing in:

class Foo
  @bar = 7


foobar = new Foo

alert foobar.bar

I kind of expected bar to retain that value but the alert pops up as undefined

MetaGuru
  • 42,847
  • 67
  • 188
  • 294
  • If you're interested in JavaScript prototype and constructor functions in JavaScript I've written an introduction here: http://stackoverflow.com/a/16063711/1641941 Why the value of Foo is provided by an IIFE is because you may want to use closure values. In this case it is redundant because you don't have any. – HMR Nov 19 '13 at 03:25

2 Answers2

2

bar is a property of Foo (the function), not instances it creates.

If you want bar on instances, you have two choices:

  1. Set it within the constructor:

    class Foo
      constructor: () ->
        @bar = 7
    
    foobar = new Foo
    
    alert foobar.bar
    

    Which translates to this JavaScript:

    var Foo, foobar;
    
    Foo = (function() {
      function Foo() {
        this.bar = 7;
      }
    
      return Foo;
    
    })();
    
    foobar = new Foo;
    
    alert(foobar.bar);
    
  2. Or set it on the prototype:

    class Foo
      bar: 7
    
    foobar = new Foo
    
    alert foobar.bar
    

    which translates to:

    var Foo, foobar;
    
    Foo = (function() {
      function Foo() {}
    
      Foo.prototype.bar = 7;
    
      return Foo;
    
    })();
    
    foobar = new Foo;
    
    alert(foobar.bar);
    
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • oh duh... I need to use `this` instead right? ...no that didn't work either – MetaGuru Nov 18 '13 at 22:05
  • No: what you need is remedial Javascript. If bar is a property of Foo, it would be accessible as `Foo.bar` – Dexygen Nov 18 '13 at 22:07
  • @GeorgeJempty: I believe he/she is looking for the CoffeeScript syntax. – T.J. Crowder Nov 18 '13 at 22:08
  • @GeorgeJempty ah yes, I am not familiar with the JavaScript that CoffeeScript is writing for me... glad I found it though now I am forced to learn! – MetaGuru Nov 18 '13 at 22:08
  • @T.J.Crowder so what I am seeing here is... Foo equals a call to the function inside of it which returns the Foo function... right? so many layers @.@ – MetaGuru Nov 18 '13 at 22:10
  • @ioSamurai: I've added two options depending on what you want to do. :-) – T.J. Crowder Nov 18 '13 at 22:11
  • Note that both options he's given have the same end-result. – nzifnab Nov 18 '13 at 22:12
  • @nzifnab: Not *quite*, but the difference isn't major. – T.J. Crowder Nov 18 '13 at 22:15
  • @T.J.Crowder doesn't the `(function() { ... })();` part seem redundant if it's just setting Foo to the function Foo()? I am guessing this is one of CoffeeScripts 'safety' features? – MetaGuru Nov 18 '13 at 22:18
  • 1
    @ioSamurai: It's so that if you add further functions to the `Foo` prototype, they get defined at the same time as `Foo`. Function *declarations* are hoisted, and so they don't occur in the step-by-step order of code, but assignments to properties on (say) `Foo.prototype` *do* occur within the step-by-step order of code. So CoffeeScript is ensuring both happen at the same time (in the step-by-step execution of the code), for instance as with [this](http://coffeescript.org/#try:class%20Animal%0A%20%20foo%3A%20(%40bar)%20-%3E%0A%20%20%20%20console.log(%40bar)%3B). – T.J. Crowder Nov 18 '13 at 22:23
1

Try this:

class Foo
  constructor: ->
    @bar = 7

foobar = new Foo()
alert foobar.bar

The problem is that when you're at the class-level @ is referring to Foo. So in your example Foo.bar == 7, but it's not setting anything on instances (which you can do in the constructor).

nzifnab
  • 15,876
  • 3
  • 50
  • 65