使用CoffeeScript在“公共函数”类中获取“私有方法”

时间:2013-07-29 04:51:51

标签: javascript class coffeescript private-methods public-method

我正在使用类和CoffeeScript / JavaScript进行一系列测试。请参阅以下代码:

class Example

    someFunction = ->
        alert @getText()

    constructor: ->
        @text = 'Hello world! ;)'
        someFunction()

    getText: ->
        @text


### Instance ###
example = new Example

这只是一个例子,在编译时我得到错误:

Uncaught TypeError: Object [object global] has no method 'getText'

你知道我怎么能解决这个问题吗? http://jsfiddle.net/P4Xdz/

4 个答案:

答案 0 :(得分:6)

如果你真的想做这类事情,你必须亲自手动提供正确的@(AKA thiscallapply

constructor: ->
    @text = 'Hello world! ;)'
    someFunction.call(@)

演示:http://jsfiddle.net/ambiguous/6KZrs/

问题是someFunction不是任何类型的方法,它只是一个简单的函数。如果您需要它的行为方式,那么您必须通过在调用它时提供所需的@来手动“方法化”它。这个(和epidemian)提出了另一种方法:明确地将对象作为参数传递:

someFunction = (ex) ->
    console.log ex.getText()

constructor: ->
    @text = 'Hello world! ;)'
    someFunction(@)

演示:http://jsfiddle.net/ambiguous/hccDr/

请记住,JavaScript中没有公共或私有,因此CoffeeScript中没有公共或私有。你可以假装它,但伪造有洞,往往需要更多的chicanery(如手动提供@call),使其工作。如果您查看代码的JavaScript版本,您会看到someFunction就是这样:

var someFunction = function() { ... };

只是一个作用于类函数的变量中的函数,仅此而已。另请注意,由于someFunctionExample类函数的本地函数,因此它不会以任何方式显示为子类。

答案 1 :(得分:3)

这可能是显而易见的但是...... coffescript无法做任何概念上你无法在javascript中做的事情。现在你的someFunction定义是一个局部变量,并没有在实例上声明为属性(与getText不同)。

当你在someFunction中使用'@'时,我假设你希望它引用Example的实例,这在你的情况下会很方便,但是在例子中没有定义someFunction。

如果您使用=>它仍然不会将它绑定到实例(它将引用类函数)。现在这可能看起来不方便,或者是一个奇怪的设计选择,但它实际上是一致的。再一次,someFunction不在实例上,它被定义为Example类函数中的局部变量。

如果你使用 - >,'@'指的是该函数的javascripts'this'(它是局部变量,显然不包含getText)。如果你使用=>它在定义时指的是javascripts'this',此时是Example类的函数。您想要引用的Example实例甚至尚未创建(尽管您希望引用它)。

@引用getText等函数中的示例实例的原因是因为javascripts此关键字引用了您定义的对象。 Coffeescript实际上并没有什么不同,除了在功能定义时为您提供一个方便的语法来引用'this'。

TLDR:

你无法真正完成你想要的东西,你可能不得不放弃对一个实例的'私有'功能的想法 我能看到你做的最好的就是你在上面的评论中已经描述过的内容 Example.prototype.getText() 因为您能够引用此方法的两种方法是通过实例和Example.prototype(定义函数)。由于您的方法未在实例上定义,因此您无法使用“this”。但是,如果从原型中调用该方法,则无论如何都会使getText函数失败。

getText: ->
        @text

@text指的是定义了getText,在此上下文中是原型(不是实例)。并且原型上的文本未定义。

如果你想让这个方法按你期望的方式运行,你可能不得不让它变成'私人'。 Javascript / Coffeescript没有像public和private这样的访问修饰符,私有方法实际上是在特定范围内定义的函数。在这种情况下,范围无法访问您想要的内容,而this关键字不会引用您所需的内容。

答案 2 :(得分:1)

  1. 您使用的是someFunction =而不是someFunction:。这不符合你的期望。
  2. 您正在呼叫someFunction,实际上您可能想要拨打@someFunction

答案 3 :(得分:-1)

在您编写示例的方式中,'someFunction'是一个未绑定任何东西的匿名函数。所以,'someFunction''this'绑定到全局对象,这解释了你的错误。您可以使用胖箭头定义'someFunction'并在Example的构造函数中放置'someFunction'来修复它。这将导致'someFunction'绑定到您的Example实例。如果您使用胖箭头绑定'someFunction',但是将其保留在构造函数之外,那么'someFunction'将绑定到Example构造函数,导致'someFunction'调用不存在的静态方法--getText - 示例。

以下是摆脱错误的方法:

class Example
    constructor: ->
        someFunction = =>
            alert @getText()

        @text = 'Hello world! ;)'
        someFunction()

    getText: =>
        @text


### Instance ###
example = new Example