Úvod do Nashornu
1. Úvod
Tento článok je zameraný na Nashorn - nový predvolený modul JavaScript pre JVM od verzie Java 8.
Na výrobu sa použilo veľa sofistikovaných techník Nashorn rádovo výkonnejší ako jeho predchodca Nosorožec, je to teda užitočná zmena.
Pozrime sa na niekoľko spôsobov, ako sa dá použiť.
2. Príkazový riadok
JDK 1.8 obsahuje tlmočník príkazového riadku s názvom jjs ktoré možno použiť na spustenie súborov JavaScriptu alebo, ak sú spustené bez argumentov, ako REPL (interaktívny shell):
$ $ JAVA_HOME / bin / jjs hello.js Dobrý deň, svet
Tu súbor ahoj.js obsahuje jednu inštrukciu: tlač („Hello World“);
Rovnaký kód je možné spustiť interaktívnym spôsobom:
$ $ JAVA_HOME / bin / jjs jjs> print ("Hello World") Hello World
Môžete tiež dať pokyn runtime * nix na použitie jjs pre spustenie cieľového skriptu pridaním a #! $ JAVA_HOME / bin / jjs ako prvý riadok:
#! $ JAVA_HOME / bin / jjs var pozdrav = "Hello World"; tlač (pozdrav);
A potom je možné súbor spustiť ako obvykle:
$ ./hello.js Dobrý deň, svet
3. Integrovaný skriptovací modul
Druhým a pravdepodobne bežnejším spôsobom spustenia JavaScriptu z prostredia JVM je server ScriptEngine. JSR-223 definuje množinu skriptovacích API, čo umožňuje zásuvnú architektúru skriptového jadra, ktorú je možné použiť pre akýkoľvek dynamický jazyk (samozrejme za predpokladu, že má implementáciu JVM).
Vytvorme JavaScriptový engine:
ScriptEngine engine = nový ScriptEngineManager (). GetEngineByName ("nashorn"); Výsledok objektu = engine.eval ("var pozdrav =" ahoj svet ";" + "tlač (pozdrav);" + "pozdrav");
Tu vytvárame nový ScriptEngineManager a okamžite ho požiadajte, aby nám dal ScriptEngine menovaný nashorn. Potom odovzdáme niekoľko pokynov a získame výsledok, ktorý sa predvídateľne ukáže ako a String “ahoj svet“.
4. Prenos údajov do skriptu
Dáta môžu byť prenesené do motora definovaním a Viazania objekt a odovzdať ho ako druhý parameter do eval funkcia:
Väzby väzby = engine.createBindings (); bindings.put ("count", 3); bindings.put ("meno", "baeldung"); Reťazec script = "var pozdrav =" Dobrý deň ";" + "pre (var i = count; i> 0; i--) {" + "pozdrav + = meno + ''" + "}" + "pozdrav"; Object bindingsResult = engine.eval (skript, väzby);
Spustenie tohto úryvku vyprodukuje: „Ahoj baeldung baeldung baeldung“.
5. Vyvolanie funkcií JavaScriptu
Je samozrejme možné volať funkcie JavaScriptu z vášho kódu Java:
engine.eval ("funkcia composeGreeting (name) {" + "návrat 'Hello' + meno" + "}"); Invocable invcable = (Invocable) engine; Objekt funcResult = invocable.invokeFunction ("composeGreeting", "baeldung");
To sa vráti „Ahoj baeldung“.
6. Používanie objektov Java
Pretože bežíme v prostredí JVM, je možné používať natívne objekty Java z kódu JavaScript.
To sa dosiahne použitím a Java objekt:
Mapa objektu = engine.eval ("var HashMap = Java.type ('java.util.HashMap');" + "var mapa = nový HashMap ();" + "map.put ('ahoj', 'svet') ; "+" mapa ");
7. Jazykové rozšírenia
Nashorn zacieľuje na ECMAScript 5.1 ale poskytuje rozšírenia, vďaka ktorým je používanie JavaScriptu o niečo príjemnejšie.
7.1. Iterujúce zbierky pre každého
Pre každý je pohodlné rozšírenie, ktoré uľahčuje iteráciu rôznych kolekcií:
Reťazcový skript = "var list = [1, 2, 3, 4, 5];" + "var výsledok = '';" + "pre každú (var i v zozname) {" + "výsledok + = i + '-';" + "};" + "tlač (výsledok);"; engine.eval (skript);
Tu spájame prvky poľa pomocou pre každý iteračný konštrukt.
Výsledný výstup bude 1-2-3-4-5-.
7.2. Funkčné literály
V jednoduchých vyhláseniach o funkciách môžete vynechať zložené zátvorky:
inkrement funkcie (v) ++ v
Je zrejmé, že je to možné vykonať iba pre jednoduché funkcie jednej linky.
7.3. Podmienené doložky o úlovku
Je možné pridať strážené klauzuly úlovku, ktoré sa vykonajú, iba ak je zadaná podmienka pravdivá:
skus {hodit "BOOM"; } catch (e if typeof e === 'string') {print ("Reťazec vyhodený:" + e); } catch (e) {print ("toto by sa nemalo stávať!"); }
Toto vytlačí „Vyhodený reťazec: BOOM“.
7.4. Zadané polia a prevody typov
Je možné použiť polia typu Java a prevádzať do a z polí JavaScriptu:
funkčné polia (arr) {var javaIntArray = Java.to (arr, "int []"); print (javaIntArray [0]); print (javaIntArray [1]); print (javaIntArray [2]); }
Nashorn tu vykonáva niektoré typové konverzie, aby sa ubezpečil, že všetky hodnoty z dynamicky písaného poľa JavaScriptu sa zmestia do celočíselných polí Java.
Výsledok volania funkcie hore argumentom [100, 1654, pravda] má za následok výstup 100, 1654 a 1 (všetky čísla).
The String a logické hodnoty boli implicitne prevedené na logické celé čísla.
7.5. Nastavenie prototypu objektu pomocou Object.setPrototypeOf
Nashorn definuje rozšírenie API, ktoré nám umožňuje zmeniť prototyp objektu:
Object.setPrototypeOf (obj, newProto)
Táto funkcia sa všeobecne považuje za lepšiu alternatívu k Object.prototype .__ proto__ malo by to byť preferovaným spôsobom, ako nastaviť prototyp objektu do celého nového kódu.
7.6. Kúzelný __noSuchProperty__ a __noSuchMethod__
Na objekte je možné definovať metódy, ktoré sa vyvolajú kedykoľvek nedefinované majetok je prístupný alebo nedefinované je vyvolaná metóda:
var demo = {__noSuchProperty__: function (propName) {print ("Prístup k neexistujúcemu vlastníctvu:" + propName); }, __noSuchMethod____: function (methodName) {print ("Vyvolaná neexistujúca metóda:" + methodName); }}; demo.doesNotExist; demo.callNonExistingMethod ()
Týmto sa vytlačí:
Prístup k neexistujúcej vlastnosti: doesNotExist Vyvolaná neexistujúca metóda: callNonExistingMethod
7.7. Viazať vlastnosti objektu na Object.bindProperties
Object.bindProperties možno použiť na väzbu vlastností z jedného objektu do druhého:
var first = {name: "Whisky", vek: 5}; var second = {objem: 100}; Object.bindProperties (prvý, druhý); tlač (prvý.objem); druhý.objem = 1000; tlač (prvý.objem);
Všimnite si, že toto vytvára „živú“ väzbu a všetky aktualizácie zdrojového objektu sú viditeľné aj cez cieľ väzby.
7.8. Umiestnenia
Aktuálny názov súboru, adresár a riadok je možné získať z globálnych premenných __FILE__, __DIR__, __LINE__:
tlač (__ FILE__, __LINE__, __DIR__)
7.9. Rozšírenia reťazca. Prototyp
Existujú dve jednoduché, ale veľmi užitočné rozšírenia Nashorn poskytuje na String prototyp. Toto sú trimRight a trimLeft funkcie, ktoré neprekvapujúco vrátia kópiu súboru String s odstráneným prázdnym priestorom:
print ("ahoj svet" .trimLeft ()); print ("ahoj svet" .trimRight ());
Vytlačí „ahoj svet“ dvakrát bez toho, aby ste začínali alebo končili medzery.
7.10. Kompatibilné s Java.asJSON Funkcia
Pomocou tejto funkcie môžeme získať objekt, ktorý je kompatibilný s očakávaniami knižníc Java JSON.
Totiž to, že ak je to sám, alebo akýkoľvek objekt, ktorý je cez neho prechodne dostupný, je to pole JavaScriptu, potom budú také objekty vystavené ako JSObject ktorou sa tiež vykonáva Zoznam rozhranie na vystavenie prvkov poľa.
Objekt obj = engine.eval ("Java.asJSONCompatible ({number: 42, greet: 'hello', prvočísla: [2,3,5,7,11,13]})"); Mapa mapa = (Mapa) obj; System.out.println (map.get ("pozdravit")); System.out.println (map.get ("prvočísla")); System.out.println (List.class.isAssignableFrom (map.get ("prvočísla"). GetClass ()));
Toto vytlačí „Ahoj" nasledovaný [2, 3, 5, 7, 11, 13] nasledovaný pravda.
8. Načítanie skriptov
Je tiež možné načítať ďalší súbor JavaScriptu z priečinka ScriptEngine:
load ('classpath: script.js')
Skript je možné načítať aj z adresy URL:
načítať ('/ script.js')
Pamätajte, že JavaScript nemá koncept menných priestorov, takže sa všetko nahromadí do globálneho rozsahu. Vďaka tomu môžu načítané skripty vytvárať konflikty pomenovaní s vaším kódom alebo navzájom navzájom. To je možné zmierniť použitím loadWithNewGlobal funkcia:
var math = loadWithNewGlobal ('classpath: math_module.js') math.increment (5);
S nasledujúcim math_module.js:
var math = {prírastok: function (num) {return ++ num; }}; matematika; bai
Tu definujeme pomenovaný objekt matematika ktorá má jedinú funkciu nazvanú prírastok. Pomocou tejto paradigmy môžeme dokonca emulovať základnú modularitu!
8. Záver
Tento článok skúmal niektoré funkcie Nashorn JavaScriptový engine. Tu uvedené príklady používajú skripty literálového písma, ale v prípade skutočných scenárov je najpravdepodobnejšie ponechať skript v samostatných súboroch a načítať ich pomocou Čitateľ trieda.
Ako vždy, kód v tomto zápise je k dispozícii na celej GitHub.