CoffeeScript:内联调用委托,它与函数绑定一起使用

时间:2014-03-16 19:21:52

标签: javascript coffeescript delegation

我有以下CS代码段:

class Ctrl
    constructor: (@security) ->
        ...

    isAuthenticated: -> @security.isAuthenticated()

转换为以下JS:

Ctrl = (function() {
    function Ctrl(security) {
        this.security = security;
        ...
    }

    Ctrl.prototype.isAuthenticated = function() {
        return this.security.isAuthenticated();
    };
})()

正如您所看到的,isAuthenticated是对security对象方法的简单委派,创建匿名函数是多余的。
我想避免创建这个额外的调用级别,而是执行一种“内联委托”,它将转换为JS类似于:

Ctrl = (function() {
    function Ctrl(security) {
        this.security = security;
        ...
    }

    Ctrl.prototype.isAuthenticated = this.security.isAuthenticated;
})()

以下操作不起作用,因为它尝试将@security绑定到错误的对象:

class Ctrl
    constructor: (@security) ->
        ...

    isAuthenticated: @security.isAuthenticated

任何线索?

3 个答案:

答案 0 :(得分:2)

您可以通过各种方式挂钩委派,但您必须了解两件事:

  1. 当你联系代表团时@是什么。
  2. 如果使用@security.isAuthenticated调用isAuthenticated而不是this,则
  3. @security可能无法工作。
  4. (1)告诉您附加委托功能需要什么(见下文)。 (2)是通常的"功能参考不是真正的方法" JavaScript中的问题;例如:

    o =
        m: -> console.log(@)
    o.m()        # Puts `o` in the console
    f = o.m; f() # Puts `window` (usually) in the console.
    

    因此,您必须isAuthenticated@security绑定,否则可能无法正常工作。

    添加委派的一种简单方法是将一堆绑定函数附加到@内的constructor

    delegate = (to, from, methods...) ->
        for m in methods
            to[m] = from[m].bind(from)
    
    class Ctrl
        constructor: (@security) ->
            delegate(@, @security, 'isAuthenticated', 'somethingElse')
    

    然后你可以说:

    c = new Ctrl(s)
    c.isAuthenticated()
    c.somethingElse(11)
    

    并且预期的事情发生了。 演示http://jsfiddle.net/ambiguous/we8gT/

    该方法的一个问题是Ctrl的每个实例最终都有自己的isAuthenticatedsomethingElse函数:它们没有附加到原型上,所以它们&#39 ;不共享。

    但我们总是可以创建自己的函数,并利用我们可以在class C内调用代码的事实:

    delegate = (klass, property, methods...) ->
        for m in methods
            do (m) -> klass::[m] = (args...) -> @[property][m](args...)
    
    class Ctrl
        delegate(@, 'security', 'isAuthenticated', 'somethingElse')
        constructor: (@security) ->
    

    注意事项:

    1. ::用于访问原型,因此将共享方法。
    2. 我们使用(args...) ->将任何参数传递给@security方法。
    3. @ class级别是班级本身。
    4. 我们使用do来确保m是我们在调用委托函数时所期望的。
    5. 演示http://jsfiddle.net/ambiguous/4c87J/

      你可以做代表团,但你不能免费获得。

答案 1 :(得分:1)

您无法在原型上使用实例的.security对象。您需要在可以访问它的构造函数中创建isAuthenticated方法:

class Ctrl
    constructor: (@security) ->
        @isAuthenticated = security.isAuthenticated
        …

translate

答案 2 :(得分:1)

Ctrl = (function() {
    function Ctrl(security) {
        this.security = security;
        ...
    }

    Ctrl.prototype.isAuthenticated = this.security.isAuthenticated;
})()

甚至不能在Javascript中使用。

安全性将是未定义的,无论如何您都会遇到isAuthenticated方法的上下文(this)问题。你不能挽救那一笔。

编辑:

证明:http://jsfiddle.net/camus/Ecd7K/

在控制台上显示错误