代码段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
输出不一样?
在节点环境中:
答:输出{}
B:输出Object b
我发现编译结果完全相同,我无法弄清楚为什么结果不同。
答案 0 :(得分:2)
您的问题是,您使用简单的对象而不是类,因此=>
的行为方式与您预期的不同。当你这样说:
o =
m: =>
与说:
完全一样f = =>
o =
m: f
这意味着@
中的this
(AKA m
)是浏览器中的全局对象(window
,或者是Node.js中的空对象AFAIK而不是像你期望的那样o
。
当你说:
class C
m: =>
当您说m
时,CoffeeScript会将C
绑定到o = new C
实例。如果使用普通对象文字而不是类,则没有特殊的构造阶段来设置绑定,也没有=>
类的实例将函数绑定到。
如果我们回到你的第一个案例:
b =
init: ->
a.onConfirmed =>
DemoFilter.onConfirmed @mycallback
mycallback: =>
console.log this
mycallback
将绑定到全局对象。此外,@
(AKA this
)的值取决于函数的调用方式而不是函数的定义(当然,限制函数),所以如果你说:
b.init()
然后@
内的init
将为b
。然后是你提交给a.onConfirmed
的匿名函数:
a.onConfirmed =>
DemoFilter.onConfirmed @mycallback
将绑定到b
,因为@
在定义该函数时为b
。但是mycallback
不关心,因为它已经绑定到全局对象。
在你的第二个案例中:
b =
init: ->
a.onConfirmed =>
DemoFilter.onConfirmed =>
console.log this
我们在调用@
时再次b
为init
,并且传递给a.onConfirmed
的匿名函数将再次绑定到b
。这意味着:
DemoFilter.onConfirmed => ...
被调用,@
将再次成为b
。这里我们有另一个匿名绑定函数,由于此@
b
是this
,因此@
b
{AKA 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()
被称为。
如果您使用的是类而不仅仅是对象:
<style name="ThemeOverlay.MyApp.ActionBar" parent="ThemeOverlay.AppCompat.ActionBar">
<item name="android:textColorPrimary">@color/white</item>
<item name="android:textColorSecondary">@color/white</item>
</style>
那么你应该看到你期待的行为。