Demandez Satyam: écriture du code propre et débogable
2 septembre 2010 à 07:13 par Satyam | En développement | 1 Commentaire
Satyam (alias Daniel Barreiro) est un temps YUI contributeur de longue et l'une des plus prolifiques, les experts généreux dans le forums YUI . Il est également l'auteur d'un nouveau livre sur YUI 2.8.0, 2.8.0 YUI: L'apprentissage de la Bibliothèque . Cet article dans le "Demandez Satyam" série a été suggéré par JoeDev . Bien que sa mise au point (comme la mise au point du nouveau livre) est le plus souvent sur YUI 2, bon nombre des pratiques décrites ici sont applicables à YUI 3 ainsi - et au développement frontend en général, indépendamment de votre bibliothèque de choix.
Avant de poster une question dans les forums bibliothèque YUI , il ya beaucoup de choses que vous pouvez faire par vous-même et, si vous avez vos outils à portée de main, vous pouvez trouver la réponse tout seul en un rien de temps. En outre, le code propre est un code robuste, beaucoup moins susceptibles de se briser lorsqu'ils sont soumis au stress. Les bonnes pratiques non seulement d'éviter les erreurs fatales (le type que vous conduisez sur le canal IRC ou des forums à la recherche d'aide), mais ils la surface des avertissements sur des erreurs mineures et vous aider à rester à l'écart du bord fatal.
Dans cet article, je vais jeter un oeil à certaines de ces meilleures pratiques. Certains d'entre eux sont spécifiques à développer avec YUI , mais la grande majorité s'appliquent au développement frontend quel que soit votre choix de la bibliothèque Ajax.
JSLint
Un voyage à travers JSLint fait partie du processus de construction de YUI. JSLint, lui-même entièrement écrit en JavaScript, est comme un compilateur, mais sans la génération de code. Il sera, cependant, produire beaucoup de messages d'erreur et les avertissements utiles qu'un compilateur. Un interprète navigateur JavaScript pardonne beaucoup d'erreurs et assume par défaut que vous seriez peut ignorer; pardonne JSLint peu, et il vous renvoie à de meilleurs choix dans votre programme.
JSLint est disponible en plusieurs formats; l' outil Générateur de YUI l'utilise comme une application en ligne de commande autonome, mais vous pouvez aussi l'intégrer dans Eclipse ou autre IDE ou-ou-moins capables éditeur plus vous utilisez - il ya même un Yahoo! Widget pour JSLint .
Si les lignes zillion de code dans la bibliothèque de YUI peut passer par JSLint sans quelques erreurs et des avertissements (il ne peut pas éviter un certain nombre de choses), donc si votre code. Je trouve JSLint très utile quand je suis fatigué. Bean comptage en fin de soirée est une perte de temps, vous êtes susceptible de manquer les erreurs les plus évidentes. JSLint ne se soucie pas à quelle heure de la journée il est et sera point pour accéder directement à cette tranche ne correspondent pas bouclés ou variable qui est mal orthographié à la racine du problème.
JSLint est très utile si vous conservez votre code propre dès le départ. Si vous n'avez jamais utilisé JSLint avant et l'essayer sur une application qui est déjà plusieurs centaines de lignes, il vous inonder avec autant d'avertissements qu'il sentira qu'il entrave votre travail plus que ça aide. Cependant, ce qui se passe seulement les premières fois. Une fois que vous apprendre à rester à l'écart de mauvaises pratiques de codage, de diagnostic JSLint seront peu nombreuses et droit au but; votre erreur réelle, celle qui est conduite, vous écrous, de toute évidence se démarquer. Dans l'intervalle, JSLint vous apprendra à faire de votre code sûr et robuste.
Alors, n'attendez pas pour une erreur difficile à afficher. Si vous n'avez jamais utilisé JSLint, essayez-le avec ce que vous croyez être un bon code, il ne serait pas aussi bon que vous avez assumé. Comme Douglas Crockford (auteur de JSLint) dit: «JSLint se blesser vos sentiments." Mais c'est un petit prix à payer pour un meilleur code.
Variables globales et utilisé
Une des choses JSLint vous avertira porte sur l'utilisation de variables globales. Il ne faut pas les variables globales, sauf ceux que vous connaissez, comme ceux créés automatiquement comme window ou document et celles pour les bibliothèques que vous utilisez comme YAHOO (en YUI 2 ) ou YUI (en YUI 3 ). Vous pouvez également créer un réseau mondial unique pour votre propre espace de noms.
Les variables globales sont dangereuses , et il ya généralement plus d'eux que vous pouvez attendre, d'ailleurs, «extras» tels que les mashups et les bannières pourrait ajouter plusieurs d'entre eux. Depuis la window HTML DOM espace de noms peuvent être omis dans les noms composés, window.name , window.length et window.location devenir le variables globales name , length et location . Avez-vous jamais utilisé les noms de variables telles dans votre code? Je ne veux pas dans leur sens, mais DOM HTML comme noms de domaine de tous les jours dans un tableau - comme le nom d'une personne, la longueur d'un objet ou l'emplacement d'un livre sur l'étagère. Que faire si vous utilisez ces variables sans les déclarer? On pourrait penser que length est d'abord undefined , mais, en fait, si vous ne déclarez pas vos locaux propre copie de celui-ci (et l'initialisation), length sera une référence à window.length . Et si vous affectez quelque chose à location , vous risquez de provoquer un utilisateur de naviguer loin de la page en cours. Ici, je ne fais que donner des exemples de collisions possibles avec le navigateur intégré de variables, mais si vous commencez à ajouter des bibliothèques à partir d'autres sources, les chances de collisions augmente. La coloration syntaxique JavaScript utilisé dans les exemples YUI utilise la variable globale dp que sa racine et le nombre de variables globales de script Google pourrait ajouter lorsque vous insérez une carte ou un autre outil dans votre page est impoli, pour dire le moins.
Ce n'est pas simplement que vous souhaitez à l'étape à la légère par rapport aux variables d'autres personnes - en restant en dehors de l'espace de nommage global, vous réduisez le risque qu'ils étape sur le vôtre (ou que vous marcher sur vos propres). Avec les discussions asynchrones se tisser autour de l'autre, comme c'est souvent le cas dans les applications JavaScript moderne, vous ne pouvez pas vraiment être sûr de l'ordre dans lequel vos différents éléments de code s'exécute et ce que la variable globale sera laissée à ce que la valeur par qui. La seule approche raisonnable est de les éviter autant que possible.
Les variables globales peuvent également pointer vers une faute de frappe. Si vous avez une variable globale que vous ne voulais pas avoir et que vous avez utilisé une variable avec un nom similaire, vous seriez peut-être mal orthographié un d'entre eux: qui est, vous avez peut-être déclarée avec un nom et utilisé avec une autre orthographe différente . Il peut aussi vouloir dire que vous l'avez déclaré après l'avoir utilisé, ce qui signifie que lors de l'exécution que vous pourriez trouver votre variable non initialisée que vous vous attendiez.
En utilisant this
En utilisant this est souvent gênante pour les débutants car il est facile de perdre la trace de l'endroit où nous sommes dans la chaîne de portée. Tant que nous n'aurons un peu de pratique, pour garder trace du champ d'application peut être un problème. En outre, l'élaboration d'un style de codage et une structure de la demande contribue grandement, après tout, il s'agit de savoir où les choses endroit que vous. Si vous apprenez à organiser votre code de façon cohérente et de magasins d'état dans des endroits logiques ( this à un tel endroit points), de l'information dans votre programme sera facile à trouver. Tout débogueur va vous montrer ce que this points à chaque étape. C'est toujours une bonne chose de vérifier d'abord si this n'est référence à l'objet que vous attendez. Un grand nombre de fois où nous avons un bug, c'est-être parce que this pointe vers window . Il ya plusieurs situations qui peuvent produire ce résultat.
Si nous avons une méthode avec une fonction intérieure, quand nous appelons cette fonction intérieure il ne sera pas la portée de l'appelant, mais plutôt celle de window . Cet exemple montre que la fonction interne ne partage pas le champ d'application de la méthode dans laquelle elle est contenue:
someObject var = { outerFunction: function () { console.log ('externe', this); / / affiche l'objet externe {} var = innerFunction function () { console.log («interne», this); / / affiche la fenêtre intérieure }; innerFunction (); } }; someObject.outerFunction ();
Il ya deux façons de résoudre ce problème. Dans cet exemple, nous demandons JavaScript pour corriger le champ d'application à l'aide call() :
someObject var = { outerFunction: function () { console.log ('externe', this); / / affiche l'objet externe {} var = innerFunction function () { console.log («interne», this); / / affiche objet interne {} }; . InnerFunction appel (ce); } }; someObject.outerFunction ();
Dans l'exemple suivant, nous profitons de la possibilité pour les fonctions internes de partager les variables contenant des fonctions. Nous créons une variable self qui nous initialisons à la valeur de this dans la fonction externe. Nous pouvons alors utiliser self dans la fonction interne de se référer à la fonction externe:
someObject var = { outerFunction: function () { console.log ('externe', this); / / affiche l'objet externe {} var auto = this; var = innerFunction function () { console.log («interne», soi-même); / / affiche objet interne {} }; innerFunction (); } }; someObject.outerFunction ();
Enfin, des événements, la portée de l'auditeur est celui de l'élément sur lequel l'auditeur est joint:
someObject var = { outerFunction: function () { console.log ('externe', this); / / affiche l'objet externe {} YAHOO.util.Event.on («bouton», la fonction «clic», () { console.log («interne», this); / / affiche id="button"> <button intérieure }); } }; someObject.outerFunction ();
À moins que nous ajuster la portée de l'auditeur lors de la mise en place
someObject var = { outerFunction: function () { console.log ('externe', this); / / affiche l'objet externe {} YAHOO.util.Event.on («bouton», la fonction «clic», () { console.log («interne», this); / / affiche objet interne {} }, Ce vrai,); } }; someObject.outerFunction ();
Ceci s'applique également aux composants YUI. Si nous écoutons un événement click sur une cellule DataTable, un nœud TreeView ou un MenuItem, la portée des auditeurs seront celles de l'occurrence du composant YUI qui possède l'événement - à moins qu'il soit explicitement autrement.
Bacs à sable pour les applications
Une autre bonne façon de garder votre code propre est de commencer avec un squelette propre. Le style des applications JavaScript de codage a changé au fil du temps. Aujourd'hui, la plupart des développeurs utilisent deux styles différents: un pour les applications et l'autre pour la bibliothèque de composants. La plupart des YUI 2 exemples reflètent le style ancien, où nous avons utilisé YAHOO.namespace de créer un espace de noms pour notre propre code.
Aujourd'hui, pour nos applications, nous utilisons principalement un bac à sable unique a déclaré dans le cadre d'une fonction anonyme qui exécute onDOMReady :
YAHOO.util.Event.onDOMReady (function () { Dom var = YAHOO.util.Dom, Event = YAHOO.util.Event, Lang = YAHOO.lang; yourVariable var = initialValue, moreOfTheSame = otherInitialValue; var MyFunction1 = function (...) { / / Corps de la fonction; }; var myFunction2 = function (...) { / / Corps de la fonction; }; ... });
Cette technique présente plusieurs avantages.
- Nous vérifions l'état de préparation du droit DOM dès le départ, veiller à ce que tous les morceaux de code HTML que nous pourrions vouloir manipuler sont présents et sûr à utiliser.
- La fonction fournie à
onDOMReadyn'est pas perdu à tous, c'est le contenant du bac à sable et, parce que c'est anonyme, il ne pollue pas l'espace de nommage global. - Nous avons immédiatement commencer à définir nos variables, y compris des alias ou des noms courts pour nos objets les plus souvent utilisées. Cela a plusieurs autres avantages de ses propres:
- Nous économiser de la frappe
- Le compresseur peut compresser YUI nos noms courts, alors qu'il ne peut pas compresser un nom global comme
YAHOOou de ses propriétés telles queutilouMenu, peu importe à quelle profondeur ils se trouvent. Si elles sont ancrées dans un nom mondiaux tels queYAHOO, toute la branche est intouchable. Ainsi, notre court noms déjàDom,EventetLangpourrait être encore réduit àA,BetClorsque le compresseur est exécuté à la compilation. - L'interprète n'a pas besoin de résoudre maintes et maintes fois les noms longs. Chaque point dans un nom tel que
YAHOO.util.Event.onDOMReadyest temps consommé dans une table de symboles rechercher. - Toutes les variables seront disponibles n'importe où dans cette fonction anonyme, même avec des fonctions définies à l'intérieur, sauf si une variable du même nom a été défini en eux. Fondamentalement, c'est comme si un environnement sous-mondial a été défini au sein, et toutes les variables, il sera disponible n'importe où simplement par son nom.
- Pour les variables dans le bac à sable nous n'avons pas besoin d'utiliser
thisqui nous donne des maux de tête tels lors de l'utilisation traditionnelle technique de programmation orientée objet de faire même la fonction principale d'un objet.
Nous définissons nos fonctions. Nous pouvons le faire avec le
vardéclaration, comme je l'ai fait ci-dessus ou lafunctiondéclaration, il ya une différence subtile mais elle est surtout hors de propos. J'utilise levardéclaration à souligner le fait que ils sont tout aussi accessibles que les autres variables: on peut y accéder n'importe où dans le bac à sable.
Bien sûr, cela repose sur la capacité de JavaScript pour nous permettre de définir des fonctions au sein des fonctions et sur le fait que les fonctions internes ont accès à toutes les variables définies dans la fonction externe. En fait, chaque fonction que vous définissez crée un nouvel environnement local accessible à tous les autres fonctions au sein.
Sandbox est le moyen standard de faire les choses dans YUI 3:
YUI (). Usage ("module1", ..., la fonction (Y) { / / C'est le bac à sable });
Les espaces de noms pour les bibliothèques
Bien que la technique sandboxing est idéal pour les applications finales, ce n'est pas bon pour les bibliothèques. Qu'est-ce qui se passe dans le bac à sable reste dans le bac à sable, complètement invisible au monde extérieur. Toutefois, lorsque vous définissez un utilitaire de bibliothèque ou d'un composant de votre choix, vous souhaitez ré-utiliser, donc il doit être universellement accessibles (ce qui n'est pas le même comme étant purement mondiale). Tout ce que vous définir sous YAHOO.example - par exemple, YAHOO.example.myUtility - est globalement accessible. Vous pouvez y accéder par son nom complet une fois qu'il a été défini. myUtility , en tant que membre de l'économie mondiale YAHOO , n'est pas mondial, mais il est globalement accessible.
Quand on construit des bibliothèques, on utilise habituellement le bac à sable pour notre code et l'espace de nommage pour le partage, comme ceci:
(Function () { var = MyClass function () { / / Ce serait le constructeur }; MyClass.prototype = { / / Propriétés et méthodes }; YAHOO.namespace ('MyLibrary'); YAHOO.MyLibrary.MyClass = MyClass })();
Nous créons un bac à sable en tout définir au sein d'une fonction anonyme, qui nous exécuter immédiatement (voir tous ces parenthèses il?, Ils veulent dire «prendre le résultat de la définition de cette fonction et l'exécuter"). Ici, nous n'attendons pas pour les DOM à être prêt, les bibliothèques font rarement, car l'application qui les utilise est responsable de vérifier que tout est en place. Dans le bac à sable, nous avons les mêmes avantages que le bac à sable précédente. On peut définir des noms courts pour rien que nous utilisons souvent, même pour la classe, nous définissons: aucun d'eux ne sera visible à l'extérieur. Puis, pour le rendre accessible globalement, nous créons un espace de noms de notre propre place et notre classe a récemment créé en elle.
YUI Logger
Disons que nous avons notre code belle et propre, sans erreurs JSLint ou des avertissements, mais nous avons encore des problèmes à déboguer. YUI peut être utile pour nous dire ce qui ne va pas. Pour le code de production, nous avons généralement charger les versions minified des composants YUI, mais il ya aussi deux autres versions. -Version debug.js est celui qui peut nous aider à découvrir les problèmes. Par exemple, nous pourrions utiliser la méthode Collection Dom setStyle à, disons, changer la couleur d'un bloc de texte. Le changement ne se produit pas et nous ne pouvons pas trouver ce qui ne va pas. Le fichier dom-debug.js a cette ligne utile, qui est supprimé dans le -min version:
YAHOO.log ("element" + el + 'n'est pas défini "," Erreur "," Dom "); Ceci est exécutée lorsque setStyle tente de localiser l'élément à porter le titre et ne le trouve pas. Le message d'erreur sera vraisemblablement un id de l'élément mal orthographié ou une erreur comme il est si difficile de choisir, après une longue journée de regarder le même code.
Il est facile d'obtenir l'enregistreur en marche; il vous suffit de comprendre ses fichiers :
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.8.1/build/logger/assets/skins/sam/logger.css"> src="http://yui.yahooapis.com/2.8.1/build/yahoo-dom-event/yahoo-dom-event.js"> <script </ script> src="http://yui.yahooapis.com/2.8.1/build/dragdrop/dragdrop-min.js"> <script </ script> src="http://yui.yahooapis.com/2.8.1/build/logger/logger-min.js"> <script </ script>
La base yahoo-dom-event global est plus susceptible d'être déjà là alors que le Drag & Drop de dépendance option est pratique pour déplacer la fenêtre enregistreur de la route. Ensuite, il suffit d'ajouter:
var = new myLogReader YAHOO.widget.LogReader (); Ensuite, c'est une question de chargement de la -debug versions des fichiers de composant et tous les messages qu'ils produisent sera montré. La quantité d'informations peut être écrasant ainsi, il est sage de ne pas charger toutes -debug versions à la fois. Le Logger peut également filtrer les informations qu'il affiche et vous pouvez décocher la catégorie Info de messages de se concentrer sur les avertir et Fail. Les filtres n'ont aucune incidence sur ce qui est connecté, que ce qui est montré; Logger enregistre tous les messages, indépendamment du fait que le lecteur du journal les affiche ou non. Il n'ya qu'une seule file de messages par l'application et l'exploitation forestière va commencer dès que le fichier de composant Logger est chargé, il n'a pas d'importance si elle est affichée ou non.
Une autre stratégie power-user pour YUI débogage avec le contrôle Logger est de profiter de la capacité à tirer parti de Logger le navigateur de la console (dans les navigateurs pris en charge):
YAHOO.widget.Logger.enableBrowserConsole (); Avec cette ligne de code, vous pouvez rediriger tous les messages Logger au navigateur de la console, qui est une partie naturelle de votre flux de travail dans le développement dans tous les cas.
La seule chose ennuyeuse sur le Logger est de se rappeler de changer les fichiers des composants de la minified, des agrégats et des combos à la -debug versions. En cela, comme toujours, le Configurateur de dépendance est une grande aide, cliquez sur le -debug bouton en haut à gauche et il va produire la liste correcte des fichiers.
Et, maintenant que je l'ai mentionné:
Vérifiez vos dépendances
C'est une bonne idée lorsque vous démarrez avec YUI pour prendre un exemple qui ressemble de près à ce que vous voulez faire et de le modifier. Comme vous ajouter plus de fonctionnalités, vous prenez des morceaux provenant d'autres exemples et de les incorporer dans votre application en développement. Une source fréquente de problèmes sont les dépendances. Beaucoup de gens coller les fichiers de dépendance de chaque exemple dans son application, la duplication certains d'entre eux, encore et encore. Missing, double ou à des dépendances de l'ordre peut produire des erreurs inattendues. Ne pas avoir le YAHOO Global objet chargé avant toute autre chose est très certainement va être fatale. En tout cas, quelque chose de chargement deux fois va certainement augmenter le temps qu'il faut chargement de votre page.
Enfin, si vous utilisez vos propres serveurs de charger la bibliothèque YUI, vous pourriez avoir le chemin de base pour votre copie de la bibliothèque de mal. Si vous avez Firebug, allez sur l'onglet Net et vérifier qu'il n'ya pas de lignes en rouge. Ces signifierait qu'une ressource demandée n'a pu être trouvée.
Débogage
Le Firebug add-on pour Firefox est encore le meilleur débogueur autour, plus il est gratuit. Par défaut, lorsque le débogueur est activé, le "Break sur toutes les erreurs» option est activée, ce qui signifie que Firebug s'arrêtera au point où il trouve une erreur et affiche le message d'erreur et le code source. Certaines de ces erreurs sera le même que JSLint aurait diagnostiqué alors JSLint est toujours le premier endroit à commencer - en particulier parce que Firebug ne peut signal une erreur sur chaque course tout en JSLint peut les signaler à la fois. Certaines erreurs ne se présentent lors de l'exécution, afin que le débogueur est la seule option. Chaque fois que vous arrivez à une telle rupture, la première chose à vérifier est this , un mot de quatre lettres de la plus délicate de tri.
Lorsque vous utilisez un bac à sable, débogueurs montrent habituellement des variables locales et des arguments, mais ils ne seront pas normalement offre de montrer aux variables dans les fonctions contenant, tels que ceux déclarés dans le bac à sable et utilisé depuis les fonctions internes. Le débogueur sera en mesure de démontrer leur valeur si vous le demander explicitement par leur nom, mais il ne sera pas les afficher automatiquement. Une autre alternative est de les rendre universellement accessibles. Par exemple, depuis YAHOO.example est toujours disponible (quand YUI 2 est sur la page), si vous voulez garder un oeil sur un certain composant en tout temps vous pouvez simplement y copier:
var = new myTree YAHOO.widget.TreeView (l '«arbre-conteneur»); YAHOO.example.myTree = myTree;
Nous ajoutons la dernière attribution pendant le débogage afin que nous puissions garder un oeil sur l'instance TreeView pendant le débogage depuis myTree seraient normalement dans le bac à sable et invisibles ailleurs.
Ne pas utiliser les membres à commencer par souligner
Beaucoup de gens utilisent le débogueur pour trouver les noms des variables ou des propriétés qui détient les informations dont ils ont besoin. Parfois, ces informations sont stockées dans les propriétés commençant par un underscore, comme _nodes . Par convention, ce sont des propriétés privées, et non pour un usage général. JavaScript applique pas vrai concept de membres privés ou protégés; ainsi le trait de soulignement est la méthode classique pour signaler l'intention du promoteur de classe pour garder que la propriété privée. Ces propriétés peuvent présenter une tentation (après tout, vous pouvez les voir là, dans le débogueur), mais il ya quelques bonnes raisons pour lesquelles il n'est pas sage de les utiliser dans vos programmes.
Tout d'abord, que les interfaces publiques sont pris en charge. Puisque vous n'êtes pas censé utiliser une propriété commençant par un underscore, le développeur de classe est libre de le modifier à tout moment. Le développeur aurait dû prévoir un mécanisme public d'accéder à cette même valeur, par exemple, un _nodes la propriété privée pourrait avoir un getNodes() ou une méthode de nodes attribut de configuration. Chacune de celles-ci seraient l'interface publique à cette même valeur. La deuxième raison de ne pas utiliser les propriétés des traits de soulignement, c'est que leurs accesseurs pourriez avoir besoin pour produire un effet secondaire qui accédant à la propriété privée serait de contourner complètement. La composante serait alors laissée dans un incompatibles, des États fragiles.
Donc, si vous utilisez le débogueur pour trouver une valeur et vous le trouverez dans une propriété en commençant par un underscore, ne l'utilisez pas. Allez plutôt à la documentation de l'API et de chercher dans l'index Méthodes pour certains getXxxx() méthode avec un nom similaire ou dans les attributs d'index de configuration. Évitez d'utiliser des variables privées.
Traces de la pile
La bibliothèque de YUI est robuste et fiable. En cas de rupture du débogueur dans la bibliothèque de YUI, il est plus probable que c'est à cause d'une erreur induite par le code que par une défaillance dans YUI elle-même. JavaScript a été conçu pour transporter, toujours faire face aux erreurs du mieux que possible. La bibliothèque de YUI fait de même. Le -debug versions auront des contrôles supplémentaires et émettre des messages de diagnostic, mais ils sont tous supprimés dans les versions minified. Si vous constatez une erreur dans un fichier YUI il est probable que il y est arrivé par entêtement pur, mais n'essayez pas de trouver l'erreur il. Lorsque le débogueur s'arrête ce n'est pas parce qu'il a trouvé la cause de l'erreur, mais parce que l'interpréteur JavaScript ne peut plus continuer.
Ruptures dans les fichiers minified ne sont pas utiles, si vous obtenez un message tel que ...
F n'est pas un objet à la ligne 7 de dom-min.js ... Il est inutile de se demander dans le forum à ce sujet. Tout d'abord, F est un alias généré par YUI Compressor pour remplacer un plus long, nom de la variable descriptive dans le fichier original non compressé, d'autre part, les quelques premières lignes d'un fichier de composant sont habituellement prises par le copyright, ce qui le compresseur YUI respecte toujours . Et puisque le compresseur YUI supprime également tous en ligne de nouveaux personnages, comme il le fait avec d'autres espaces blancs, tout le code exécutable dans dom-min.js est dans les lignes 7, 8 et 9 - si le numéro de ligne ne dit pas grand chose non plus .
C'est alors que l'onglet Trace de la pile dans le droit de sous-groupe de l'onglet Script de Firebug (ou là où vous pouvez trouver la trace de la pile dans votre débogueur) est très utile. Il vous dit comment vous y êtes arrivé. Voici une capture d'écran de Firebug:

L'ordre du jour sur le dessus du panneau de droite, createEvent() , est le nom de la fonction où l'instruction en cours est: l'une est sous l'endroit où createEvent() a été appelé; celui ci-dessous que la fonction qui a appelé la précédente; et ainsi de suite. La plupart des débogueurs vous permettra de sélectionner l'un de ces points de trace et de voir comment vous avez obtenu à l'endroit où vous êtes. Firebug vous permet également de vérifier la valeur des variables à chacun des points de trace. On peut voir dans le panneau secondaire à gauche sur la flèche jaune pointant vers createEvent() . Nous avons été chanceux cette fois, car il pointe toujours sur la ligne contenant le code incriminé, mais ce code pourrait être n'importe où dans cette ligne, heureusement, createEvent() se trouve au début de la ligne. Voir les variables et les arguments? B , G , L ... il n'ya pas de deviner ce que les noms d'origine aurait pu, comme cela est le compresseur YUI au travail. Toutefois, notez que YAHOO est intact et les avis de copyright soient conservées.
Vous pourriez ne pas reconnaître la plupart des noms dans la trace de la pile, car ils pourraient être des fonctions au sein des fonctions au sein de la bibliothèque de YUI elle-même. Finalement, vous pouvez voir les noms de fonctions vous reconnaître. Dans cette image, je sais showAlbums , qui appelle le constructeur de la REDT classe (qui est le code que j'ai écrit). Je n'ai pas la moindre idée de quoi que ce soit d'autre. C'est là que je vais aller chercher ... pour ceux que je connais.
Si vous n'êtes pas sûr, vous pouvez parcourir la liste complète. Si vous voyez le code compressé (en supposant que vous n'avez pas encore votre propre compressé), il suffit de les ignorer ou de passer à la version non-minified des fichiers source YUI. Mais l'accent principalement sur les noms que vous reconnaissez qui appartiennent à votre propre code. Notez que Firebug utilise (?)() des traces qu'il ne peut pas nommer. Habituellement, votre code dans le bac à sable sera signalé cette façon depuis le bac à sable est contenue dans une fonction anonyme. À tout moment dans votre telles traces, vérifier les valeurs des variables que vous avez fourni comme arguments; certains d'entre eux pourraient ne pas être ce que vous avez assumé. Vérifiez-les contre les API docs pour voir si elle est une valeur d'argument valable.
Si les valeurs des arguments et des variables que vous voyez ne sont pas concluants, au moins vous pouvez placer un point d'arrêt avant droit de votre code appelle la composante YUI. Vous pourriez alors être en mesure de voir comment vous avez obtenu dans le pétrin.
traces de la pile sont souvent ignorés par les développeurs, mais avec une tendance JavaScript pour continuer à creuser lui-même dans un trou toujours plus profond, qui tente d'exercer, il est bon d'être en mesure de venir à la surface de regarder autour. Comme pour toutes les techniques de débogage, il ne fonctionne pas toujours, mais il est bon de savoir qu'il est là. Soyons honnêtes, si vous avez lu jusqu'ici, vous savez ce que le désespoir est.
Appels asynchrones
Un lot de l'interactivité qui caractérise applications Web2.0 est basé sur la capacité de gérer les événements asynchrones. En contraste avec le style original des applications web, où toutes les interactions impliquées en attente d'une nouvelle page pour être livré à partir du serveur, les applications modernes interactive avec mise en place des choses et l'écoute pour toute de plusieurs événements possible de se passer ... et puis de répondre à ces événements. Nous avons mis auditeurs pour les clics ou les frappes et ou d'autres événements programmatiques; elles sont généralement intuitive. Appels asynchrones et leurs rappels, cependant, sont souvent difficiles à comprendre.
L'erreur la plus commune que je vois dans les implémentations sur les forums est de placer le droit de code après un appel asynchrone tels que Connection Manager's asyncRequest() ou DataSource de sendRequest() méthodes, en supposant que ce code sera exécuté quand l'opération est terminée. Lorsque vous appelez cette fonction, vous êtes juste d'amorçage de l'opération, ne pas l'exécuter dans son intégralité. Aucune donnée ne sera disponible après l'appel à la méthode asynchrone. Seuls la demande pour de telles données auraient été produites à ce jour. Le serveur doit le recevoir et les traiter, et la réponse (si jamais il arrive) n'est toujours pas à l'avenir. C'est pourquoi de telles opérations asynchrones, nous utilisons des fonctions de rappel.
Un rappel est comme la fonction que nous assigner comme un écouteur pour un événement tel qu'un clic sur un bouton dans un formulaire, quand l'utilisateur clique sur, l'auditeur est appelé. Le rappel d'un événement asynchrone est beaucoup comme ça, tout comme nous envoyer un formulaire à un utilisateur de remplir, nous envoyons un message de requête au serveur, et tout comme nous d'attendre le formulaire rempli doit être soumis à dos notre programme, nous attendons la réponse envoyée par le serveur de revenir à nous. Nous ne pouvons pas savoir quand l'utilisateur soumet le formulaire ou le serveur d'envoyer la réponse, c'est pourquoi nous avons mis ce pour une action de l'utilisateur que nous appelons un écouteur d'événements et pour un événement asynchrone que nous appelons une fonction de rappel. Il pourrait sembler la réponse du serveur est rapide si elle n'est pas instantanée, mais cela signifie âges dans le temps CPU.
Le débogage des appels asynchrones
Parfois il n'ya pas d'autre alternative que d'une seule étape dans le code. Soyez prudent lorsque vous arrivez à des appels asynchrones tels que Connection Manager's asyncRequest() méthode, DataSource de sendRequest() ou DOM window.setTimeout() . Ces lancer une requête asynchrone des données sur le serveur ou de retarder une action un moment donné et leurs rappels obtenir appelé lorsque les données ont été reçues ou que le temps s'est écoulé. Il ya deux aspects à considérer: d'abord, le débogueur n'est pas un pas dans la fonction de rappel automatique. Si vous voulez rattraper la réponse, vous devez mettre un point d'arrêt à l'intérieur de la fonction de rappel. Beaucoup de gens atteignent le point d'appeler la méthode asynchrone et attendre le mode pas à pas à reprendre dans le rappel lorsque l'opération asynchrone est terminée. Cela n'arrivera pas; le thread d'exécution ne découlent pas automatiquement dans le rappel, et le débogueur ne peut pas s'attendre à ce que l'on figure sur.
Deuxièmement, lorsque vous atteignez la ligne avec l'appel asynchrone, mis le point d'arrêt dans le rappel, puis laisser tourner l'application. Habituellement, tout ce qui va après l'appel asynchrone n'est pas vraiment important, en fait, l'appel asynchrone est normalement à la fin d'une fonction, car il n'y a pas beaucoup à faire jusqu'à ce que la réponse arrive. Ne pas en une seule étape au cours de l'appel asynchrone, parce que le débogueur gardera l'interpréteur JavaScript en attente et, lorsque la réponse arrive ou les laps de temps, il ne sera pas atteint depuis l'interprète a été gelé et incapable de s'en occuper. Donc, si vous cliquez sur Pas à pas, quand vous arrivez à l'appel asynchrone, assurez-vous que le point d'arrêt dans le rappel, puis cliquez sur Exécuter alors l'interpréteur JavaScript est actif et capable de gérer la réponse.
Pour la répétition d'événements tels que les rappels à window.setInterval() ou d'autres opérations critiques du temps, il est préférable de ne pas mettre des points d'arrêt en eux. Pendant que vous êtes en attente, de nombreux événements ne seront pas atteints. Il est généralement préférable d'utiliser console.log ou l'enregistreur de YUI simplement signaler que l'événement qui se passe et montrent une critique quelques valeurs. Ne pas utiliser window.alert() pour la même raison, il met les mains sur le navigateur et les événements que vous aimez ne seront pas atteints.
Conclusion
Il existe de nombreux outils pour nous aider à découvrir ce qui se passe dans nos programmes. Avec les bons outils à portée de main, nous pouvons trouver une erreur en moins de temps que ce qu'il nous faut pour écrire une question dans les forums. La première étape, cependant, est d'écrire du bon code et fiables et faire JSLint partie intégrante de votre processus de développement.
Partager et prolonger: Ajouter aux Favoris del.icio.us | Digg it! | reddit!
1 Commentaire »
Flux RSS pour les commentaires sur ce post.
Laissez un commentaire

Copyright © 2006-2011 Yahoo! Tous droits réservés. Politique de confidentialité - Conditions d'utilisation
Propulsé par WordPress sur Yahoo! Web Hosting .



i Oui simplement mis d'accord sur que votre conclusion est juste.
Commentaire de fonctions Melbourne - Septembre 2, 2010 #