JavaScript ist eine objektbasierte Skriptsprache.
Die Sprache ist unter dem – wenig gebräuchlichen – Namen ECMAScript durch die Ecma International standardisiert. JavaScript bezeichnet ursprünglich die Implementation durch Netscape, wie JScript jene durch Microsoft. Im allgemeinem Sprachgebrauch wird aber meistens JavaScript als Name verwendet.
Ihr Hauptanwendungsgebiet sind Programme, deren Code im Quelltext von Webseiten eingefügt wird und den der Webbrowser interpretiert, d. h. ausführt. Es gibt daneben JavaScript, das auf dem Webserver abläuft, z. B. als Active Server Pages oder im Apache Cocoon, und vom Web unabhängige Anwendungen, z. B. im Windows Script Host.
Im Quelltext einer Webseite können HTML-Elementen wie Hyperlinks, Formularfelder oder Bilder Funktionen zugeordnet sein, die der Webbrowser bei bestimmten Ereignissen wie Mausbewegungen und -klicks sowie Tastatureingaben ausführt. Die in JavaScript programmierten Funktionen können Inhalte der Seite verändern und das Erscheinungsbild daraufhin anpassen, z. B. die Farbe eines Links ändern, während der Mauszeiger über dem Symbol des Links steht. Das hat den Vorteil, dass der Webserver nicht für jede Änderung eine neue Seite zum Computer des Benutzers schicken muss. JavaScript kann auch weniger sichtbare Arbeiten erledigen, z. B. das Prüfen einer Benutzereingabe auf eine plausible Schreibweise, bevor sie zum Server geschickt wird. Dabei wird der Server von diesen Arbeiten und dem Hin- und Herschicken der Daten entlastet. Oft prüft ein JavaScript schon beim Seitenaufbau, welchen Browser der Webseiten-Besucher nutzt, und veranlasst sofort, dass eine für diesen Browser optimale Darstellungsvariante der HTML-Seite geladen wird.
JavaScript wird entweder im Klartext zwischen in den HTML-Quelltext geschrieben oder in eine externe Datei (meistens mit der Endung .js) ausgelagert.
JavaScript wurde ursprünglich von Netscape entwickelt und ist inzwischen die im WWW meistgebrauchte clientseitige Skriptsprache. Die meisten Websites verwenden heute JavaScript. Trotz des ähnlichen Namens und einer ähnlichen Syntax ist JavaScript grundlegend verschieden von der Programmiersprache Java, das von Sun Microsystems stammt. Die Namensgleichheit erklärt sich vor allem aus Marketinggründen und den damals sehr populären Java-Applets. Die Syntax wurde auch aus diesem Grund weitgehend der von Java angeglichen. JavaScript setzt im Gegensatz zu Java und anderen klassisch objektorientierten Sprachen aber keine Klassen ein, sondern verwendet stattdessen Objekte als Prototypen.
Die Grundfunktionalität von JavaScript ist heute als ECMAScript oder ECMA-262 standardisiert und wird von den meisten Browsern weitgehend unterstützt (JavaScript in der Version 1.5 entspricht ECMA-262 Version 3). Microsoft entwickelte für den Internet Explorer eine Skriptsprache, die Netscapes JavaScript weitgehend gleicht, die jedoch schon aus rechtlichen Gründen anders genannt werden musste, nämlich JScript. JScript ist ebenfalls eine konforme Implementation von ECMAScript.
Über das Document Object Model (DOM) kann JavaScript auf alle Elemente der Webseite zugreifen, dessen Elemente ändern oder sogar neue erzeugen, nachdem die Seite vom Browser geladen und dargestellt wurde. Dieses wird als Dynamic HTML (DHTML) oder dynamisches HTML bezeichnet.
| 18. Sep. 1995 | Mit der Vorversion des Navigator 2.0 veröffentlicht Netscape einen Browser mit einer eingebetteten Skriptsprache, die zu diesem Zeitpunkt LiveScript heißt und von Brendan Eich entwickelt wurde. Die Sprache soll u. A. Formulareingaben des Benutzers vor dem Absenden überprüfen können. |
| 4. Dez. 1995 | Netscape und Sun Microsystems benennen die Sprache aus Marketinggründen in JavaScript um (JavaScript 1.0). |
| 29. Apr. 1996 | Mit der ersten Beta-Version des Navigator 3.0 führt Netscape JavaScript 1.1 ein. Neu ist die Möglichkeit, auf Bilder zuzugreifen und sogenannte Rollover-Grafiken zu erstellen. |
| Mai 1996 | Microsoft stellt mit der Beta-Version des Internet Explorer 3 seinen ersten JavaScript-fähigen Browser vor. Die Skriptsprache heißt allerdings aus rechtlichen Gründen JScript und entspricht etwa dem Stand des Netscape Navigator 2. JScript schlägt einen eigenen Weg der Entwicklung ein, bleibt aber im Wesentlichen kompatibel zu JavaScript. |
| 15. Okt. 1996 | Mit der Ankündigung des Netscape Communicators wird JavaScript 1.2 veröffentlicht. |
| 4. Juni 1997 | Der Netscape Communicator 4.0 mit JavaScript 1.2 erscheint. |
| Juni 1997 | Die „European Computer Manufacturers Association“ veröffentlicht ihren Standard ECMA-262 (ECMAScript), der zusammen mit Netscape entwickelt wurde und die Grundelemente einer Skriptsprache standardisieren soll. |
| 1. Okt. 1997 | Microsoft gibt den Internet Explorer 4 heraus, der den Sprachumfang von JavaScript 1.1 abdeckt. Darüber hinaus werden eigene Erweiterungen veröffentlicht, die zu Kompatibilitätsunterschieden zwischen Navigator und Internet Explorer führen und eine DOM-ähnliche Syntax zur Verfügung stellen, die es ermöglicht, auf alle Elemente der Webseite zuzugreifen und diese beliebig zu verändern. |
| 23. Feb. 1998 | Der neue Browser Mozilla wird mit der Freigabe des Quelltextes des Netscape Navigators auf den Weg gebracht. |
| April 1998 | ECMAScript ist nun ISO-Norm: "ISO/IEC 16262:1998 Information technology - ECMAScript language specification". |
| Juli 1998 | Eine Beta-Version des Netscape Communicators 4.5 wird veröffentlicht. JavaScript trägt nun die Versionsnummer 1.3. Erstmals zu finden war diese JavaScript-Version schon in der Version 4.06 des Netscape Communicators. |
| Oktober 1998 | Netscape stellt JavaScript 1.4 vor. Diese Version ist vollständig kompatibel mit ECMA-262. Ein Browser mit der Unterstützung dieser Version erscheint jedoch nicht. |
| April 2000 | Netscape gibt die Preview Release 1 des Navigator 6 heraus, welcher auf dem sich in der Entwicklung befindlichen Browser Mozilla in der Version 0.6 beruht. Diese Version implementiert erstmals JavaScript 1.5 und das DOM Level 1. |
| 5. Juni 2002 | Mozilla 1.0 erscheint mit JavaScript 1.5. |
| 29. Nov. 2005 | Mozilla Firefox 1.5 erscheint mit JavaScript 1.6. |
Derartige Anwendungen werfen ein ungünstiges Licht auf die Autoren einer Website und führen dazu, dass viele Anwender die JavaScript-Unterstützung ihres Browsers deaktivieren.
Object als allgemeiner Prototyp, von dem alle Objekte abgeleitet sind
Function als Prototyp für Funktionen
Array als Prototyp für Arrays
String als Prototyp für Zeichenketten
Boolean als Prototyp für Boolesche Variablen
Number als Prototyp für Zahlen (64-Bit Gleitkommazahlen gemäß IEEE 754)
Math stellt Konstanten und Methoden für mathematische Operationen bereit. Math kann nicht als Konstruktor dienen.
Date für Operationen mit Daten bzw. Zeitpunkten und Datumsformaten
RegExp für reguläre Ausdrücke
Die restlichen Objekte, die beim clientseitigen JavaScript verwendet werden, entstanden historisch vor allem durch die Netscape-Spezifikationen (window, document usw.). Zahlreiche Unterobjekte von document wurden mittlerweile durch DOM HTML standardisiert (title, images, links, forms usw.). Aktuelle Browser unterstützen zudem DOM Core und andere W3C-DOM-Standards sowie Erweiterungen von Microsoft JScript.
String, numerische Werte den Typ Number und boolesche Werte den Typ Boolean. Des Weiteren gibt es die Typen null und undefined. Dieses sind sogenannte einfache Werte (primitive values). Alle anderen Werte sind Objekte (objects)
und haben den Typ Object. Funktionen, Arrays, Datumsobjekte und reguläre Ausdrücke sind so gesehen spezielle Objekte.
Beim direkten Notieren von Zeichenketten, Zahlen oder booleschen Variablen entstehen einfache Werte (z.B. bei var variable = "Beispieltext";). Beim Nutzen der jeweiligen Konstruktorfunktionen hingegen entstehen Objekte (z. B. bei var variable = new String("Beispieltext");).
JavaScript ist nicht typisiert, d. h. der Datentyp einer Variablen kann sich während der Ausführung eines Scripts ändern, was manchmal zu Fehlern bzw. unerwünschten Effekten führt.
objekt.eigenschaft
bzw.
objekt.methode(*)
Allen Objekten können zur Laufzeit neue Eigenschaften und Methoden hinzugefügt werden. In diesem Beispiel wird eigenschaftA mit 1 belegt:
objekt.eigenschaftA = 1;
Eigenschaften können auch in der folgenden Form angesprochen werden, wobei der Eigenschaftsname als Zeichenkette angegeben wird:
objekt* = 1;
Durch diese Schreibweise können alle Eigenschaften eines Objektes in einer For ... in-Schleife durchlaufen werden. In diesem Beispiel wird „objekt.eigenschaftA = 1“ ausgegeben.
for (var eigenschaftsname in objekt) { window.alert("objekt." + eigenschaftsname + " = " + objekt*); }
Entfernen lassen sich Eigenschaften mit dem Operator delete:
delete objekt.eigenschaftA;
beispielobjekt = new Object(); | Neues Objekt erstellen |
beispielobjekt = {}; | Neues Objekt erstellen (Alternative) |
beispielarray = new Array(1,2,3,4) | Neues Array anlegen |
beispielarray = * | Neues Array anlegen (Alternative) |
beispielarray.length | Anzahl der Elemente zurückgeben |
beispielarray.concat(anderesArray) | Zwei Arrays verbinden |
beispielarray.join(Trennzeichen) | Array in Zeichenkette umwandeln |
beispielarray.pop() | Letztes Element aus Array löschen |
beispielarray.push(neuerWert) | Ein neues Element an das Ende des Array anhängen |
beispielarray.reverse() | Reihenfolge der Elemente umkehren |
beispielarray.sort(VergleichsFunction) | Elemente sortieren |
"Zeichenkette" oder 'Zeichenkette', d. h. man schreibt die Zeichenkette zwischen Anführungszeichen. Stattdessen kann auch der String-Konstruktor verwendet werden: new String(10) beispielsweise ergibt die Ziffernfolge '10', einen String.
beispielstring = "Hallo" | Neuen String anlegen |
beispielstring = new String("Hallo") | Neuen String anlegen (Alternative) |
beispielstring.length | Gibt die Länge des Strings wieder |
beispielstring.toLowerCase() | Gibt den String komplett kleingeschrieben wieder |
beispielstring.toUpperCase() | Gibt den String komplett großgeschrieben wieder |
beispielstring.split(Trennzeichen) | Wandelt den String durch ein Trennzeichens in einen Array mit Teilstrings um |
string.indexOf(andererString) | Gibt die Position des ersten Vorkommens des angegebenen Strings wieder. Wird dieser nicht darin gefunden, so gibt die Methode -1 zurück |
string.lastIndexOf(andererString) | Gibt die Position des letzten Vorkommens des angegebenen Strings wieder. Wird dieser nicht darin gefunden, so gibt die Methode -1 zurück |
Während die Kurzschreibweise "Hallo" ein einfacher Wert des Typs String angelegt wird, entsteht bei new String("Hallo") ein Objekt des Typs Object. In der Praxis ist es meistens unerheblich dieses zu unterscheiden. Im Falle jedoch der objektunabhängigen Funktion eval(), die einen String-Wert entgegennimmt und diesen als JavaScript-Ausdruck interpretiert, zeigt sich der feine Unterschied:
eval("25+25") | ergibt 50 (Typ Number) | => wie auch eval(new String("25+25").toString())
|
eval(new String("25+25")) | ergibt "25+25" (Typ String) | => wie auch eval('"25+25"')
|
Die Funktion eval() gibt deshalb verschiedene Werte zurück, weil ihr im ersten Fall ein String zur Auswertung übergeben wird, im zweiten Fall hingegen wird ihr die Referenz auf einen String übergeben.
beispielzeitpunkt = new Date() | Ein neues Date-Objekt erzeugen |
Math.max(Zahl1, Zahl2) | Gibt die größere der beiden angegebenen Zahlen zurück |
Math.min(Zahl1, Zahl2) | Gibt die kleinere der beiden angegebenen Zahlen zurück |
Math.pow(Basis, Exponent) | Gibt das Ergebnis der Exponentialrechnung zurück |
Math.random() | Gibt eine Zufallszahl, die größer oder gleich 0 und kleiner als 1 ist, zurück |
Math.round(Zahl) | Rundet die angegebene Zahl |
Math.abs(Zahl) | Gibt die absolute Zahl, d. h. den Betrag der angegebenen Zahl zurück |
if ... elseif .... Stattdessen kann man zwei If-Anweisungen verwenden, von denen die Erste die Zweite als Else-Code aufnimmt:
if (Bedingung) { Anweisungen; } else { if (Bedingung) { Anweisungen; } else { Anweisungen; } }
Beliebig viele "Else if"-Blöcke sind erlaubt:
if (Bedingung) { Anweisungen; } else if (Bedingung) { Anweisungen; } else if (Bedingung) { Anweisungen; } else { Anweisungen; }
function meineFunktion (Parameter1, Parameter2, Parameter3) { Anweisungen; return Ausdruck; }
Funktionen können auch ineinander verschachtelt werden. Die inneren Funktionen sind dabei nur innerhalb der äußeren verfügbar.
Neben der obigen gängigen Notation kann alternativ eine sogenannte Function Expression verwendet werden:
var Addieren = function (zahl1, zahl2) { return zahl1 + zahl2; };
Da alle Funktionen vom Prototyp-Objekt Function abgeleitet sind, kann eine Funktion zudem mithilfe des Function-Konstruktors notiert werden. Das Besondere an dieser Schreibweise ist, dass sowohl Parameternamen als auch der Code des Funktionskörpers als Strings notiert werden.
var Addieren = new Function("zahl1", "zahl2", "return zahl1 + zahl2;");
Beispiel: Der ursprüngliche Algorithmus von Euklid zur Ermittlung des größten gemeinsamen Teilers: Es ist eine geometrische Lösung; die kleinere Strecke wird jeweils von der größeren abgezogen.
function gcd (a, b) { while (a != b) { if (a > b) { a = a - b; } else { b = b - a; } } return a; }
Die Anzahl der Parameter beim Aufruf muss nicht zwingend mit der Anzahl der Parameter in der Funktionsdefinition übereinstimmen. Wenn beim Aufruf weniger Parameter angegeben werden, dann wird für die übrigen Parameter einfach der Wert undefined eingesetzt. Weiter kann innerhalb der Funktion auch über das arguments-Array auf die Parameter zugegriffen werden.
Beispiel für Verwendung einer Funktion höherer Ordnung:
Array.prototype.fold = function (functor) { var result = 0; for (var i = 0; i < this.length; i++) { result = functor(result, this*); } return result; } var array = new Array(21,33,17,12); var addition = function (a, b) { return a + b; }; var sum = array.fold(addition);
Ebenso ist es möglich curried functions zu schreiben:
function add (a, b) { if (arguments.length < 1) return add; if (arguments.length < 2) { return function (c) { return a + c; }; } else { return a + b; } }
new erstelltes Objekt zu initialisieren. In diesem Fall spricht man von einem Konstruktor oder einer Konstruktor-Funktion. Innerhalb dieser Funktion kann das neue Objekt über die Variable this angesprochen werden. Darüber können dem Objekt Eigenschaften angehängt werden.
function meinObjekt () { this.zahl = 1; }
Neue Instanz erstellen:
var objekt = new meinObjekt();
Zugriff auf die Eigenschaft zahl, es wird „1“ ausgegeben:
window.alert(objekt.zahl);
Im Beispiel wurde dem Objekt eine Eigenschaft vom Typ Number, d.h. eine Zahl angehängt. Erlaubt sind Eigenschaften jedes möglichen Typs, darunter auch Funktionen. Objektmethoden sind somit nur spezielle Eigenschaften vom Typ function.
Methoden werden zudem anhand ihrer Zugriffsrechte auf objekteigene Eigenschaften und Methoden unterschieden. Private Methoden haben prinzipiell Zugriff auf alle öffentlichen und privaten Eigenschaften und Methoden. Dasselbe gilt für sogenannte privilegierte öffentliche Methoden. Nicht-privilegierte öffentliche Methoden können nur auf öffentliche Eigenschaften und Methoden zugreifen. Erstgenannte werden innerhalb der Konstruktor-Funktion definiert, letztgenannte werden von außen über die Eigenschaft prototype der Konstruktor-Funktion hinzugefügt (siehe den folgenden Abschnitt).
Im folgenden Beispiel werden die verschiedenen Eigenschafts- und Methodentypen demonstriert.
function meinObjekt (parameter) { /* parameter ist eine private Eigenschaft */ /* Speichere eine Referenz auf das aktuelle Objekt in der privaten Eigenschaft self */ var self = this; /* private Eigenschaft */ var private_eigenschaft = "privat"; /* öffentliche Eigenschaft */ this.oeffentliche_eigenschaft = "öffentlich"; /* private Methode */ var private_methode = function () { window.alert(private_eigenschaft + " " + self.oeffentliche_eigenschaft); }; /* privilegierte öffentliche Methode */ this.privilegierte_methode = function () { window.alert(private_eigenschaft + " " + this.oeffentliche_eigenschaft); private_methode(); }; } /* nicht-privilegierte öffentliche Methode */ meinObjekt.prototype.oeffentliche_methode = function () { window.alert(typeof(private_eigenschaft) + " " + typeof(private_methode)); window.alert(this.oeffentliche_eigenschaft); };
Neue Instanz erstellen:
var objekt = new meinObjekt();
Auf private_eigenschaft und private_methode kann von außen nicht zugegriffen werden. Daher wird zweimal „undefined“ ausgegeben:
window.alert(objekt.private_eigenschaft + " " + objekt.private_methode);
Der Zugriff auf oeffentliche_eigenschaft hingegen ist von außen möglich. Es wird „öffentlich“ ausgegeben:
window.alert(objekt.oeffentliche_eigenschaft);
Ebenso können privilegierte_methode und oeffentliche_methode von außen aufgerufen werden:
objekt.privilegierte_methode(); objekt.oeffentliche_methode();
Diese Methoden demonstrieren die unterschiedlichen Zugriffsrechte.
privilegierte_methode gibt die Eigenschaften private_eigenschaft und oeffentliche_eigenschaft aus. Im Meldungsfenster wird „privat öffentlich“ ausgegeben. Danach ruft sie private_methode() auf, die noch einmal dasselbe demonstriert.
oeffentliche_methode hingegen hat keinen Zugriff auf private_eigenschaft und private_methode. Das Meldungsfenster zeigt zweimal „undefined“. Lediglich der Zugriff auf oeffentliche_eigenschaft gelingt.
Aufgrund eines Fehlers in der ECMAScript-Spezifikation ist das Ansprechen von öffentlichen Eigenschaften und Methoden in privaten Methoden schwierig, weil this nicht wie in öffentlichen Methoden auf das aktuelle Objekt verweist. Daher bedient man sich eines Tricks, indem man im Konstruktor this in einer privaten Eigenschaft speichert, gängigerweise self. Darüber gelingt der Zugriff auf öffentliche Eigenschaften und Methoden in privaten Methoden.
Function-Prototyp abgeleitete Objekt verfügt über eine Eigenschaft prototype. Diese übernimmt eine wichtige Aufgabe, wenn die Funktion als Konstruktor benutzt wird, um neue Objekte zu initialisieren. Die Eigenschaft prototype definiert in diesem Falle gemeinsame Eigenschaften aller Objekte, die mit dem Konstruktor erstellt werden. Man spricht von prototyp-basierter Vererbung. Auf diese Weise ermöglicht JavaScript mehrstufige Vererbung:
Konstruktor eines Prototyps erstellen:
function Kraftfahrzeug (Fabrikat) { this.Fabrikat = Fabrikat; this.Beispieleigenschaft = "Beispielwert"; }
Konstruktor des abgeleiteten Prototyps erstellen:
function PKW (Fabrikat) { this.constructor(Fabrikat); this.weitereEigenschaft = "Beispielwert"; } PKW.prototype = new Kraftfahrzeug();
Eine neue Instanz des allgemeinen Prototyps Kraftfahrzeug dient als Muster des abgeleiteten Prototyps PKW. Dadurch werden die Eigenschaften des allgemeinen Prototyps an den abgeleiteten Prototyp vererbt: Jedes PKW-Objekt ist gleichzeitig ein Kraftfahrzeug-Objekt. Über this.constructor kann im PKW-Konstruktor der Kraftfahrzeug-Konstruktor angesprochen werden. Dieses wird im Beispiel dazu genutzt, die Parameter an letztgenannten weiterzugeben. So muss this.Fabrikat = Fabrikat; nur im Kraftfahrzeug-Konstruktor notiert sein.
Instanz des Prototyps PKW erstellen:
var Golf = new PKW("Volkswagen Golf"); var Ente = new PKW("Citroen 2CV");
Über die Eigenschaft prototype der Konstruktorfunktion können einem Prototyp auch nachträglich Eigenschaften und Methoden hinzugefügt werden. Diese Änderungen wirken sich auf alle davon abgeleiteten Objekte aus:
PKW.prototype.Radanzahl = 4; PKW.prototype.zeigeRadanzahl = function () { window.alert(this.Fabrikat + " hat " + this.Radanzahl + " Räder."); }; Golf.zeigeRadanzahl(); // Ausgabe: „Volkswagen Golf hat 4 Räder.“ Ente.zeigeRadanzahl(); // Ausgabe: „Citroen 2CV hat 4 Räder.“
Eine nützliche Methode des Object-Prototyps ist hasOwnProperty(Eigenschaftsname). Sie gibt einen booleschen Wert, also true oder false zurück. Dadurch lässt sich ermitteln, ob eine bestimmte Eigenschaft durch dessen Konstruktor selbst oder durch seine Prototyp-Kette definiert wird. Im Beispiel ergibt Golf.hasOwnProperty("Radanzahl") false, ebenso wie Golf.hasOwnProperty("zeigeRadanzahl"). Beide Eigenschaften wurden nachträglich über PKW.prototype hinzugefügt. Golf.hasOwnProperty("Fabrikat") und Golf.hasOwnProperty("weitereEigenschaft") hingegen ergeben true, weil diese Eigenschaften durch die Konstruktoren Kraftfahrzeug und PKW belegt wurden.
try ... catch zur Fehlerbehandlung.
Die Anweisung try ... catch ... finally fängt Ausnahmen (exceptions), die aufgrund eines Fehlers oder einer throw-Anweisung auftreten, ab. Die Syntax ist wie folgt:
try { // Anweisungen, in denen Ausnahmen auftreten oder ausgelöst werden können } catch (error) { // Anweisungsfolge, die im Ausnahmefall ausgeführt wird. // In diesem Teil kann die Fehlerbehandlung erfolgen. } finally { // Anweisungsfolge, die anschließend in jedem Fall ausgeführt wird. } ... throw("sample exception")
Zu Beginn werden die Anweisungen im try-Block ausgeführt. Falls eine Ausnahme auftritt, wird der Kontrollfluss sofort zum catch-Block mit dem Ausnahmeobjekt als Parameter umgeleitet.
Im Normalfall wird der Ausnahmeblock übersprungen. Nach der Ausführung des try-Blocks (auch teilweise) und gegebenenfalls des catch-Blocks werden in jedem Fall die Anweisungen im finally-Block ausgeführt. Der finally-Teil kann weggelassen werden, alternativ der catch-Teil.
جافا سكريبت | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | 자바스크립트 | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | ஜாவாஸ்கிரிப்டு | จาวาสคริปต์ | JavaScript | Джава сценарій (мова програмування) | JavaScript | JavaScript
This article is licensed under the GNU Free Documentation License.
It uses material from the
"JavaScript".
Home Page • arts • business • computers • games • health • hospitals • home • kids & teens • news • physicians • recreation• reference • regional • science • shopping • society • sports • world