我有一些代码,如下所示。
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),这似乎有效,但有没有理由说我无法使用此解析器包含?
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引擎一起工作。
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());
}