在嵌套的Coffeescript中访问实例属性

时间:2014-01-07 17:22:01

标签: express coffeescript

所以我在node-app中使用express。随着我的应用越来越大,我想把我的路线放到额外的文件中。如果我摆脱中间的get对象,我似乎能够掌握bugDB。但我无法访问内部对象中的bugDB。有什么建议?也许甚至有一个更好的代码模式,如何更优雅地完成这一点。

我愿意帮助你。提前致谢。 (由于我不是母语人士,我找不到有类似问题的人,如果你知道如何更好地表达问题,请告诉我方式:))

BUGROUTER.COFFEE
class BugsRouter
    constructor: (@bugDB)->   // instance-variable with databaselink
        return

    get:{
        allBugs: (req, res)=>
            console.log "db", @bugDB // this gives me undefined
                                     // is "this" in the get context? 
            @bugDB.allDocs {include_docs: true}, (err, response)->
                res.json 200, response
        }
module.exports = BugsRouter

SERVER.COFFEE
BugsRouter = require "./routes/BUGROUTER"
bugsRouter = new BugsRouter(bugDB)
console.log bugsRouter.bugDB # this is working
app.get    "/bugs/all", bugsRouter.get.allBugs

2 个答案:

答案 0 :(得分:2)

子对象不能那样工作。当你这样说:

class C
    p:
        f: ->

然后p只是一个普通的对象,碰巧是C原型上的一个属性,它不会特别知道@应该在f内部class C p: f: => }。如果你尝试使用胖箭头:

f

然后你不小心创建了一个名为@的命名空间类函数,因此调用Cf将为c = new C c.p.f() 。无论哪种情况,都说:

c = new C
p = c.p
p.f()

与:

相同
f

所以p将在c而非get的上下文中调用。

如果您不介意在调用constructor时手动绑定constructor: (@bugDB) -> @get = { } for name, func of @constructor::get @get[name] = func.bind(@) 内的功能,则可以解决此问题:

_.bind

这假设您有Function.bind可用。如果不这样做,则可以使用任何其他绑定技术($.proxy@get = { },...)。需要@get技巧以确保您不会意外修改原型的BugsRouter版本;如果您确定自己只会创建constructor: (@bugDB) -> for name, func of @get @get[name] = func.bind(@) 的一个实例,那么您可以使用此实例:

get

绑定原型版本@内的函数,而不是实例的本地副本。

您可以观看此简化演示,了解@flag在各种情况下的情况,并密切关注@get = { }值,以查看因不使用@constructor::get而导致的意外原型修改和class C1 get: f: -> console.log('C1', @) class C2 get: f: => console.log('C2', @) class C3 constructor: -> @flag = Math.random() for name, func of @get @get[name] = func.bind(@) get: f: -> console.log('C3', @) class C4 constructor: -> @flag = Math.random() @get = { } for name, func of @constructor::get @get[name] = func.bind(@) get: f: -> console.log('C4', @) for klass in [C1, C2, C3, C3, C4, C4] o = new klass o.get.f()

{{1}}

上述的实时版本:http://jsfiddle.net/ambiguous/8XR7Z/

答案 1 :(得分:0)

嗯,好像我毕竟找到了一个更好的解决方案:

class Test
    constructor: ->
        @testVariable = "Have a nice"
        return

    Object.defineProperties @prototype,
        get:
            enumerable :true
            get:->
                {
                    day: => @testVariable + " day"
                    week: => @testVariable + " day"
                }

console.log (new Test()).get.day()

这允许我按照我想要的方式拨打(new Test()).get.day()。 实时版本:JSFiddle