2010-12-15 97 views
9

Mise à jour Ajouté jsFiddle - voir en bas de postdifférence de performance jQuery sans « chaque »

J'ai actuellement une fonction qui réactive les tous les champs handicapés à l'écran. Bien qu'il fonctionne assez rapidement (< 1ms selon Firebug profileur), je suis en train de ranger tout le Javascript dans mes écrans et pensé que cette fonction particulière semblait être un peu redondant:

function enableDisabledFields() { 
    $('[disabled]').each(function(i) { 
     $(this).removeAttr('disabled'); 
    }); 
} 

J'étais sous l'impression que ces 3 lignes pourraient être remplacées comme suit, et je m'attendais sinon mieux que au moins performances égal.

function enableDisabledFields() { 
    $('[disabled]').removeAttr('disabled'); 
} 

Apparemment, je me trompe. Le premier fonctionne beaucoup mieux et je ne comprends pas très bien pourquoi. Même l'ajout de sélecteurs supplémentaires tels que: input ne fait aucune différence (et en fait aggrave le problème).

Quelqu'un peut-il éclaircir ma confusion? Merci.

Modifier Je devrais ajouter que nous utilisons une ancienne version de jQuery - 1.3.1 je crois.

Éditer2 Voici quelques liens jsFiddle. S'il vous plaît gardez à l'esprit que je peux mal comprendre profiler Firebug (que je pense semble être le cas).

Option 1: http://jsfiddle.net/kcut7/

Option 2: http://jsfiddle.net/ZgZpU/

+1

Avez-vous une chance de créer quelques pages sur http://jsfiddle.net/? –

+0

quand vous dites "performer beaucoup mieux", quels chiffres obtenez-vous pour les deux? – Ben

+0

les deux font la même chose? – kobe

Répondre

4

Dans jQuery 1.3.1 est mis en œuvre de façon légèrement différente aux versions actuelles:

v1.4.4

removeAttr: function(name, fn) { 
    return this.each(function(){ 
     jQuery.attr(this, name, ""); 
     if (this.nodeType === 1) { 
      this.removeAttribute(name); 
     } 
    }); 
}, 

v1.3.1

jQuery.each({ 
    removeAttr: function(name) { 
     jQuery.attr(this, name, ""); 
     if (this.nodeType == 1) 
      this.removeAttribute(name); 
    } 
}, function(name, fn){ 
    jQuery.fn[ name ] = function(){ 
     return this.each(fn, arguments); 
    }; 
}); 

La fonctionnalité est plus ou moins le même, les deux utilisent .each() dans tous les cas pour traiter la liste. La définition de chaque n'a pas fondamentalement changé du tout:

// args is for internal usage only 
each: function(object, callback, args) { 
    var name, i = 0, 
     length = object.length, 
     isObj = length === undefined || jQuery.isFunction(object); 

    if (args) { 
     if (isObj) { 
      for (name in object) { 
       if (callback.apply(object[ name ], args) === false) { 
        break; 
       } 
      } 
     } else { 
      for (; i < length;) { 
       if (callback.apply(object[ i++ ], args) === false) { 
        break; 
       } 
      } 
     } 

    // A special, fast, case for the most common use of each 
    } else { 
     if (isObj) { 
      for (name in object) { 
       if (callback.call(object[ name ], name, object[ name ]) === false) { 
        break; 
       } 
      } 
     } else { 
      for (var value = object[0]; 
       i < length && callback.call(value, i, value) !== false; value = object[++i]) {} 
     } 
    } 

    return object; 
}, 

donc juste une boucle en utilisant .call() beaucoup.

Je pense que la seule explication à une augmentation de la vitesse avec un boucle supplémentaire.each() externe serait la taille de la structure de données étant très réduite à un seul élément avant d'être transmis à travers plusieurs couches d'appels, ce qui est probablement créer des copies de données locales à chaque niveau. Passer la liste entière à traiter crée peut-être beaucoup plus de frais généraux, aurait besoin de profiler l'utilisation du tas à dire.

+1

Une alerte pro-ness! :RÉ – Fred