2010-11-26 13 views
2

Fondamentalement, je réécris une partie d'une de mes applications Web. J'avais un script qui réduirait tout ou partie des panneaux de l'interface à la fois, et un autre pour les coder.Erreur de tableau/objet JavaScript extrêmement ennuyeux

Cependant, mes anciennes fonctions avaient l'air vraiment laid, et étaient ennuyeux à taper et pas assez puissant:

function collapse_all() 
{ 
    document.getElementById("panel_1").style.display="none" 
    document.getElementById("panel_2").style.display="none" 
    document.getElementById("panel_3").style.display="none" 
} 
function expand_all() 
{ 
    document.getElementById("panel_1").style.display="" 
    document.getElementById("panel_2").style.display="" 
    document.getElementById("panel_3").style.display="" 
} 

Maintenant, j'ai ceci:

function panel() //first variable in argument is collapse or expand, all others are panels to act on 
{ 
    var panels = panel.arguments 
    alert(typeof panel.arguments) 
    var mode = panels.shift() //here's my problem 
    if(mode=="collapse") {mode="none"} 
    if(mode=="expand") {mode=""} 
    var items = panels.length 
    for (i = 0;i < items;i++) {document.getElementById(panels[i]).style.display=mode} 
} 

panel("collapse","panel_1","panel_2","panel_3") 

J'ai un problème cependant. Firebug me dit que panels.shift() n'est pas une fonction. Avec un peu de Google, j'ai réussi à découvrir que panel.arguments n'est pas un tableau mais un objet, donc je ne peux pas utiliser de méthodes de tableau. Je suis vraiment confus quant à la façon dont je pourrais soit convertir l'objet dans un tableau ou trouver une autre solution de contournement, car je ne sais rien à peu près sur les objets JavaScript. Un exemple de code serait très apprécié.

+3

Vous devriez vraiment utiliser ';' à la fin de vos instructions.S'appuyer sur JavaScripts n'est pas ce que vous voulez. Croyez-moi. – jwueller

+0

Merci pour la suggestion, mais je ne suis pas un développeur web professionnel et j'ai lu c'est seulement un problème quand vous avez plusieurs lignes de code écrasées sur une ligne (et j'utilise des points-virgules pour cela) et quand la ligne suivante commence Je n'ai jamais eu de problèmes avec ça ... –

+0

Eh bien, puisque vous n'êtes "pas un développeur web professionnel", je vous recommande vivement de suivre les conseils d'elusive et d'utiliser le point-virgule si vous pensez en avoir besoin ou pas. améliorer la lisibilité et supprimer toute ambiguïté que le compilateur pourrait rencontrer –

Répondre

4

Vous pouvez convertir l'objet arguments dans un tableau comme celui-ci:

var argsArray = Array.prototype.slice.call(arguments); 

Ce que cela fait est d'utiliser la méthode slice commune à tous les réseaux via Array.prototype pour créer un véritable objet Array du tableau comme arguments. call() (une méthode de toutes les fonctions) est utilisée pour appeler cette méthode slice avec une valeur this de arguments et aucun paramètre, ce qui a pour effet de copier tous les éléments de this dans un nouveau tableau. Cela peut sembler sournois ou hacky mais il est en fait conçu dans la langue: voir la note au bas de section 15.4.4.10 of the ECMAScript 3rd Edition spec.

De même, au sein d'une fonction, l'objet arguments est fourni en tant que variable, vous n'avez donc pas besoin d'y accéder en tant que propriété de l'objet fonction comme vous le faites. Dans votre cas, utilisez simplement arguments plutôt que panel.arguments.

+0

Merci, ça marche super bien que mes autres réponses soient utiles, je vais choisir celle-ci parce que c'est la première réponse à donner moi exactement ce dont j'avais besoin –

+0

Pouvez-vous expliquer plus en profondeur ce que 'Array.prototype.slice.call()' est en train de faire? –

+1

@Derek: Explication ajoutée –

4

Vous pouvez garder beaucoup plus simple (nettoyer votre mise en forme, des points-virgules, etc.):

function panel() 
{ 
    var panels = Array.prototype.slice.call(arguments); 
    var displayMode = (panels[0] == "collapse" ? "none" : ""); 

    for (var i = 1; i < panels.length - 1; i++) 
    { 
     document.getElementById(panels[i]).style.display = displayMode; 
    } 
} 

Aussi, si vous réécrivez votre application, il pourrait être un bon moment pour envisager d'utiliser des choses comme jQuery. Vous pouvez assigner chacun de vos panneaux un certain nom de classe, et de réduire votre code à quelque chose comme ceci:

function panel(hide) 
{ 
    $('.className').css({ display: (hide ? 'none' : '') }); 
} 

que vous pouvez utiliser comme ceci:

panel(true); // or 
panel(false); 

Ou, parce que maintenant il est si syntaxiquement simple, vous pourriez tout aussi bien créer deux fonctions distinctes pour que votre code soit simple et que vous sachiez exactement ce qu'il va faire à partir des noms de fonctions seul:

function showPanels() { 
    $('.className').css({ display: '' }); 
} 

function hidePanels() { 
    $('.className').css({ display: 'none' }); 
} 

Et enfin, si vous ne vous inquiétez pas à le faire via CSS, vous pouvez vraiment écourter votre script à ce qui ne peut être plus clair:

function showPanels() { 
    $('.className').show(); 
} 

function hidePanels() { 
    $('.className').hide(); 
} 

Cheers!

+1

+1! Bon conseil! – jwueller

+0

vraiment un excellent conseil. Ceci est un exemple parfait de la façon dont jQuery aide à nettoyer le code javascript. –