24 janvier 2014

JavaScript : condition ou opération mathématique

NB 141221 : utile avec la manipulation et conversion des types JavaScript
cf. mémo opérateurs JavaScript.

Pour l'efficacité du code, l'on peut vouloir éviter une condition par le recours à une clé ou un index appelant telle fonction :

var resultat;
var faire = [
 function(){ resultat = "a"; },
 function(){ resultat = "b"; }
];
//variations de x entre 0 et 1, d'où :
faire[x]();
/* a la place de if (x == 1) etc. */ 

Voir par exemple Tal Bereznitskey - Javascript Hacks for Hipsters.

Imaginons maintenant une interface où deux zones (de 56 * 64) sont cliquables, en bas à gauche et en haut à droite de la page, et détection du clic avec 'if' :

document.body.onclick = function(ze){
 var D = document,
  d = D.documentElement,
  b = D.body,
  x = ze ? ze.pageX : event.offsetX,
  y = ze ? ze.pageY : event.offsetY,
  X = d.scrollLeft > 0 ? d.scrollLeft : b.scrollLeft,
  Y = d.scrollTop > 0 ? d.scrollTop : b.scrollTop,
  w = d.clientWidth,
  h = d.clientHeight;
 if ((x < X + 57 && y > Y + h - 65) || (x > X + w - 57 && y < Y + 65)){
  agir();
} }

Il peut y avoir deux équivalents mathématiques à la structure conditionnelle, une formule avec modulo et l'autre avec division :

//avec modulo :
Math.ceil((x - x % (X + 57) + Y + h - 65 - (Y + h - 65) % y) / (x - x % (X + 57) + Y + h - 65 - (Y + h - 65) % y + 1)) * Math.ceil((X + w - 57 - (X + w - 57) % x + y - y % (Y + 65)) / (X + w - 57 - (X + w - 57) % x + y - y % (Y + 65) + 1));

//avec division
Math.ceil((Math.floor(x / (X + 57)) + Math.floor((Y + h - 65) / y)) / (Math.floor(x / (X + 57)) + Math.floor((Y + h - 65) / y) + 1)) * Math.ceil((Math.floor((X + w - 57) / x) + Math.floor(y / (Y + 65))) / (Math.floor((X + w - 57) / x) + Math.floor(y / (Y + 65)) + 1));

Le résultat de chaque formule est zéro au clic dans l'une des zones cliquables, un sinon.

var agir = [
 function(){ /* etc. */ },
 function(){ return; }]
document.body.onclick = function(ze){
 var D = //...
 agir[formule]();
}

En terme de performance, au-delà du fun :

  1. Mathematical operation vs conditional statement · jsPerf montre que la structure conditionnelle reste, dans ce cas, bien plus performante que le modulo (tests faits sur Mac donnant perte de 67% sur Firefox 27 et de 90% sur Chrome 29 - ordre de résultat retrouvé sur Win) ;
  2. par ailleurs, pour information, la formule avec modulo est par elle-même équivalente à la formule avec division (Firefox), ou plus performante (avec division : perte de 24% sur Chrome) : Modulus vs division · jsPerf - toujours sur Mac.

Pour finir sur le cas d'un index sans longue formule, Index vs condition · jsPerf, sur Mac, la structure conditionnelle est beaucoup plus rapide avec Firefox et légèrement plus lente avec Chrome.

Aucun commentaire: