Er passerer flere sett med argumenter som en matrise i Javascript raskere enn flere funksjonskall?

stemmer
0

Etter å ha blitt svakt ubehagelig med flere samtaler til den samme funksjon, med forskjellige parametre (som vist på DOM-delen av koden nedenfor), bestemte jeg å teste ut passerer parametrene for denne funksjonen ved å iterere gjennom en matrise i stedet (som vist i mouse_function_two). Til min overraskelse fant jeg at mouse_function_twogikk betraktelig raskere.

Mitt spørsmål er, vil mouse_function_twobli vurdert bedre Java praksis enn mouse_function_one?

Merk: Jeg er litt bekymret for jeg kan ikke bruke firebugs console.time verktøyet riktig!

innledende forsøk

function mouse_function_one (hover_selector, class_name, add_link) {

  hover_item = $(hover_selector)

  hover_item.each(function(){
    $(this).hover(
      function () {
        $(this).addClass(class_name);
        if ( add_link == true ) {
          $(this).click(function(){
            var href = $(this).find('a').attr('href');
            window.location.href = href;
          });

        }
        else return false;
      },
      function () {
        $(this).removeClass(class_name);
    });
  });
}

Sekund (raskere) forsøk:

function mouse_function_two (args) {

  for (var i=0; i < args.length; i++) {

    hover_selector = $(args[i][0]);
    class_name = args[i][1];
    add_link = args[i][2];

    hover_item = $(hover_selector)

    hover_selector.each(function(){
      $(this).hover(
        function () {
          $(this).addClass(class_name);
          if ( add_link == true ) {
            $(this).click(function(){
              var href = $(this).find('a').attr('href');
              window.location.href = href;
            });

          }
          else return false;
        },
        function () {
          $(this).removeClass(class_name);
        });
    });

  }
}

Klient-kode:

// on dom ready
$(function(){

  console.time('f1');
  mouse_function_one('#newsletter .right', 'hovered', true);
  mouse_function_one('.block-couple div.right', 'hovered', false);
  mouse_function_one('.bulletin', 'selected', true);
  console.timeEnd('f1'); //speed is calculated as 104ms

  args = [];
  args[0] = ['#newsletter .right', 'hovered', true]; 
  args[1] = ['.block-couple div.right', 'hovered', false]; 
  args[2] = ['.bulletin', 'selected', true]; 

  console.time('f2');
  mouse_function_two(args);
  console.timeEnd('f2'); //speed is calculated as 10ms

});
Publisert på 11/09/2009 klokken 20:56
kilden bruker
På andre språk...                            


3 svar

stemmer
3

Er det en flaskehals stykke kode? Ved hjelp av arrays som args åpner deg opp til en hel kategori av bugs som navngitte parametre beskytte deg mot. Den andre kode leser ganske dårlig, og hvis du ikke allerede, gitt tid, vil vise seg å være en komplett ass å feilsøke. Så, med mindre det er kritisk, holde det tilregnelig. Bare når det er virkelig problematisk koden du bør begynne å kaste bort fornuftige språk funksjoner for å skrape ut litt fart.

EDIT: Jo mer jeg ser på koden, synes mindre balanserte ytelses. Det er en rekke ting som du ikke har priset ut som kan føre en til en annen konklusjon som kostnaden ved gjentatt metode påkalling over en enkelt påkallelse og at å fylle arrays osv er ikke benchmarket i deg andre tilfelle.

Svarte 11/09/2009 kl. 21:01
kilden bruker

stemmer
0

Jeg ville vurdere å sende en JSON objekt i ditt tilfelle. Rammeverk som ExtJS og JQuery stole på disse tungt som gjør slikt gir deg stor fleksibilitet (esp. Som API din utvikler seg), og det kan du pakke mye data i en enkelt objekt.

function mouse_function_three (args) { ... }

hvor args ser ut som ...

[{'hover_selector': ... , 'class_name': ... , 'add_link': ...}, {'hover_selector': ... , 'class_name': ... , 'add_link': ...}, ... ]

du kan selv utvide dette ved å inkludere muligheten til å angi standardegenskaper for hvert objekt eiendom som sådan:

{
'default_hover_selector': 'asdf',
'default_class': 'asdf',
'add_link: false,
'items': [{'hover_selector': ... , 'class_name': ... , 'add_link': ...}, {'hover_selector': ... , 'class_name': ... , 'add_link': ...}, ... ]
}

Jeg tror denne løsningen vil gi deg den ytelsen og intuitivity (er at selv et ord) du ønsker.

Svarte 11/09/2009 kl. 21:17
kilden bruker

stemmer
4

Hvis andre rutinen er raskere, er det sannsynligvis fordi den ikke gjør det den er ment å gjøre. Ta en titt på denne tekstutdrag:

  for (var i=0; i < args.length; i++) {

    hover_selector = $(args[i][0]);
    class_name = args[i][1];
    add_link = args[i][2];

    hover_item = $(hover_selector)

    hover_selector.each(function(){
      $(this).hover(
        function () {

To problemer her:

  1. Du bruker implisitte globale variabler.
  2. Blokker i Javascript ikke innføre en ny omfang.

Hver av disse vil føre til det samme bug, sammen de bare gjøre det dobbelt sikker på at det vil skje: nedleggelsene opprettet for hover()hendelseshåndterer fungerer bare inneholde verdiene av den siste sløyfen iterasjon. Når disse handlers er endelig ringte, class_namevil alltid være "selected", og add_linkvil alltid være true. I kontrast, ville den opprinnelige funksjon kalles med et annet sett med parametere hver gang, som ville bli fanget i funksjonens omfanget av hendelsesbehandlinger, og dermed fungerer som forventet.


Som for stilen ... Det er rotete. Du har omsluttet hele funksjonen kroppen i en loop, fjernet beskrivende argumenter, og i stor grad kompliserer kall av funksjonen.

Heldigvis kan du løse problemet jeg påpeke ovenfor, forenkle funksjon, og forenkle hvordan det heter alt på en gang:

// For starters, I've eliminated explicit parameters completely.
// args wasn't descriptive, and all JavaScript functions have an implicit
// arguments array already - so let's just use that.
function mouse_function_three () {

  // use jQuery's array iteration routine:
  // this takes a function as an argument, thereby introducing scope and
  // avoiding the problem identified previously
  $.each(arguments, function() {
    var class_name = this.class_name;
    var add_link = this.add_link;
    var selected = $(this.hover_selector);

    // no need to use selected.each() - jQuery event binding routines
    // always bind to all selected elements
    selected.hover(function() {
      $(this).addClass(class_name);
    },
    function() {
      $(this).removeClass(class_name);
    });

    // bring this out of the hover handler to avoid re-binding
    if ( add_link ) {
      $(selected).click(function(){
        var href = $(this).find('a').attr('href');
        window.location.href = href;
      });

    }
  }); // each set of arguments
}

Du vil da kalle denne nye rutinen som så:

console.time('f3');
mouse_function_three( 
 {hover_selector: '#newsletter .right', class_name: 'hovered', add_link: true},
 {hover_selector: '.block-couple div.right', class_name: 'hovered', add_link: false},
 {hover_selector: '.bulletin', class_name: 'selected', add_link: true}
);
console.timeEnd('f3');

Merk at disse endringene kan meget vel eliminere eventuelle hastighetsforskjell fra første forsøk, så koden effektivt gjør den samme tingen, men med den ekstra trinn av pakking og deretter trekke parametere ...

Svarte 11/09/2009 kl. 21:25
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more