匿名函数用作回调,但定义函数不用

时间:2016-10-23 07:08:42

标签: coffeescript

我有一个看起来像这样的模块:

module.exports = AtomMarkdownLabels =
  # other stuff here

  file_changed_added: (file_path) =>
    fs.readFile file_path, 'utf-8', @process_yaml
    console.log 'file changed'

  process_yaml: (err, data) =>
    console.log "process_yaml is called"

我知道file_changed_added正在从其他一些功能中调用,我看到"文件已更改"在控制台中输出,但如果我将process_yaml更改为

,则file_changed_added不是{\ n}
file_changed_added: (file_path) =>
    fs.readFile file_path, 'utf-8', (err, data) =>
      console.log "test"
    console.log 'file changed'

我看到了"测试"和"文件已更改"被称为正确。会发生什么事?

1 个答案:

答案 0 :(得分:2)

=>有两个略有不同的目的:

  1. 在定义命名函数(f = => ...)或匿名函数f(x, => ...))时,=>只是确保函数内的@与{{@相同1}}在周围的环境中。

  2. 在类中定义方法时:

    class C
      m: => ...
    

    =>确保@内的m成为C的实例。

  3. 两种用途都是创建绑定函数,但它们绑定到不同的东西。

    您正在使用此结构:

    obj =
      func: =>
        # ...
    

    这相当于:

    f = =>
      # ...
    obj =
      func: f
    

    因为您使用的是普通旧对象而不是类。那么@定义之外的AtomMarkdownLabels是什么? @不会有任何用处,特别是它不会是您的AtomMarkdownLabels对象,也不会有process_yaml属性@process_yaml file_changed_added }}将是undefined或错误。

    我不确定Atom有什么特别想要你回来的,但课程应该有用,就像这样:

    # Use a class so that => does what you're expecting it to do
    class AtomMarkdownLabels
      # other stuff here
    
      file_changed_added: (file_path) =>
        fs.readFile file_path, 'utf-8', @process_yaml
        console.log 'file changed'
    
      # you may or may not need => here
      process_yaml: (err, data) =>
        console.log "process_yaml is called"
    
    # Export an instance of your class
    module.exports = new AtomMarkdownLabels
    

    如果您想要或必须使用普通对象,那么您可以完全绕过@,并按照以下方式执行:

    # Just plain old functions so define them that way
    process_yaml = (err, data) ->
      console.log "process_yaml is called"
    
    file_changed_added = (file_path) ->
      fs.readFile file_path, 'utf-8', process_yaml
      console.log 'file changed'
    
    module.exports = AtomMarkdownLabels =
      # other stuff here
    
      file_changed_added: file_changed_added
    

    或者像这样:

    # Explicitly name your object rather than using @
    module.exports = AtomMarkdownLabels =
      # other stuff here
    
      file_changed_added: (file_path) ->
        fs.readFile file_path, 'utf-8', AtomMarkdownLabels.process_yaml
        console.log 'file changed'
    
      process_yaml: (err, data) ->
        console.log "process_yaml is called"
    

    这也应该解决几天前的your other CoffeeScript问题。