CoffeeScript类中的作用域范围

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"

在构造函数中将它们绑定到 this/@? - biziclop
你的意思是 constructor: -> @errors = [] @functions: doStuff -> ... 吗? - Industrial
也许可以使用胖箭头 => http://coffeescript.org/#fat_arrow 我不是Coffeescript大师,抱歉 :) - biziclop
我也是。尝试了一些调整,但无法使其正常工作。 - Industrial
更新了我的帖子,附上了我尝试使用它的方式。 - Industrial
如果没有其他帮助,您可以在functions数组中的每个项目上使用javascript自己的bind函数:https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind - biziclop
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并非旨在滥用此类功能。所有对象方法都应直接在对象原型中。如果您在其中有一个对象,则其中的所有方法都不是您对象的方法。


2
作为对GlitchMr答案的补充,我将解释为什么每个尝试都失败了。
  1. functions对象在原型中声明,因此@errors 编译为myClass.errors。但是,errors对象被声明为实例成员,而不是原型成员。
  2. 您使用CoffeeScript的函数表示法定义functions,但它应该是一个对象。错误消息是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的箭头函数的优势!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接