片段A:
DemoFilter =
onConfirmed: (cb) ->
cb()
a =
onConfirmed: (callback) ->
this.callback = callback
confirm: ->
this.callback()
b =
init: ->
a.onConfirmed =>
DemoFilter.onConfirmed @mycallback
mycallback: =>
console.log this # output: {} or Object window on browser
b.init()
a.confirm()
片段 B:
DemoFilter =
onConfirmed: (cb) ->
cb()
a =
onConfirmed: (callback) ->
this.callback = callback
confirm: ->
this.callback()
b =
init: ->
a.onConfirmed =>
DemoFilter.onConfirmed =>
console.log this # output: Object b
# mycallback: =>
# console.log this
b.init()
a.confirm()
为什么这些console.log
输出不一样?
在节点环境中:
A:输出{}
B: 输出对象b
我发现编译结果完全一样,我想不通为什么结果不一样。
最佳答案
这里的问题是您使用的是简单的对象而不是类,因此 =>
的行为不符合您的预期。当你这样说时:
o =
m: =>
这和说完全一样:
f = =>
o =
m: f
这意味着 m
中的 @
(又名 this
)是全局对象(window
in a浏览器或者 AFAIK,node.js 中的一个空对象)而不是你期望的 o
。
当你说:
class C
m: =>
当您说o = new C
时,CoffeeScript 会将m
绑定(bind)到C
实例。如果您使用普通对象文字而不是类,则没有特殊的构造阶段来设置绑定(bind),也没有类的实例供 =>
将函数绑定(bind)到。
如果我们回到您的第一个案例:
b =
init: ->
a.onConfirmed =>
DemoFilter.onConfirmed @mycallback
mycallback: =>
console.log this
mycallback
将绑定(bind)到任何全局对象。此外,@
(又名 this
)的值取决于函数的调用方式,而不是函数的定义位置(当然不包括绑定(bind)函数),因此如果您说:
b.init()
那么 init
中的 @
将是 b
。然后你交给a.onConfirmed
的匿名函数:
a.onConfirmed =>
DemoFilter.onConfirmed @mycallback
将绑定(bind)到 b
,因为当您定义该函数时,@
是 b
。但是 mycallback
不会在意,因为它已经绑定(bind)到全局对象。
在你的第二种情况下:
b =
init: ->
a.onConfirmed =>
DemoFilter.onConfirmed =>
console.log this
当调用 init
并将匿名函数传递给 a.onConfirmed
时,我们再次将 @
设为 b
将再次绑定(bind)到 b
。这意味着当:
DemoFilter.onConfirmed => ...
被调用,@
将再次成为 b
。这里我们有另一个匿名绑定(bind)函数,因为 @
是 b
在这个级别我们有 this
(AKA @
) b
当 console.log this
被调用时。
如果您使用的是类而不仅仅是对象:
class A
onConfirmed: (@callback) ->
confirm: ->
@callback()
class B
constructor: (a) ->
a.onConfirmed =>
DemoFilter.onConfirmed @mycallback
mycallback: =>
console.log @
a = new A
b = new B(a)
a.confirm()
然后您应该会看到您期望的行为。
关于javascript - 这两个实现有什么不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35702056/