4

我正在使用类和 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

4 回答 4

6

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

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

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

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

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

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

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

请记住,JavaScript 中没有公共或私有,因此 CoffeeScript 中没有公共或私有。您可以伪造它,但伪造品有漏洞,并且往往需要更多的诡计(例如手动提供@with call)才能使其发挥作用。如果您查看代码的 JavaScript 版本,您会发现someFunction就是这样:

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

只是一个变量中的一个函数,它的作用域是类函数,仅此而已。还要记住,由于someFunction它是类函数的本地Example函数,因此它不会以任何方式对子类可见。

于 2013-07-29T05:48:52.400 回答
3

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

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

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

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

@ 引用 getText 等函数中的示例实例的原因是因为 javascripts this 关键字引用了您定义的对象。Coffeescript 确实没有什么不同,除了在函数定义时为您提供一种方便的语法来引用“this”。

TLDR:

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

getText: ->
        @text

@text 指的是 getText 的定义,在这种情况下它是原型(而不是实例)。原型上的文本未定义。

如果你想让这个方法按照你期望的方式运行,你可能不得不让它不是“私有的”。Javascript/Coffeescript 没有 public 和 private 之类的访问修饰符,私有方法实际上是在特定范围内定义的函数。在这种情况下,该范围无法访问您想要的内容,并且 this 关键字不引用您需要的内容。

于 2013-07-29T06:04:47.753 回答
1
  1. 您正在使用someFunction =而不是someFunction:. 这不会如你所愿。
  2. 你打电话someFunction,而事实上你可能想打电话@someFunction
于 2013-07-29T05:08:33.207 回答
-1

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

以下是摆脱错误的方法:

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

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

    getText: =>
        @text


### Instance ###
example = new Example
于 2013-07-30T01:40:12.437 回答