ScriptEngine JavaScript不支持包含?

问题描述 投票:2回答:2

我有一些代码,如下所示。

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("nashorn");
engine.eval("[1, 2, 3].includes(1)");

但是这会引发以下错误

javax.script.ScriptException: TypeError: [1, 2, 3].includes is not a function in <eval> at line number 1
    at jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:470)
    at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:454)
    at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:406)
    at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:402)
    at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:155)
    at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)

我可以改为indexOf(1),这似乎有效,但有没有理由说我无法使用此解析器包含?

javascript java nashorn javax
2个回答
2
投票

String.prototype.includes在ECMAScript 2015(ECMA-262第6版)中指定。 Nashorn引擎实现了ECMA-262 Edition 5.1)。另见http://www.ecma-international.org/ecma-262/6.0/#sec-string.prototype.includes

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes有一个String.prototype.includes的polyfill。我检查了polyfill与Nashorn引擎一起工作。


0
投票

Nashorn不支持includes(),因为它在添加includes()之前实现了JavaScript规范的早期版本。您可以使用Mozilla网站上的参考资料将填充(也称为填充)支持()填充到Nashorn中。

最初的问题是在JavaScript数组上做include()。之前的答案是JavaScript字符串,所以不正确。下面是一段JUnit测试代码,展示了如何对数组和字符串使用polyfill。

    // Copied from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes#Polyfill
    public static final String NASHORN_POLYFILL_STRING_PROTOTYPE_INCLUDES = "if (!String.prototype.includes) { Object.defineProperty(String.prototype, 'includes', { value: function(search, start) { if (typeof start !== 'number') { start = 0 } if (start + search.length > this.length) { return false } else { return this.indexOf(search, start) !== -1 } } }) }";
    // Copied from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes#Polyfill
    public static final String NASHORN_POLYFILL_ARRAY_PROTOTYPE_INCLUDES  = "if (!Array.prototype.includes) { Object.defineProperty(Array.prototype, 'includes', { value: function(valueToFind, fromIndex) { if (this == null) { throw new TypeError('\"this\" is null or not defined'); } var o = Object(this); var len = o.length >>> 0; if (len === 0) { return false; } var n = fromIndex | 0; var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); function sameValueZero(x, y) { return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y)); } while (k < len) { if (sameValueZero(o[k], valueToFind)) { return true; } k++; } return false; } }); }";

    @Test
    public void testStringIncludesWithPolyfill() throws Exception {
        runScript(NASHORN_POLYFILL_STRING_PROTOTYPE_INCLUDES, "'[1, 2, 3]'.includes(2)");
    }

    @Test(expected=javax.script.ScriptException.class)
    public void testStringIncludesWithoutPolyfill() throws Exception {
        runScript(null, "'[1, 2, 3]'.includes(2)");
    }

    @Test
    public void testArrayIncludesWithPolyfill() throws Exception {
        runScript(NASHORN_POLYFILL_ARRAY_PROTOTYPE_INCLUDES, "[1, 2, 3].includes(2)");
    }

    @Test(expected=javax.script.ScriptException.class)
    public void testArrayIncludesWithoutPolyfill() throws Exception {
        runScript(null, "[1, 2, 3].includes(2)");
    }

    private void runScript(final String polyfill, final String booleanExpression) throws ScriptException {
        final ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
        final ScriptEngine        scriptEngine        = scriptEngineManager.getEngineByName("nashorn");
        Assert.assertNotNull(scriptEngine);
        if (null != polyfill) {
            scriptEngine.eval(polyfill);
        }
        final Object booleanExpressionResult = scriptEngine.eval(booleanExpression);    // returns Boolean object
        Assert.assertNotNull(booleanExpressionResult);
        Assert.assertEquals(booleanExpressionResult.getClass(), Boolean.class);
        System.out.println(booleanExpression + " = " + booleanExpressionResult.toString());
    }
© www.soinside.com 2019 - 2024. All rights reserved.