【问题标题】:Decorate functions in a CoffeeScript class在 CoffeeScript 类中装饰函数
【发布时间】:2012-06-15 22:14:21
【问题描述】:

我正在编写一个主干应用程序,我想编写一个经过身份验证的装饰器,我可以用它来装饰路由器类中的方法(路由)列表。

所以我有一个带有几种方法的路由器,并尝试过类似的方法。但是,当我调用我想要装饰的路线时,装饰器没有附加。

class MyApp extends Backbone.Router

  routes: 
    ''         : 'home'
    'foo'      : 'foo'
    'bar'      : 'bar'


  authenticated: ['foo', 'bar'] 

  initialize: ->
    @decorateAuthenticatedFunctions()      

  decorateAuthenticatedFunctions: => 
    _.each @authenticated, (method)=>
      @[method] = (args)=>
        if @authorized()
          @[method].apply @, args
        else
        @navigate '', true

  authorized: =>
    @user? and @user.loggedIn 

  foo: =>
    #do stuff

  bar: =>
    #do stuff

我该如何解决这个问题?

【问题讨论】:

  • 你确定initialize 被调用了吗?在那里添加一个console.log的警报以确保。

标签: javascript backbone.js coffeescript decorator


【解决方案1】:

你有一些问题。

首先,我认为initialize 不会因为某种原因被调用。我可以说,因为如果它被调用,那么它会引发错误(见下一点)。现在我不是骨干专家,但也许可以尝试使用构造函数?

class MyApp extends Backbone.Router
  constructor: ->
    super
    @decorateAuthenticatedFunctions()

其次,该循环不起作用。您将用一个新函数替换 @[method],该函数在该函数中调用 @[method]。当它成功时,你会得到一个递归的无限函数调用。所以保存对原始函数的引用,然后使用装饰器函数调用该引用。

当你在那里时,不需要下划线,因为咖啡脚本循环非常好。而且你甚至根本不需要这个循环的闭包,因为你只是立即使用循环值。

这个稍作改动的非主干版本有效:

http://jsfiddle.net/ybuvH/2/

class MyApp

  authenticated: ['foo', 'bar'] 

  constructor: ->
    @decorateAuthenticatedFunctions()      

  decorateAuthenticatedFunctions: =>
    for method in @authenticated
      fn = @[method]
      @[method] = (args) =>
        if @authorized()
          fn.apply @, args
        else
          console.log 'denied'

  authorized: =>
    @user? and @user.loggedIn 

  foo: =>
    console.log 'foo'

  bar: =>
    console.log 'bar'

app = new MyApp

app.user = { loggedIn: no }
app.foo() # denied
app.bar() # denied

app.user = { loggedIn: yes }
app.foo() # foo
app.bar() # bar​

【讨论】:

  • 您不想提供自己的constructor。 Backbone 机器将调用initialize。不过,他在else 上缺少一些缩进,这可能会导致一些意外行为。使用_.each 有一个优势,如果可用,它将使用本机forEach
【解决方案2】:

我认为您遇到了 this 上下文问题。

请记住,“胖箭头”=> 在函数定义时绑定到 this。因此,当您想将其绑定到您的 MyApp 实例时,您的 decorateAuthenticatedFunctions: => 将绑定到全局 this

试试这个:

...

initialize: ->
  @decorateAuthenticatedFunctions.call(@) # Call with proper context

decorateAuthenticatedFunctions: ->    # Use skinny arrow
  _.each @authenticated, (method)=>
    @[method] = (args)=>
      if @authorized()
        @[method].apply @, args
      else
      @navigate '', true

authorized: ->                        # Use skinny arrow
  @user? and @user.loggedIn 

...

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2011-10-04
  • 2015-10-23
  • 2011-06-06
  • 2017-09-14
  • 2011-10-28
  • 2019-07-23
  • 1970-01-01
  • 2016-05-21
相关资源
最近更新 更多