Ú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 Stringahoj 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.