【问题标题】:Scope in coffeescript classes咖啡脚本类的范围
【发布时间】:2012-10-10 20:15:48
【问题描述】:

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

我可以在不向每个嵌套函数传递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"

【问题讨论】:

  • 在构造函数中绑定到this/@?
  • 你的意思是constructor: -> @errors = [] @functions: doStuff -> ... ?
  • 也许用粗箭头 => coffeescript.org/#fat_arrow我不是咖啡脚本大师,抱歉:)
  • 我也没有。尝试摆弄它,但无法让它工作。
  • 用我尝试使用它的方式更新了我的帖子。

标签: javascript scope coffeescript


【解决方案1】:

在 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 不适合这样的滥用。所有对象方法都应该直接在对象原型中。如果你有对象,它的所有方法都不是你的对象的方法。

【讨论】:

    【解决方案2】:

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

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

    这是在这种情况下正确使用fat arrow 的示例。

    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 胖箭头的威力!

    【讨论】:

    • 感谢=>的解释
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-13
    • 2013-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多