coffeescript课程的范围

时间:2012-10-20 10:14:03

标签: javascript scope coffeescript

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

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

2 个答案:

答案 0 :(得分: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不会像这样滥用。所有对象方法都应该直接在对象原型中。如果你有对象,它的所有方法都不是你对象的方法。

答案 1 :(得分:2)

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

  1. functions对象在原型上声明,因此@errors被编译为myClass.errors。但是,errors对象被声明为实例成员,而不是原型成员。
  2. 使用CoffeeScript的函数表示法定义functions,它应该是一个对象。错误消息是CoffeeScript编译器错误;修复此语法错误后,它的工作原理应该如此!
  3. 你在这个例子前面说明为什么它不起作用,所以我不会告诉你两次!
  4. 以下是在这种情况下正确使用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肥胖箭头的力量!