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