在CoffeeScript中使用语言助手来分配原型属性

时间:2013-12-26 18:20:31

标签: javascript coffeescript javascript-objects

我有一个CoffeeScript代码,它是neo4j的驱动程序代码。因为它有一个类PropertyContainer,它有两个函数getset,它们被列为语言助手。以下是selfdata,它们基本上是此对象的原型属性。可以像a.selfa.data一样访问这些内容。

我不明白为什么他们之前是getset,在下面的代码中。 getset清楚地标识了正在读取或写入的属性,但它是如何工作的。在CoffeeScript中,您将原型属性定义为s prop_name: -> somecode,但如果您放置get prop_name: -> somecode,则不应将属性名称更改为get prop_name之后返回的内容。我是CoffeeScript的新手,所以也许我错过了一些东西。请帮助。

class PropertyContainer

    #
    # Construct a new wrapper around a Neo4j property container with the given
    # data directly from the server at the given Neo4j {GraphDatabase}.
    #
    # @private
    # @param db {GraphDatbase}
    # @param data {Object}
    #
    constructor: (db, data) ->
        @db = db
        @_request = db._request     # convenience alias

        @_data = data or {}
        @_data.self = data?.self or null

    ### Language helpers: ###

    get = (props) =>
        @::__defineGetter__ name, getter for name, getter of props
    set = (props) =>
        @::__defineSetter__ name, setter for name, setter of props

    ### Properties: ###

    #
    # @property {String} The URL of this property container.
    #
    # @todo This might be an implementation detail; should we remove it?
    #   If not, should it at least be renamed to just URL?
    #
    get self: -> @_data.self or null

    #
    # @property {Object} This property container's properties. This is a map
    #   of key-value pairs.
    #
    get data: -> @_data.data or null
    set data: (value) -> @_data.data = value

这实际上是基于REST API的Neo4j驱动程序。我不认为它与HTTP的GET方法有任何关系。我检查了__defineGetter____defineSetter__,除了以类似的方式用于其他类之外,这些在整个库中都没有其他地方可见。可能是这些是一些CoffeeScript内部原型原型。如果有人能够对此有所了解,那会爱吗。再次感谢。

1 个答案:

答案 0 :(得分:1)

CoffeeScript类是一个函数定义,顶部有一堆class-ish东西。这意味着你可以将任何你想要的代码放在一个类中。所以,如果我们看一下:

class C
    f = -> #...
    f(6)

然后我们有一个私有函数f和一个简单的函数调用f(6)

现在,如果我们在混音中添加=>

class C
    f = => #...

然后f绑定到该类,以便@内的f本身为C

现在我们可以将它应用于相关课程:

class PropertyContainer
    #...

    get = (props) =>
        @::__defineGetter__ name, getter for name, getter of props
    set = (props) =>
        @::__defineSetter__ name, setter for name, setter of props

    get self: -> @_data.self or null

因此,我们有两个函数getset,这些函数比PropertyContainer有很多,因此@get内的setPropertyContainer get。然后我们调用get({ self: (-> @_data.self or null ) }) 函数并添加一些括号和大括号来突出显示结构:

get self ...

我们应该开始看看发生了什么。 get只是使用object参数调用self函数,该对象只有一个键(get self ...),其值是函数。

这使整个PropertyContainer::__defineGetter__('self', -> @_data.self or null) 调用看起来像这样:

// Non-standard and deprecated way
var o = {};
o.__defineGetter__("gimmeFive", function() { return 5; });
console.log(o.gimmeFive); // 5

然后,如果我们看看__defineGetter__做了什么:

o.self

我们发现我们只是将o._data.self设置为o = new PropertyContainer(...) o.self 的访问者别名,以便:

o = new PropertyContainer(...)
o._data.self

与:

真的相同
get

或更一般地,// Using the get operator var o = { get gimmeFive() {return 5}}; console.log(o.gimmeFive); // 5 函数允许您发送对函数的简单属性访问。您还应该注意MDN页面中的“标准兼容”示例:

get

现在我们看到PropertyContainer内的__defineGetter__正在使用非标准set函数模拟JavaScript的get operator

PropertyContainer内的{{1}}功能同样模仿JavaScript的set operator