2010-04-19 16 views
9

tekil sorunları, sunucuya biraz bilgi gerektiren sunucuJavaScript 'sınıf' ve ben (tekil değil) başka bir nesneyi kullanmak bir tekil nesne var

function RequestManager(params, success, error){ 
    //create an ajax manager 
    this.param = params; 
    this._success = success; //callbacks 
    this._error = error; 
} 

RequestManager.prototype = { 

    require: function(text){ 
    //make an ajax request 
    }, 
    otherFunc: function(){ 
    //do other things 
    } 

}

sorun i tekil nesne içinden myRequestManager.require arayamayacağımı olduğunu. Firebug consolle diyor ki: "myRequestManager.require bir işlev değil", ancak sorunun nerede olduğunu anlamıyorum. Bu durumun uygulanması için daha iyi bir çözüm var mı?

+0

Hatayı almadım ... RequestManager'ı oluştururken params işlevi nereden geliyor? –

+0

Verdiğiniz kod örneğinde, params tanımlanmamıştır. Örneğinizden bir şey mi bıraktın? – Robusto

cevap

6

Kodunuz, sizin teklif ettiğiniz sırada bulunuyor, değil mi? Singleton, kaynağında RequestManager'un üstünde görünüyor mu?

Eğer öyleyse, bu senin problemin. (!):

  1. fonksiyon Oldukça ince, ama bunları gösterdiğin sırayla alıntı kod sizin iki bit varsayarak vardır, burada şeyler (ben daha aşağıda açıklayacağım) sırası var RequestManager tanımlanmıştır.
  2. Tekil koşunuzu oluşturan anonim işleviniz, örneğin RequestManager örneğini başlatmayı içerir.
  3. RequestManager prototipinin yerine yenisi eklenir. myRequestManager örnek prototip değiştirildi önce örneği beri

onunla bu (yeni) prototip üzerinde tanımlı işlevler yok. Örneklendiğinde yerinde olan prototip nesnesini kullanmaya devam ediyor.

Sen ya, RequestManager 'ın prototip özelliklerini ekleyerek ziyade değiştirerek kod yeniden sıralamayı kolayca düzeltebilirim

örn: Eğer var çünkü çalışır

RequestManager.prototype.require = function(text){ 
    //make an ajax request 
}; 
RequestManager.prototype.otherFunc = function(){ 
    //do other things 
}; 

değil yerini prototype nesnesi, eklediniz. myRequestManager, ekledikleri nesneyi kullandığı nesneye eklediğinizden (yapıcı işlevinin prototype özelliğinde yeni bir nesne ayarlamayı tercih ettiğinden) görür.

Neden böyle oluyor biraz teknik ve çoğunlukla spekülasyona gidiyorum. Tercüman yeni bir "yürütme bağlamı" (örneğin, bir işlev veya global   — örneğin sayfa düzeyinde   — bağlamına girdiğinde), bir şeyler yaptığı sıra, aşağıdan yukarı kaynak sırası değildir, aşamalar vardır. . İlk aşamalardan biri bağlamda tanımlanan tüm fonksiyonları başlatmaktır; Bu,'dan önce olur, herhangi bir adım adım kod çalıştırılır. Tüm ihtişamıyla ilgili detaylar 10.4.1 (global kod), 10.4.3 (işlev kodu) ve 10.5 (bildirim bağlamaları) içinde the spec, ancak temel olarak işlevler, adım adım kodun ilk satırından önce oluşturulur.:-)

Bu izole bir deney örnekle görmek en kolay şudur: kullanıyor Thing1 örneği bir foo özelliği olmadığı için bunu çalıştırırsanız

<!DOCTYPE HTML> 
<html> 
<head> 
<meta http-equiv="Content-type" content="text/html;charset=UTF-8"> 
<title>Test Page</title> 
<style type='text/css'> 
body { 
    font-family: sans-serif; 
} 
</style> 
<script type='text/javascript'> 
// Uses Thing1 
var User1 = (function() { 
    var thing1 = new Thing1(); 

    function useIt() { 
     alert(thing1.foo()); 
    } 

    return useIt; 
})(); 

// Uses Thing2 
var User2 = (function() { 
    var thing2 = new Thing2(); 

    function useIt() { 
     alert(thing2.foo()); 
    } 

    return useIt; 
})(); 

// Thing1 gets its prototype *replaced* 
function Thing1() { 
    this.name = "Thing1"; 
} 
Thing1.prototype = { 
    foo: function() { 
     return this.name; 
    } 
}; 

// Thing2 gets its prototype *augmented* 
function Thing2() { 
    this.name = "Thing2"; 
} 
Thing2.prototype.foo = function() { 
    return this.name; 
}; 

// Set up to use them 
window.onload = function() { 
    document.getElementById('btnGo').onclick = go; 
} 

// Test! 
function go() { 

    alert("About to use User1"); 
    try 
    { 
     User1(); 
    } 
    catch (e) 
    { 
     alert("Error with User1: " + (e.message ? e.message : String(e))); 
    } 

    alert("About to use User2"); 
    try 
    { 
     User2(); 
    } 
    catch (e) 
    { 
     alert("Error with User2: " + (e.message ? e.message : String(e))); 
    } 
} 

</script> 
</head> 
<body><div> 
<div id='log'></div> 
<input type='button' id='btnGo' value='Go'> 
</div></body> 
</html> 

Eğer User1 başarısız görebileceğiniz gibi (prototip değiştirildiğinden), ancak User2 çalıştığı için Thing2 örneğinden yararlanır * çünkü (prototip artırılmış, değiştirilmemiş) kullanır.

+1

+1 JavaScript kaldırma tuzağı yine grev! – bobince

+1

Açıklama ve örnekler için teşekkürler, prototip ile prototip değiştirilen prototip arasındaki farkı alamadım. Şimdi çalışıyor :-) –

+1

@Kucebe: Harika! Evet, bu ince bir şey. :-) Sadece prototipler değil, bazen sizi ısırtacak olan şeylerin sırasıdır (kesinlikle * ben *). –