Bevezetés a Nashorn-ba

1. Bemutatkozás

Ez a cikk a következőkre összpontosít Nashorn - az új alapértelmezett JavaScript motor a JVM számára a Java 8-tól kezdve.

Számos kifinomult technikát alkalmaztak Nashorn nagyságrendekkel teljesítőbb, mint elődje nevezte Orrszarvú, tehát érdemes változás.

Vessünk egy pillantást néhány felhasználási módra.

2. Parancssor

A JDK 1.8 tartalmaz egy meghívott parancssori tolmácsot jjs amely használható JavaScript fájlok futtatására, vagy ha argumentum nélkül indult, REPL (interaktív shell) néven:

$ $ JAVA_HOME / bin / jjs hello.js Hello World

Itt a fájl hello.js egyetlen utasítást tartalmaz: nyomtatás („Hello World”);

Ugyanaz a kód futtatható interaktív módon:

$ $ JAVA_HOME / bin / jjs jjs> print ("Hello World") Hello World

Utasíthatja a * nix futásidejének használatát is jjs egy cél szkript futtatásához a hozzáadásával #! $ JAVA_HOME / bin / jjs első sorként:

#! $ JAVA_HOME / bin / jjs var greeting = "Hello Világ"; nyomtatás (üdvözlet);

Ezután a fájl a szokásos módon futtatható:

$ ./hello.js Hello World

3. Beágyazott szkript motor

A JavaScript futtatásának második és valószínűleg gyakoribb módja a JVM-en belül a ScriptEngine. A JSR-223 meghatároz egy szkript API-kat, lehetővé téve egy plug-inelhető script motor architektúrát, amely bármely dinamikus nyelvhez használható (természetesen ha rendelkezik JVM implementációval).

Hozzunk létre egy JavaScript-motort:

ScriptEngine motor = new ScriptEngineManager (). GetEngineByName ("nashorn"); Objektum eredménye = motor.eval ("var üdvözlet =" hello world ";" + "print (üdvözlet);" + "üdvözlet");

Itt létrehozunk egy újat ScriptEngineManager és azonnal kérje meg, hogy adjon nekünk egy ScriptEngine nevezett nashorn. Ezután átadunk egy pár utasítást, és megkapjuk az eredményt, amely kiszámíthatóan kiderül, hogy a HúrHelló Világ“.

4. Adatok továbbítása a szkriptbe

Az adatok a motor definiálásával adhatók át a Kötések objektumot, és második paraméterként továbbítja a eval funkció:

Kötéskötések = motor.createBindings (); bindings.put ("count", 3); bindings.put ("név", "baeldung"); String script = "var greeting =" Hello ";" + "for (var i = count; i> 0; i--) {" + "üdvözlet + = név + ''" + "}" + "üdvözlet"; Object bindingsResult = motor.eval (szkript, összerendelések);

A kódrészlet futtatása a következőt eredményezi:Helló baeldung baeldung baeldung“.

5. JavaScript-függvények meghívása

Természetesen lehetséges Java-kódból meghívni a JavaScript-függvényeket:

engine.eval ("function composeGreeting (név) {" + "return 'Hello' + név" + "}"); Invocable invocable = (Invokálható) motor; Object funcResult = invocable.invokeFunction ("composeGreeting", "baeldung");

Ez visszatérSzia baeldung“.

6. Java objektumok használata

Mivel a JVM-ben futunk, natív Java objektumok is használhatók a JavaScript kódon belül.

Ezt úgy érhetjük el, hogy a Jáva tárgy:

Objektumtérkép = engine.eval ("var HashMap = Java.type ('java.util.HashMap');" + "var map = new HashMap ();" + "map.put ('hello', 'world') ; "+" térkép ");

7. Nyelvbővítmények

Nashorn az ECMAScript 5.1-et célozza meg de kiterjesztéseket biztosít, hogy a JavaScript használata egy kicsit szebb legyen.

7.1. Gyűjtemények itterálása mindenkinek

Az egyes egy kényelmes kiterjesztés a különböző gyűjtemények iterációjának megkönnyítésére:

Karaktersorozat = "var list = [1, 2, 3, 4, 5];" + "var result = '';" + "mindegyikhez (var i a listán) {" + "eredmény + = i + '-';" + "};" + "nyomtatás (eredmény);"; motor.eval (szkript);

Itt egy tömb elemeit egyesítjük a használatával az egyes iterációs konstrukció.

A kapott kimenet lesz 1-2-3-4-5-.

7.2. Funkció literálok

Az egyszerű függvénydeklarációkban elhagyhatja a göndör zárójeleket:

függvény növekmény (in) ++ in

Nyilvánvaló, hogy ez csak egyszerű, egysoros funkciók esetén lehetséges.

7.3. Feltételes fogási záradékok

Lehetőség van őrzött fogási záradékok hozzáadására, amelyek csak akkor teljesülnek, ha a megadott feltétel teljesül:

próbáld {dobni a "BOOM" -t; } catch (e if typeof e === 'string') {print ("String dobva:" + e); } catch (e) {print ("ennek nem szabad megtörténnie!"); }

Ez kinyomtatja aDobott húr: BOOM“.

7.4. Gépelt tömbök és típuskonverziók

Lehetséges Java tipizált tömbök használata és konvertálás JavaScript tömbökbe és azokból:

