2011-07-01 3 views
14

CoffeeScript örneğinin ve sınıf değişkeninin nasıl çalıştığını anlamaya çalışıyorum bu kodla geldim (ve sonuçlar yorumlarda yer alıyor).CoffeeScript Encapsulation ve Değişken Erişimi

class A 
    x: 1 
    @y: 2 

    constructor: (@z) -> 
    #console.log "const x", x #ReferenceError: x is not defined 
    console.log "constructor y", @y #undefined 
    console.log "constructor z", @z # = 3 for A and 6 for B 

    get:() -> 
    #console.log "get x", x #ReferenceError: x is not defined 
    console.log "get y", @y #undefined 
    console.log "get z", @z # = 3 for A and 6 for B 

    get2:() => 
    #console.log "get2 x", x #ReferenceError: x is not defined 
    console.log "get2 y", @y #undefined 
    console.log "get2 z", @z # = 3 for A and 6 for B 

    @get3:() -> 
    #console.log "get3 x", x #ReferenceError: x is not defined 
    console.log "get3 y", @y # = 2 
    console.log "get3 z", @z #undefined 

    @get4:() => 
    #console.log "get4 x", x #ReferenceError: x is not defined 
    console.log "get4 y", @y # = 2 
    console.log "get4 z", @z #undefined 

class B extends A 
    constructor: (@w) -> 
    super(@w) 

console.log '------A------' 
i = new A 3 
console.log "i.x", i.x # = 1 
console.log "i.y", i.y #undefined 
console.log "i.z", i.z # = 6 
i.get() 
i.get2() 
A.get3() 
A.get4() 
console.log '------B------' 
i = new B 6 
console.log "i.x", i.x # = 1 
console.log "i.y", i.y #undefined 
console.log "i.z", i.z # = 6 
console.log "i.w", i.w # = 6 
i.get() 
i.get2() 
B.get3() 
B.get4() 
console.log '------------' 

bazı garip şeyler Buradaki vardır:

x var ben herhangi bir yöntemle ama x var itibaren erişmek için bekliyordum herhangi bir yöntemle veya kurucusundan erişilemiyor
  1. (ReferenceError) . Sadece A veya B (i.x) örneğinden erişebiliyorum. Neden?

  2. @y var @y var değerini herhangi bir yöntemden elde etmeyi bekliyordum, ancak çoğu yerde hiçbir değeri yok (tanımlanmamış değer, bir ReferenceError istisnası değil). @y sadece @ get3 ve @ get4 değerine sahiptir (örnek yöntemler?). Tanımlanırsa, neden değerini alamıyorum?

  3. @y ve @z var Her ikisi de @y ve @z örnek değişkenlerdir, ancak @z yapıcıda başlatıldığı için farklı bir davranışı vardır. @y get3 ve @ get4'te geçerlidir ve @z get ve get2'de geçerlidir. Yine, burada neler oluyor?

Sorun şu ki bu davranışlarla gerçekten kafam karışmış durumda. Bu kod doğru mu? Yani, CS tarafından oluşturulan JS hakkında daha fazla bilgi almalı mıyım?

Tks

cevap

15

İşlev gövdelerinde, @, this anlamına gelir ve sınıf tanımlarında, @, prototip yerine sınıfın kendisini ifade eder. Yukarıdaki örnekte, @y'un tanımı A.y, A.prototype.y değil, 'un çeşitli yöntemler tanımlama yöntemleriyle sınırlandırıldığından, bu konuya başvurmak zor olacaktır. @get isimli yöntemlerden @y kullanarak erişebilirsiniz, çünkü bu durumda this her zaman A anlamına gelir.

x tanımı A.prototype.x atıfta ve böylece get yöntemlerinden size get1 ve get2 yılında @x aracılığıyla erişmek gerekir.

temel bir kılavuz olarak işlev organlarının @ dışında kullanmamaya çalışın ve her şey çok daha mantıklı hale getirecek:

class A 
    constructor: (@a) -> 
    b: 2 
    tryStuff: => 
    console.log(@a) #will log whatever you initialized in the constructor 
    console.log(@b) #will log 2 

EDIT: Eğer statik yöntemler olmak @something olarak tanımlanan yöntemler düşünebiliriz Bu sınıf, onları classname.something() ile arayabilir, ancak statik yöntemler olarak, herhangi bir örnek değişkenine erişemez.

+0

Harika! Bence en önemli şey burada: "Temel bir rehber olarak, fonksiyon gövdelerinin dışında @ kullanmamayı deneyin ve her şey çok daha anlamlı olacaktır" Doğru! –

8

sorularınıza yanıt vermek için:

  1. x = 1 sınıf bünyesinde kapsamı bünyesinde x adında bir değişken oluşturmak olacaktır. Fakat sınıf gövdesi içinde x: 1, prototip üzerinde bir x mülkünü tanımlar. console.log x'u console.log @x olarak değiştirirseniz, 1 alırsınız.
  2. Sınıf gövdesi içinde, @, sınıfa kendisini gösterir. Yapıcı içinde (ve instance.method olarak adlandırılan yöntemlerde), belirli örneğini işaret eder. console.log @y'u console.log A.y olarak değiştirin ve 2 alırsınız. (JavaScript, sınıf aslında yapıcı işlevi olduğu için de, örneğinden sınıfa bir başvuru almak için @constructor kullanabilirsiniz.)
  3. örneğine yapıcı noktalarında @ olduğundan, kuruyorsunuz Örneğin, verilen değere z özelliği.

Ve evet, ben anlamakta tavsiye edersiniz yatan JavaScript Ben @ kadar çok farklı anlamlara sahip olmak için biraz garip biliyorum ama anladıktan sonra bu anlamda bir çok yapar JavaScript en yanıltıcıdır parçaların this (bir dilin, emin olmak için). Bu arada, my book bu konuda daha fazla bilgi var.

+1

Tks! Ve BTW, kitabınızı önceden sipariş ettim: D Hope yakında olsun! –