J'aime employer une coquille de Javascript en développant les fonctions faites sur commande de Javascript qui contiennent plus que quelques lignes de code. Il est plus facile repérer logique et erreurs de programmation. Le cycle de développement est également plus rapide parce que vous pouvez éviter le cycle du code de chargement sur un web server, rechargeant une page Web, etc.
Quelle est une coquille de Javascript que vous pouvez demander ? D'abord un certain fond. Le Javascript est un langage de programmation fonctionnelle basé par objet faiblement dactylographié complet complexe à l'origine développé par Brendan Eich dans 1995 tout en travaillant au navigateur de Netscape Navigator. Il plus souvent est employé dans des applications Web de client-côté mais est également employé pour permettre l'accès scripting aux objets inclus dans d'autres applications. Le langauge a été normalisé dans les spécifications ECMA-262 (ECMAScript). La version en cours est l'édition 5 qui a été éditée en décembre 2009. Formellement, le Javascript est un dialecte d'ECMAScript dont les spécifications de langauge sont commandées par la base de Mozilla. Il y a d'autres dialectes comprenant ActionScript que la langue scripting a employé dans le flash d'Adobe. Le Javascript évolue toujours pendant qu'une langue et plusieurs versions sont en utilisation quotidienne. La version en cours est le Javascript 1.8.
Le navigateur de Mozilla Firefox a le moteur de Javascript de langue de C.A. Ce s'est orginally appelé Javascript Reference (JSRef) mais de nos jours est connu comme SpiderMonkey. D'autres produits de Mozilla utilisent également ce moteur et il est à la disposition du public sous un tri-permis de MPL/GPL/LGPL. La version en cours, SpiderMonkey 1.7, se conforme au Javascript 1.8 qui est un superjeu ECMA-262 de l'édition 3. Elle se compose d'une bibliothèque (ou du DLL) contenant le moteur de temps d'exécution de Javascript (compilateur, interprète, decompiler, collecteur d'ordures, directeur d'atome et classes standard). Le codebase de SpiderMonkey n'a aucune dépendance sur le reste du codebase de Mozilla. Le codebase contient également les routines pour une interface utilisateurs simple qui peut être liée à la bibliothèque d'exécution afin de faire une ligne de commande coquille.
La coquille de Javascript de SpiderMonkey n'inclut pas le soutien intégré de la ligne de commande traitement d'argument. Récemment j'ai décidé d'ajouter un tel appui de sorte que je n'aie pas dû continuer à écrire essentiellement le code semblable pour analyser la ligne de la commande d'un manuscrit arguments pour vérifier des arguments valides et les options. La décision principale de conception que j'ai prise était ligne de suivre de schéma et de POSIX commande traditionnelle format d'argument et d'analyser la ligne de commande arguments et options utilisant des getopts--comme la fonction.
Plutôt que réinventent la roue que j'ai décidé d'essayer pour mettre en communication une version du getopt de schéma (3) fonction au Javascript. La fonction de getopt de schéma a tenu l'essai du temps et c'est logique interne s'est avéré extrêmement robuste. Ici la source de langage C :
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int opterr = 1, /* if error message should be printed */
optind = 1, /* index into parent argv vector */
optopt, /* character checked for validity */
optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""
/*
* getopt --
* Parse argc/argv argument vector.
*/
int
getopt(nargc, nargv, ostr)
int nargc;
char * const nargv[];
const char *ostr;
{
static char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
if (optreset || *place == 0) { /* update scanning pointer */
optreset = 0;
place = nargv[optind];
if (optind >= nargc || *place++ != '-') {
/* Argument is absent or is not an option */
place = EMSG;
return (-1);
}
optopt = *place++;
if (optopt == '-' && *place == 0) {
/* "--" => end of options */
++optind;
place = EMSG;
return (-1);
}
if (optopt == 0) {
/* Solitary '-', treat as a '-' option
if the program (eg su) is looking for it. */
place = EMSG;
if (strchr(ostr, '-') == NULL)
return (-1);
optopt = '-';
}
} else
optopt = *place++;
/* See if option letter is one the caller wanted... */
if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) {
if (*place == 0)
++optind;
if (opterr && *ostr != ':')
(void)fprintf(stderr,
"%s: illegal option -- %c\n", _getprogname(),
optopt);
return (BADCH);
}
/* Does this option need an argument? */
if (oli[1] != ':') {
/* don't need argument */
optarg = NULL;
if (*place == 0)
++optind;
} else {
/* Option-argument is either the rest of this argument or the
entire next argument. */
if (*place)
optarg = place;
else if (nargc > ++optind)
optarg = nargv[optind];
else {
/* option-argument absent */
place = EMSG;
if (*ostr == ':')
return (BADARG);
if (opterr)
(void)fprintf(stderr,
"%s: option requires an argument -- %c\n",
_getprogname(), optopt);
return (BADCH);
}
place = EMSG;
++optind;
}
return (optopt); /* return option letter */
}
Et voici la fonction fonctionellement équivalente de Javascript que j'ai développée :
//
// getopt.js Finnbarr P. Murphy March 2010
//
// Based on BSD getopt.c Use subject to BSD license.
//
// For details of how to use this function refer to
// the BSD man page for getopt(3). GNU-style long
// options are not supported.
//
var opterr = 1; // print error message
var optind = 0; // index into parent argv array
var optopt = ""; // character checked for validity
var optreset = 0; // reset getopt
var optarg = ""; // option argument
function getopt(nargv, ostr)
{
if ( typeof getopt.place == 'undefined' ) {
getopt.place = ""; // static string, option letter processing
getopt.iplace = 0; // index into string
}
var oli; // option letter list index
if (optreset > 0 || getopt.iplace == getopt.place.length) {
optreset = 0;
getopt.place = nargv[optind]; getopt.iplace = 0;
if (optind >= nargv.length || getopt.place.charAt(getopt.iplace++) != "-") {
// argument is absent or is not an option
getopt.place = ""; getopt.iplace = 0;
return("");
}
optopt = getopt.place.charAt(getopt.iplace++);
if (optopt == '-' && getopt.iplace == getopt.place.length) {
// "--" => end of options
++optind;
getopt.getopt.place = ""; getopt.getopt.iplace = 0;
return("");
}
if (optopt == 0) {
// Solitary '-', treat as a '-' option
getopt.place = ""; getopt.iplace = 0;
if (ostr.indexOf('-') == -1)
return("");
optopt = '-';
}
} else
optopt = getopt.place.charAt(getopt.iplace++);
// see if option letter is what is wanted
if (optopt == ':' || (oli = ostr.indexOf(optopt)) == -1) {
if (getopt.iplace == getopt.place.length)
++optind;
if (opterr && ostr.charAt(0) != ':')
print("illegal option -- " + optopt);
return ('?');
}
// does this option require an argument?
if (ostr.charAt(oli + 1) != ':') {
// does not need argument
optarg = null;
if (getopt.iplace == getopt.place.length)
++optind;
} else {
// Option-argument is either the rest of this argument or the entire next argument.
if (getopt.iplace < getopt.place.length) {
optarg = getopt.place.substr(getopt.iplace);
} else if (nargv.length > ++optind) {
optarg = nargv[optind];
} else {
// option argument absent
getopt.place = ""; getopt.iplace = 0;
if (ostr.charAt(0) == ':') {
return (':');
}
if (opterr)
print("option requires an argument -- " + optopt);
return('?');
}
getopt.place = ""; getopt.iplace = 0;
++optind;
}
return (optopt);
}
La version de langage C de la fonction de getopt exige l'utilisation d'une variable pointeur statique, endroit d'exécuter ses (voir la ligne 54 de getopt.c.) variables statiques magiques telles que l'endroit une fois utilisée dans les fonctions maintiennent leur valeur entre les appels de fonction. La langue de Javascript ne soutient pas des variables statiques ou des indicateurs cependant. Le contournement pour l'issue de variable statique était assez insignifiant. Dans le Javascript les fonctions sont également des objets et nous pouvons créer ainsi une variable qui est un membre d'une fonction. Puisque la variable est maintenant une partie d'un objet, c'est valeur est maintenu entre les appels de fonction. Voir les lignes 19 - 22 de getopt.js. Le contournement pour l'issue d'indicateurs de non était de remplacer l'indicateur par un endroit de variable de corde ainsi qu'une variable, l'iplace, qui est employé pour indexer dans cette corde.
Voici un exemple insignifiant de la façon employer la fonction de getopt dans un manuscrit de coquille de Javscript.
$ cat test.js
#!/bin/js
load("getopt.js");
var opt;
while ((opt = getopt(arguments, "ghf:v")) != '') {
switch (opt) {
case 'f':
print("f option found. Argument is: " + optarg);
break;
case 'g':
print("g option found");
break;
case 'h':
print("usage: " + environment["_"] + " [-f filename] [-g] [-v]");
quit(0);
case 'v':
print("v option found");
break;
case ':':
print("Error - Option needs a value: " + optopt);
quit(1);
case '?':
print("Error - No such option: " + optopt);
quit(1);
}
}
quit(0);
$
$ ./test.js
$ ./test.js -h
usage: ./test.js [-f filename] [-g] [-v]
$ ./test.js -j
illegal option -- j
Error - No such option: j
$ ./test.js -gvf finn
g option found
v option found
f option found. Argument is: finn
$ ./test.js -g -v -f finn
g option found
v option found
f option found. Argument is: finn
$
Si vous regardez étroitement ce manuscrit, vous pouvez noter un certain nombre de constructions peu communes de Javascript. Tout d'abord, il y a un certain nombre d'appels () à une fonction stoppée. La coquille de Javascript ne soutient pas à la façon des indigènes la fonction classique de sortie (). Au lieu de cela les lotisseurs choisissent de fournir une fonction appelée stoppée () qui est essentiellement, pour tous les buts pratiques les mêmes que la fonction de sortie de C (). Une autre construction peu commune est comment la fonction de getopts () est rendue disponible à ce manuscrit utilisant la fonction de charge (). La charge () est une autre fonction qui est seulement disponible dans la coquille de Javascript et est employée pour inclure d'autres dossiers de code source dans un manuscrit. Dans ce cas-ci, la charge (« getopts.js ") fait les getopts () fonctionner et les variables relatives, c.-à-d. optarg, optreset, etc., disponibles à ce manuscrit. Une autre fonction a fourni par la coquille de Javascript est la fonction d'impression () qui écrit au stdout.
Si vous regardez la première ligne de ce manuscrit vous verrez que la méthode de shebang d'appeler un manuscrit, dans ce cas-ci un manuscrit de Javascript, est soutenue juste comme avec les manuscrits de coquille réguliers. Notez l'utilisation de l'environnement [« _ »] dans le message d'utilisation sur la ligne 17 de produire le nom du manuscrit. Il s'avère que la propriété d'appelé de l'objet d'arguments a été désapprouvée dans le Javascript 1.4 et la propriété d'appelé est désuète marqué. Ainsi ni l'un ni l'autre de ces propriétés ne sont disponibles dans la coquille de Javascript pour renvoyer le nom du manuscrit appelant. Heureusement, les réalisateurs de la coquille ont décidé de rendre l'environnement d'utilisateur disponible à la coquille au moyen de l'objet d'environnement.
Voici le manuscrit simple pour énumérer dehors des cordes d'environnement disponibles à vous dans la coquille de Javascript :
#!/bin/js
var key;
for ( key in environment ) {
if (typeof environment[key] == 'string') {
print(key + ' ---> ' + environment[key]);
}
}
Et voici une partie du rendement quand ce manuscrit est couru sur une plate-forme de GNU/Linux :
USERNAME ---> fpm GDM_KEYBOARD_LAYOUT ---> us LANG ---> en_US.UTF-8 SHLVL ---> 3 HOME ---> /home/fpm LOGNAME ---> fpm COLORTERM ---> gnome-terminal PWD --> /work/js/tmp _ ---> ./env.js OLDPWD ---> /work/js
De ce rendement, vous pouvez voir que je suis ouvert une session comme fpm, mon annuaire courant est /home/fpm/js/tmp et le manuscrit que je me suis exécuté pour obtenir ce rendement s'appelle l'env.js et a été exécuté à partir de mon annuaire courant. Ainsi, dans le manuscrit ci-dessus d'exemple de getopts j'avais l'habitude la clef de _ pour rechercher le nom du manuscrit.
Bien, c'est tout que j'ai le temps pour écrire au sujet de cette matière à l'heure actuelle. Je vous encourage à ajouter la coquille de Javascript à votre trousse d'outils et à se familiariser avec elle. J'espère que vous trop trouverez la fonctionnalité de getopts utile quand vous écrivez vos propres manuscrits de coquille de Javascript. Je l'apprécierais si vous me feriez savoir si vous trouvez n'importe quels bogues dans le code.


