függvénytömbök (arr) {var javaIntArray = Java.to (arr, "int []"); nyomtatás (javaIntArray [0]); nyomtatás (javaIntArray [1]); nyomtatás (javaIntArray [2]); }

Nashorn néhány típusú konverziót végez itt, hogy megbizonyosodjon arról, hogy a dinamikusan beírt JavaScript tömb összes értéke elfér-e a csak egész Java-tömbökben.

A fenti függvény argumentummal történő meghívásának eredménye [100, „1654”, igaz] 100, 1654 és 1 kimenetet eredményez (minden szám).

A Húr és a logikai értékeket implicit módon konvertáltuk logikai egész megfelelőikre.

7.5. Az objektum prototípusának beállítása Object.setPrototypeOf

Nashorn meghatároz egy API kiterjesztést, amely lehetővé teszi számunkra az objektum prototípusának megváltoztatását:

Object.setPrototypeOf (obj, newProto)

Ezt a funkciót általában jobb alternatívának tekintik Object.prototype .__ proto__ így az objektum prototípusának minden új kódban történő beállításának előnyben részesített módja kell, hogy legyen.

7.6. Mágikus __noSuchProperty__ és __noSuchMethod__

Lehetőség van olyan módszerek definiálására egy objektumon, amely minden alkalommal meghívódik határozatlan ingatlanhoz hozzáfér vagy an határozatlan metódust hívják meg:

var demo = {__noSuchProperty__: function (propName) {print ("Hozzáférés a nem létező tulajdonsághoz:" + propName); }, __noSuchMethod__: function (metódusnév) {print ("Meghívott nem létező metódus:" + metódusnév); }}; demo.doesNotExist; demo.callNonExistingMethod ()

Ez kinyomtatja:

Meglévő nem létező tulajdonság: doesNotExist Meghívott nem létező módszer: callNonExistingMethod

7.7. Az objektum tulajdonságainak megkötése a Object.bindProperties

Object.bindProperties használható tulajdonságok egyik objektumból a másikba történő megkötésére:

var first = {név: "Whisky", életkor: 5}; var másodperc = {kötet: 100}; Object.bindProperties (első, második); nyomtatás (első.kötet); második.térfogat = 1000; nyomtatás (első.kötet);

Figyelje meg, hogy ez létrehoz egy „élő” kötést, és a forrásobjektum minden frissítése a kötési célponton keresztül is látható.

7.8. Helyek

Az aktuális fájlnév, könyvtár és egy sor a globális változókból szerezhető be __FILE__, __DIR__, __LINE__:

nyomtatás (__ FILE__, __LINE__, __DIR__)

7.9. A String.prototype kiterjesztései

Két egyszerű, de nagyon hasznos kiterjesztés létezik Nashorn biztosítja a Húr prototípus. Ezek trimRight és trimBal funkciók, amelyek nem meglepő módon visszaadják a Húr eltávolítva a szóközt:

print ("hello world" .trimLeft ()); print ("hello world" .trimRight ());

Kétszer kinyomtatja a „helló világot” szóköz nélkül vagy szóköz nélkül.

7.10. Java.asJSONKompatibilis Funkció

Ennek a funkciónak a használatával megszerezhetünk egy objektumot, amely kompatibilis a Java JSON könyvtárak elvárásaival.

Nevezetesen, hogy ha maga vagy bármely, rajta keresztül átmenetileg elérhető objektum egy JavaScript tömb, akkor az ilyen objektumok ki lesznek téve JSObject hogy megvalósítja a Lista interfész a tömb elemek kiállításához.

Object obj = engine.eval ("Java.asJSONCompatible ({szám: 42, üdvözlet: 'hello', prím: [2,3,5,7,11,13]})"); Térképtérkép ((Térkép) obj; System.out.println (map.get ("üdvözlet")); System.out.println (map.get ("primes")); System.out.println (List.class.isAssignableFrom (map.get ("primes"). GetClass ()));

Ez kinyomtatja aHelló”Követi [2, 3, 5, 7, 11, 13] utána igaz.

8. Szkriptek betöltése

Lehetőség van egy másik JavaScript fájl betöltésére is a ScriptEngine:

betöltés ('classpath: script.js')

A parancsfájl URL-ből is betölthető:

betöltés ('/ script.js')

Ne feledje, hogy a JavaScript nem rendelkezik a névterek fogalmával, ezért minden a globális hatókörbe kerül. Ez lehetővé teszi a betöltött parancsfájlok számára, hogy névütközéseket hozzanak létre a kóddal vagy egymással. Ez enyhíthető a loadWithNewGlobal funkció:

var math = loadWithNewGlobal ('classpath: math_module.js') math.increment (5);

A következőkkel math_module.js:

var math = {növekmény: függvény (num) {return ++ szám; }}; matek; bai

Itt definiálunk egy nevű objektumot matek amelynek egyetlen funkciója van növekedés. Ennek a paradigmának az alkalmazásával akár az alapvető modularitást is utánozhatjuk!

8. Következtetés

Ez a cikk a Nashorn JavaScript motor. Az itt bemutatott példák használt szó szerinti sztringeket tartalmaznak, de való életben a forgatókönyvet valószínűleg külön fájlokban szeretné megtartani, és egy Olvasó osztály.

Mint mindig, ebben az írásban a kód is elérhető a GitHubon.