Optional chaining (?.) 在 Nashorn 中使用。

huangapple go评论77阅读模式
英文:

Optional chaining (?.) in nashorn

问题

我在我的项目中使用了 Nashorn我想从 JSON 中获取属性但该属性可能没有值

在 JavaScript 中使用可选链并设置一个值如果属性为 null但在 Nashorn 中当我使用 (?.)我会得到这个错误

    import org.springframework.stereotype.Service
    import javax.script.ScriptEngineManager
    import javax.script.Bindings
    
    @Service
    class SampleService {
    
        class Person(
                val firstName: String,
                val lastName: String,
                val child: Child?
        )
    
        class Child(
                val name: String,
                val age: Int
        )
    
        fun runScript() {
            val engine = ScriptEngineManager().getEngineByName("nashorn")
            val bindings: Bindings = engine.createBindings()
            val person = Person("John", "Smite", null)
            bindings["person"] = person
            try {
                val script = """
                   var childAge = person.child?.age || 0;
                   childAge; // 作为结果返回。
                """.trimIndent()
                val scriptResult: Any = engine.eval(script, bindings)
            } catch (e: Exception) {
                throw e
            }
    
        }
    }

我得到了这个错误:

javax.script.ScriptException: <eval>:1:28 预期一个操作数,但找到了 。
var childAge = person.child?.age || 0;
^ 在 <eval> 中位于行号 1,列号 28

我查看了这个链接,但我无法解决这个问题:
可选链 (?.)

我该如何修复这个错误?


<details>
<summary>英文:</summary>

I use nashorn in my project. I want get property from a json, but property may not have value.

In javascript, use optional chaining and set a value, if property is null; but in nashorn, when I use (?.), I get this error:

    import org.springframework.stereotype.Service
    import javax.script.ScriptEngineManager
    import javax.script.Bindings
    
    @Service
    class SampleService {
    
        class Person(
                val firstName: String,
                val lastName: String,
                val child: Child?
        )
    
        class Child(
                val name: String,
                val age: Int
        )
    
        fun runScript() {
            val engine = ScriptEngineManager().getEngineByName(&quot;nashorn&quot;)
            val bindings: Bindings = engine.createBindings()
            val person = Person(&quot;John&quot;, &quot;Smite&quot;, null)
            bindings[&quot;person&quot;] = person
            try {
                val script = &quot;&quot;&quot;
                   var childAge = person.child?.age ?? 0;
                   childAge; //return as result.
                &quot;&quot;&quot;.trimIndent()
                val scriptResult: Any = engine.eval(script, bindings)
            } catch (e: Exception) {
                throw e
            }
    
        }
    }

I get this error:

    javax.script.ScriptException: &lt;eval&gt;:1:28 Expected an operand but found .
    var childAge = person.child?.age ?? 0;
    ^ in &lt;eval&gt; at line number 1 at column number 28

I checked this link, but I could not solve the problem:
[Optional chaining (?.)][1]


How can I fix this error?


  [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

</details>


# 答案1
**得分**: 1

以下是翻译好的内容:

目前 Nashorn 的策略是遵循 ECMAScript 规范。当我们发布 JDK 8 时,我们将与 ECMAScript 5.1 保持一致。

Nashorn 引擎已在 JDK 11 中被弃用,作为 JEP 335 的一部分,并计划在未来的 JDK 发布中将其移除,作为 JEP 372 的一部分。

> **GraalVM JavaScript** 可以作为 Nashorn 引擎之前执行的代码的替代品。它提供了之前由 Nashorn 提供的所有功能,其中许多功能默认可用,一些在标志后面,一些需要对源代码进行轻微修改。

可选链是相当新的特性,ECMAScript 5.1 不支持这个功能。

我从 **nashorn** 迁移到了 **GraalVM JavaScript**,并将代码更改如下:

```kotlin
import com.oracle.truffle.js.scriptengine.GraalJSScriptEngine
import org.graalvm.polyglot.Context
import org.graalvm.polyglot.HostAccess
import org.springframework.stereotype.Service
import javax.script.ScriptEngine

@Service
class SampleService {

    data class Person(
            val firstName: String,
            val lastName: String,
            val child: Child?
    )

    data class Child(
            val name: String,
            val age: Int
    )

    fun runScript() {

        val person = Person("John", "Smite", null)

        val engine: ScriptEngine = GraalJSScriptEngine.create(null,
                Context.newBuilder("js")
                        .allowHostAccess(HostAccess.ALL)
                        .allowExperimentalOptions(true)
                        .option("js.ecmascript-version", "2020")
                        .option("js.nashorn-compat", "true"))
        engine.put("person", person)
        try {
            val script = """
                print(person.child?.name);
                //print undefined
                print(person.child?.name ?: 'not exist');
                //print not exist
            """.trimIndent()
            engine.eval(script)
        } catch (e: Exception) {
            throw e
        }
    }
}
英文:

The current strategy for Nashorn is to follow the ECMAScript specification. When we release with JDK 8 we will be aligned with ECMAScript 5.1.link

The the Nashorn engine has been deprecated in JDK 11 as part of JEP 335 and is scheduled to be removed from future JDK releases as part of JEP 372.

> GraalVM JavaScript can step in as a replacement for code previously executed on the Nashorn engine. It provides all the
> features previously provided by Nashorn, with many being available by
> default, some behind flags, some requiring minor modifications to your
> source code.link

Optional chaining is pretty new and ECMAScript 5.1 is not supported this feature.

I migrate from nashorn to GraalVM JavaScript and changed the code as follows:

import com.oracle.truffle.js.scriptengine.GraalJSScriptEngine
import org.graalvm.polyglot.Context
import org.graalvm.polyglot.HostAccess
import org.springframework.stereotype.Service
import javax.script.ScriptEngine


@Service
class SampleService {

    data class Person(
            val firstName: String,
            val lastName: String,
            val child: Child?
    )

    data class Child(
            val name: String,
            val age: Int
    )

    fun runScript() {

        val person = Person(&quot;John&quot;, &quot;Smite&quot;, null)

        val engine: ScriptEngine = GraalJSScriptEngine.create(null,
                Context.newBuilder(&quot;js&quot;)
                        .allowHostAccess(HostAccess.ALL)
                        .allowExperimentalOptions(true)
                        .option(&quot;js.ecmascript-version&quot;, &quot;2020&quot;)
                        .option(&quot;js.nashorn-compat&quot;, &quot;true&quot;))
        engine.put(&quot;person&quot;, person)
        try {
            val script = &quot;&quot;&quot;
                print(person.child?.name);
                //print undefined
                print(person.child?.name ?? &#39;not exist&#39;);
                //print not exist
            &quot;&quot;&quot;.trimIndent()
            engine.eval(script)
        } catch (e: Exception) {
            throw e
        }
    }
}

huangapple
  • 本文由 发表于 2020年10月5日 23:46:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/64211977.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定