我正在使用类和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/
答案 0 :(得分:6)
如果你真的想做这类事情,你必须亲自手动提供正确的@
(AKA this
)call
或apply
:
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() { ... };
只是一个作用于类函数的变量中的函数,仅此而已。另请注意,由于someFunction
是Example
类函数的本地函数,因此它不会以任何方式显示为子类。
答案 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)
someFunction =
而不是someFunction:
。这不符合你的期望。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