2016-02-29 3 views
1

Отрывок А:Что отличается между этими двумя реализациями

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 выход не то же самое?

В среде Node:

A: выход {}
B: выходной Object b

Я нашел скомпилированный результат совсем то же самое, я не могу понять, почему результат отличается.

ответ

2

Ваша проблема заключается в том, что вы используете простые объекты, а не классы, поэтому => не ведет себя так, как вы ожидаете. Когда вы говорите, это:

o = 
    m: => 

, что точно так же, как говорят:

f = => 
o = 
    m: f 

, и это означает, что @ (AKA this) внутри m является глобальным объектом (window в браузере или, AFAIK, пустой объект в node.js), а не o, как вы ожидаете.

Когда вы говорите:

class C 
    m: => 

CoffeeScript связывается m с 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 (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() 

, то вы должны увидеть поведение вы ожидаете.

Смежные вопросы