9

我想在一个类属性中嵌套一些函数,如下所示。
不幸的是,他们无法访问课程的主要范围。

我可以在不向每个嵌套函数传递引用的情况下解决这个问题this吗?

class myClass

  constructor: -> @errors = []

  doSomething: -> @errors.push "I work as expected"

  functions:
    doStuff: ->
      @errors.push "I cant access @errors" # => TypeError: Cannot call method 'push' of undefined

    ugly: (context) ->
      context.errors.push "It works, but I am ugly" # Works fine but requires scope injection

使用建议的粗箭头的非工作替代方案:

class myClass
  constructor: ->
    @errors = []

    @functions:
      doStuff: =>
        @errors.push "I wont work either" # TypeError: Cannot call method 'toString' of undefined

可选的替代方法,它不写入全局this.errors属性:

class myClass

  constructor: ->

    @functions =
      errors: []
      doStuff: ->
        @errors.push "I will write to functions.errors only"
4

2 回答 2

3

在 JavaScript 中(结果,CoffeeScript 也是如此),方法使用this包含方法的对象。

method()                  // this == globalObject
object.method()           // this == object
Math.random()             // this == Math

这通常效果很好,除非你处理像你这样的例子:

object.functions.method() // this == object.functions

在处理 JavaScript 时,我会避免为函数使用命名空间——即使有变通方法,它也不能很好地发挥作用。例如,您可以尝试将this对象的引用放入 中object.functions,这样任何函数object.functions都可以访问它。

class MyClass
  constructor: ->
    @errors = []
    @functions.self = this

  doSomething: ->
    @errors.push "I work as expected"

  functions:
    alsoDoSomething: ->
      @self.errors.push "Also works!"

起初这似乎可行,但当您使用类似applycall之类的属性时可能会令人困惑,obj1.functions.alsoDoSomething.call(obj2)因为obj2对象不正确(用户应该这样做obj2.functions,这可能会令人困惑)。

真正的解决方案是:不要。JavaScript 不适合这样的滥用。所有对象方法都应该直接在对象原型中。如果你有对象,它的所有方法都不是你的对象的方法。

于 2012-10-20T11:42:25.243 回答
2

作为 GlitchMr 答案的附录,我将解释为什么您的每次尝试都失败了。

  1. functions对象在原型上声明,因此@errors被编译为 myClass.errors. 但是,该errors对象被声明为实例成员,而不是原型成员。
  2. functions当它应该是一个对象时,您可以使用 CoffeeScript 的函数符号来定义。错误信息是 CoffeeScript 编译器错误;在修复了这个语法错误之后,它就可以正常工作了!
  3. 你在这个例子前面加上为什么它不起作用,所以我不会告诉你两次!

这是在这种情况下正确使用粗箭头的示例。

class MyClass

  constructor: ->
    @errors = []
    @functions = 
      doStuff: =>
        @errors.push "I can and do access @errors"

c = new MyClass
c.functions.doStuff()
console.log c.errors # ["I can and do access @errors"]

希望这有助于揭开错误的神秘面纱并展示 CoffeeScript 胖箭头的力量!

于 2012-10-22T21:05:57.103 回答