为什么实例方法不起作用?

时间:2016-12-22 00:07:28

标签: coffeescript

我正在学习coffescript。我想要一个实例方法(@generate_human)在课程的每个瞬间完成时运行,但是我得到的错误是该函数不存在。当我将方法改为类方法时,一切正常。发生了什么事?

class Human  # As biological creature
    constructor: (@given_sex = null,
                  @age = null,  # Age of the person
                  @max_age = 85) ->  # Maximum allowed age of the person during person generation


        _alive = true

        alive: ->
            @_alive

        dead: ->
            not @alive()

        has_died: ->
            @_alive = false

        _available_sexes: {0: 'female', 1: 'male'}

        sex: ->
            _sex = @_available_sexes[@given_sex]

        generate_human: ->
            @_alive = true
            if @age is null
                @age = Math.floor(Math.random() * @max_age)
            if @given_sex is null
                @given_sex = Math.floor(Math.random() * 2)
            else if @given_sex not in [0,1]
                n = @given_sex
                err = 'Invalid sex value: ' + n
                console.log(err)
                throw new Error(err)

         @generate_human()  # In JavaScript this line throws an error that function 'this.generate_human()' does not exist

h = new Human()

1 个答案:

答案 0 :(得分:0)

在班级,@(AKA this)是班级本身。当你这样说:

class C
  @m()

@中的@m()将引用类本身,而不是类的实例。如果你看看JavaScript版本,你应该看看发生了什么:

var C = (function() {
  function C() {}
  C.m(); // <---------- This is the @m() call.
  return C;
})();

这与定义类方法的语法一致:

class C
  @m: ->

成为这个JavaScript:

var C = (function() {
  function C() {}
  C.m = function() {}; // <--------- Here is the class method.
  return C;
})();

如果您希望在创建实例时运行该方法,请在constructor中调用它:

class Human
  constructor: (@given_sex = null, @age = null, @max_age = 85) ->
    @generate_human()
  #...

您可能想要查看CoffeeScript对_alive = true所做的事情,但没有定义默认的@_alive实例变量,实际上是private class variable of sorts;你可能想要_alive: true

此外,您应该非常小心并且与CoffeeScript中的空白一致,任何变化或不一致都可能导致奇怪和令人费解的错误。例如,我建议您针对constructor定义使用该格式,如果所有方法都处于相同的缩进级别,您将有更好的时间。