当构建中的CoffeeScript一个类,应该所有的实例方法使用来定义=>
(“脂肪箭头”)算子和所有的静态方法使用被定义->
操作者?
Answer 1:
不,这不是我会使用规则。
我在定义方法发现脂肪箭头的主要用途,一种情况是当你想使用的方法作为回调和方法引用实例字段:
class A
constructor: (@msg) ->
thin: -> alert @msg
fat: => alert @msg
x = new A("yo")
x.thin() #alerts "yo"
x.fat() #alerts "yo"
fn = (callback) -> callback()
fn(x.thin) #alerts "undefined"
fn(x.fat) #alerts "yo"
fn(-> x.thin()) #alerts "yo"
正如你看到的,你可能会碰到路过一个实例的方法的引用作为回调,如果你不使用胖箭头的问题。 这是因为脂肪箭头绑定对象的实例来this
而薄箭头没有,这么薄箭头方法称为回调如上无法访问实例的领域,如@msg
或调用其他实例方法。 最后一行有对于其中薄箭头已经使用的情况下一种解决方法。
Answer 2:
在其他的答案没有提及的一点是重要的是要注意的是,与脂肪结合箭函数时,不需要可能会导致意想不到的结果,如在这个例子中有一类我们就称之为DummyClass。
class DummyClass
constructor : () ->
some_function : () ->
return "some_function"
other_function : () =>
return "other_function"
dummy = new DummyClass()
dummy.some_function() == "some_function" # true
dummy.other_function() == "other_function" # true
在这种情况下,功能也正是人们所预料的,有似乎没有损失,使用脂肪箭头,但是当我们修改它已经被定义后DummyClass原型发生了什么(例如,改变一些警报或更改日志的输出) :
DummyClass::some_function = ->
return "some_new_function"
DummyClass::other_function = ->
return "other_new_function"
dummy.some_function() == "some_new_function" # true
dummy.other_function() == "other_new_function" # false
dummy.other_function() == "other_function" # true
我们可以看到我们的覆盖前面定义的原型功能使some_function被正确改写,但other_function保持在实例一样胖箭头已经从类引起other_function绑定到所有实例,以实例不会提到回到他们的阶级找到一个函数
DummyClass::other_function = =>
return "new_other_new_function"
dummy.other_function() == "new_other_new_function" # false
second_dummy = new DummyClass()
second_dummy.other_function() == "new_other_new_function" # true
即使脂肪箭头将无法正常工作,胖箭头不仅会导致功能被绑定到新的实例(这做获得新的功能,如人们所期望的)。
然而,这导致了一些问题,如果我们需要什么样的功能(例如,在切换日志记录功能,输出箱或某事的情况下),将在现有的所有实例(包括事件处理程序)工作[因为如此,我们不能用在最初的定义脂肪箭头],但我们仍然需要访问内部属性在事件处理程序[我们用肥箭不细箭头]的确切原因。
那么做到这一点最简单的方法是仅仅包括在原来的类定义两个功能,一个用细箭头这确实是要执行的操作定义,并与脂肪箭头,什么也不做的另一个定义,但调用的第一个函数例如:
class SomeClass
constructor : () ->
@data = 0
_do_something : () ->
return @data
do_something : () =>
@_do_something()
something = new SomeClass()
something.do_something() == 0 # true
event_handler = something.do_something
event_handler() == 0 # true
SomeClass::_do_something = -> return @data + 1
something.do_something() == 1 # true
event_handler() == 1 # true
因此,当使用瘦/胖箭头,可以概括很容易在四个方面:
当两个条件都METT细箭头单独函数应使用:
- 该方法将永远不会通过引用包括event_handlers例如你从来没有的情况下,如进行传递:some_reference = some_instance.some_method; some_reference()
- 和方法应该是在所有情况下,通用因此,如果原型函数变化如此做的方法在所有情况下,
当满足以下条件时,应使用脂肪箭头单独的功能:
- 该方法应该精确绑定在创建实例的实例,并保持永久绑定,即使为原型的函数定义的改变,这包括所有情况下的功能应该是一个事件处理程序和事件处理程序的行为应该是一致的
脂肪箭头函数直接调用时,满足以下条件时,应使用细箭头功能:
- 需要的方法,通过引用被称为诸如事件处理程序
- 和功能可能会在未来改变通过更换细箭头功能影响现有实例
细箭头函数直接调用脂肪箭头(未展示),当满足以下条件时,应使用功能:
- 脂肪箭头功能必须始终高度重视实例
- 但细箭头功能可以改变(甚至不使用原来的脂肪箭头功能的新功能)
- 并且永远不会需要的细箭头功能通过引用传递
在所有这些方法,必须在原型的功能可能会被更改为特定情况下的行为是否会正确的行为,例如虽然功能与肥胖定义箭头其行为的一个实例内可能不一致如果它调用的情况下,可以考虑在所述原型内变化的方法
Answer 3:
Usually, ->
is fine.
class Foo
@static: -> this
instance: -> this
alert Foo.static() == Foo # true
obj = new Foo()
alert obj.instance() == obj # true
Note how the static method return the class object for this
and the instance returns the instance object for this
.
What's happening is that the invocation syntax is providing the value of this
. In this code:
foo.bar()
foo
will be the context of the bar()
function by default. So it just sorta works how you want. You only need the fat arrow when you call these function in some other way that does not use the dot syntax for invocation.
# Pass in a function reference to be called later
# Then later, its called without the dot syntax, causing `this` to be lost
setTimeout foo.bar, 1000
# Breaking off a function reference will lose it's `this` too.
fn = foo.bar
fn()
In both of those cases, using a fat arrow to declare that function would allow those to work. But unless you are doing something odd, you usually don't need to.
So use ->
until you really need =>
and never use =>
by default.
Answer 4:
只是unstanding脂肪箭头的例子
不工作:(@canvas未定义)
class Test
constructor: ->
@canvas = document.createElement 'canvas'
window.addEventListener 'resize', ->
@canvas.width = window.innerWidth
@canvas.height = window.innerHeight
工作原理:(@canvas定义)
class Test
constructor: ->
@canvas = document.createElement 'canvas'
window.addEventListener 'resize', =>
@canvas.width = window.innerWidth
@canvas.height = window.innerHeight