2015-04-15 16 views
5

1) Ho un compito di implementare jQuery Javascript. Ma per qualche ragione il mio metodo non funziona. Per esempio quando scrivopiccola implementazione di jquery

$('.a').each(function (index) {$(this).append('<b>' + index + '</b>')}) 

esso restituisce

DOMException: impossibile eseguire 'querySelectorAll' su 'Documento': '[object Object]' non è un selettore valido.

, inoltre, non posso usare this.each all'interno di altre funzioni. Ad esempio se avessi usato ciascuno invece di forEach all'interno dell'app non avrebbe funzionato.


<script type="text/javascript"> 
(function() { 
    function $(selector) { 
    if (this instanceof $) return this.search(selector) 
     return new $(selector); 
    } 
    $.prototype = { 
    constructor: $, 
    length: 0, 

    search: function(selector) { 
     var that=this; 
     var elems=Array.prototype.slice 
      .call(document.querySelectorAll(selector)); 
     elems.forEach(function(x,i){that[i]=x;}); 
     this.length = elems.length; 
     return this; 
    }, 

    append: function(text) { 
     if (text instanceof $) { 
     this[0].appendChild(text[0]); 
     for(var i = 1; i < this.length-1; i++) { 
      var p = text[0].cloneNode(true); 
      this[i].appendChild(p); 
     } 
     } else Array.prototype.slice 
      .call(this).forEach(function(x){ 
       x.innerHTML = x.innerHTML + text; 
      }); 

     return this; 
    }, 

    each: function(callback){ 
     for (var i=0;i<this.length;i++){ 
     this[i]=callback.call(this,this[i]) 
     }; 
     return this; 
    }, 

    } 
    window.$ = $; 
}()); 

+3

* "Ho un compito di implementare jQuery Javascript" * Er .... jQuery * ** è *** implementato "on" (in) JavaScript. –

+0

sta funzionando su fiddle qui è [demo] (http://jsfiddle.net/n4aspu8p/) – ozil

+7

Dal modo in cui FYI utilizza il metodo '.each()' su un selettore che sta selezionando un '# id' (che è un singolo elemento) non ha alcun senso. –

risposta

5

Per esempio, quando scrivo

$('#id').each(function (index) {$(this).html('<b>' + index + '</b>')}) 

esso restituisce

DOMException: Impossibile eseguire 'querySelectorAll' on 'documento': '[oggetto Object] 'non è un selettore valido.

Stai facendo $(this) all'interno del vostro each callback. Modo che le chiamate $ con this insieme all'elemento DOM, che non è instanceof $, e così si chiama new $(selector) passando l'elemento DOM. Questo finisce per chiamare this.search(selector) dove, ancora, selector è l'elemento DOM. Quindi chiami querySelectorAll(selector). QSA accetta stringhe, non elementi DOM e quindi l'elemento viene convertito nella stringa "[object Object]" (o su alcuni motori sarà "[object HTMLElement]") e non riesce.

È possibile diagnosticare questi errori a piedi attraverso il codice di dichiarazione-by-economico utilizzando il debugger integrato nel browser. Se hai intenzione di reimplementare jQuery per qualche ragione, devi abituarti a fare esattamente questo: usare pesantemente il debugger, identificare cosa c'è che non va e correggerlo.

In questo caso, per esempio, ti consigliamo di rilevare che selector non è una stringa e gestire tale, per esempio qualcosa di vagamente simile a questo:

search: function(selector) { 
    var that=this, elems; 
    if (typeof selector === "string") { 
    elems = Array.prototype.slice.call(document.querySelectorAll(selector)); 
    elems.forEach(function(x,i){that[i]=x;}); 
    this.length = elems.length; 
    } else { 
    this[0] = selector; 
    this.length = 1; 
    } 
    return this; 
}, 

Ma ci saranno un sacco di altre cose si incorrerà in là di questo, che è necessario il debugger per.

+0

Non riesco a capire perché quando vado fuori da una funzione di accodamento questo sembra ok, ma il passo successivo riguarda ogni funzione e ora questo [0] non è definito. – Aleks

+0

Ho capito! ogni mia funzione non è stata scritta correttamente! – Aleks

+0

Ho ancora 1 domanda! Quando scrivo la funzione .children() voglio che "questo" sia cambiato e restituirlo. Ho ragione quando cancello tutte le proprietà: 0,1,2 ... fino alla lunghezza in 'questo' e poi le sostituisco con quelle nuove che sono figli di questo? Oppure c'è un metodo più elegante per farlo? – Aleks

0

Questo funziona per il vostro caso d'uso, ma per implementare tutti i casi limite sarebbe un po 'più complicato:

(function() { 
    function $(selector) { 
    if (!(this instanceof $)){//forgot new 
     return new $(selector); 
    } 
    if(typeof selector === 'string'){ 
     return this.search(selector); 
    } 
    //assuming selector is a dom object 
    this[0]=selector; 
    this.length=1; 
    } 
    $.prototype = { 
    constructor: $, 
    length: 0, 

    search: function(selector) { 
     var that=this; 
     var elems=Array.prototype.slice 
      .call(document.querySelectorAll(selector)); 
     elems.forEach(function(x,i){that[i]=x;}); 
     this.length = elems.length; 
     return this; 
    }, 
    append: function(text) { 
     if (text instanceof $) { 
     this[0].appendChild(text[0]); 
     for(var i = 1; i < this.length-1; i++) { 
      var p = text[0].cloneNode(true); 
      this[i].appendChild(p); 
     } 
     } else { 
      this.each(function(x){ 
       this.innerHTML = this.innerHTML + text; 
      }); 
     } 
     return this; 
    }, 
    // callback is called with the invoking object to be the dom element 
    each: function(callback){ 
     for (var i=0;i<this.length;i++){ 
     this[i]=callback.call(this[i],i); 
     }; 
     return this; 
    }, 

    } 
    window.$ = $; 
}()); 
$('.a').each(function (index) {return $(this).append('<b>' + index + '</b>')}) 
+0

La tua risposta è molto utile, ma anche ogni funzione dovrebbe essere cambiata in modo tale da richiamare semplicemente la richiamata ma non assegnarla a questo [i] – Aleks

Problemi correlati