Memory management 在coffeescript中构建类时,有没有理由不对实例方法使用fat箭头?

Memory management 在coffeescript中构建类时,有没有理由不对实例方法使用fat箭头?,memory-management,coffeescript,arrow-functions,Memory Management,Coffeescript,Arrow Functions,在coffeescript中构建类时,是否有理由不使用胖箭头作为实例方法 编辑: 那好吧!很好的回答!:)总之,问题是: -占用更多内存 -无法修补 -问:为什么要用这种方法 惯例: -在绑定函数时要显式 -在构造函数中声明带箭头的fat方法 -尽可能多地使用,只是不要在类内声明是的,有理由不总是使用胖箭头。事实上,我主张永远不要使用脂肪箭头所指的方法:) 瘦箭头和胖箭头方法在概念上是不同的。前者编译为预期的基于原型的JS代码;这些方法属于类原型。另一方面,带粗箭头的方法与构造函数代码中的每个实

在coffeescript中构建类时,是否有理由不使用胖箭头作为实例方法

编辑: 那好吧!很好的回答!:)
总之,问题是:
-占用更多内存
-无法修补
-问:为什么要用这种方法
惯例:
-在绑定函数时要显式
-在构造函数中声明带箭头的fat方法

-尽可能多地使用,只是不要在类内声明

是的,有理由不总是使用胖箭头。事实上,我主张永远不要使用脂肪箭头所指的方法:)

瘦箭头和胖箭头方法在概念上是不同的。前者编译为预期的基于原型的JS代码;这些方法属于类原型。另一方面,带粗箭头的方法与构造函数代码中的每个实例相关联

始终使用粗箭头方法最明显的缺点是,它会使每个类实例占用更多内存(因为它有更多自己的属性),并且初始化速度较慢(因为它必须创建这些绑定函数,并在每次创建实例时设置它们)

使用fat arrow方法的另一个缺点是它打破了通常对方法的期望:方法不再是类实例之间共享的函数,而是每个实例的单独函数。例如,如果您希望在类中定义方法后修改该方法,则这可能会导致问题:

class Foo
  # Using fat-arrow method
  bar: (x) => alert x

# I have some Foos
foos = (new Foo for i in [1..3])

# And i want to path the bar method to add some logging. 
# This might be in another module or file entirely.
oldbar = Foo::bar
Foo::bar = (args...) ->
  console.log "Foo::bar called with", args
  oldbar.apply @, args

# The console.log will never be called here because the bar method 
# has already been bound to each instance and was not modified by 
# the above's patch.
foo.bar(i) for foo, i in foos

但在我看来,最重要的缺点是更加主观:引入胖箭头方法会使代码(和语言)不必要地不一致,难以理解

代码变得更加不一致,因为在任何时候我们在类定义中看到
时,在引入胖箭头方法之前,我们知道它意味着“在类“prototype”中用值
声明名为
的属性”(除非
==“constructor”
,这是一种特例),无论
是数字还是函数,它都只是原型中的一个属性。随着胖箭头方法的引入,我们现在有了另一个不必要的特殊情况:如果
是一个胖箭头函数,它将做一件与任何其他值完全不同的事情

还有另一个不一致之处:在方法定义中使用胖箭头比在其他任何地方使用胖箭头都要多。与保留外部
this
(在
类中,
this
绑定到类构造函数)不同,带粗箭头的方法中的
this
是定义方法时不存在的对象(即类的实例)

如果混合使用细箭头和粗箭头方法,代码也会变得更难理解,因为现在每次开发人员看到一个粗箭头方法时,他们都会问自己为什么需要这个方法来绑定实例。该方法的声明和它的使用位置之间没有直接的相关性,这正是fat arrow方法的需要所在


对于所有这些,我建议永远不要使用胖箭头方法。更喜欢将方法绑定到将要使用它的实例,而不是声明方法的实例。例如:

# Be explicit about 'onClick' being called on 'someObject':
$someJQueryElement.on 'click', (e) -> someObject.onClick e

# Instead of:
$someJQueryElement.on 'click', someObject.onClick
或者,如果确实希望在构建时在每个实例上绑定该方法,请明确说明:

# Instead of fat-arrow methods:
class A
  constructor: ->
    @bar = 42
  foo: => 
    console.log @bar

# Assing the method in the constructor, just like you would 
# do with any other own property
class A
  constructor: ->
    @bar = 42
    @foo = => 
      console.log @bar
我认为在
class A
的第二个定义中,使用
foo
方法发生的事情比第一个定义中要明确得多

最后,请注意,我并不反对使用胖箭头。这是一个非常有用的构造,我一直在用它来处理普通函数;我只是希望避免在
类中使用它
方法定义:)


编辑:另一个反对使用粗箭头方法的案例:装饰函数:

# A decorator function to profile another function.
profiled = (fn) ->
  (args...) ->
    console.profile()
    fn.apply @, args
    console.profileEnd()

class A
  bar: 10

  # This works as expected
  foo: profiled (baz) ->
    console.log "@bar + baz:", @bar + baz

  # This doesn't
  fatArrowedFoo: profiled (baz) =>
    console.log "@bar + baz:", @bar + baz

(new A).foo 5           # -> @bar + baz: 15
(new A).fatArrowedFoo 5 # -> @bar + baz: NaN

让我添加我的另一种观点

<>由“流行病”所表达的避免脂肪箭的详细原因是好的,但考虑如下:

  • 如果你对CoffeeScript生成的“基于原型的底层JS代码”不太关心(或者根本不关心),只要你能够编写一致且无bug的CoffeeScript代码
  • 如果你不打算在Java上编写数以百万计的小类,那么他们将花费99%的时间在继承树上下调用彼此的方法,并且在这个过程中完成的工作很少;换句话说,如果您认识到性能敏感的“内部循环”不是放置方法调用的好地方
  • 如果您不打算在运行时装饰、修补或修改类的方法
  • 如果您在标题注释中说明了fat arrow的用法,以便将来开发人员使用您的代码
然后我建议始终使用fat arrow,作为一种习惯,无论是对于方法还是对于匿名函数

这将使您的CoffeeScript代码更简单、更安全、更直观,因为您将知道,
@
始终引用您正在定义其方法的当前对象,就像在大多数其他编程语言中一样,与运行时调用您的函数和方法的人无关

更正式地说,fat-arrow使
这个
关键字(及其缩写
@
)与任何其他标识符一样,在词汇范围上完全相同。编程语言历史表明,词法作用域是范围标识符最直观、最不容易出错的方法。这就是为什么它在很久以前成为所有新语言的标准行为

如果选择此路径,细箭头将成为例外,并成为usef