Thanks. That makes sense. Two follow-ups, if I may:
A. Where can I read about such non-ECMA-standard features in Nashorn? B. ECMAScript 6 includes `String.prototype.startsWith`, but it is not supported by Nashorn in ES6-mode: ``` 1 $ jjs -version --language=es6 2 nashorn 1.8.0_101 3 jjs> typeof String.prototype.startsWith 4 undefined ``` And it is unclear whether Nashorn intends to support it yet (https://bugs.openjdk.java.net/browse/JDK-8066046). So, is it a deliberate omission? --- Esben On Mon, Oct 17, 2016 at 7:44 AM Attila Szegedi <szege...@gmail.com> wrote: > it’s a side effect of the fact that primitive strings values in Nashorn > are instances of java.lang.String, and the fact that with Nashorn you can > invoke methods on Java objects, therefore “startsWith” is a Java String > method. > > While Java methods also don’t inherit from Function.prototype (hence, you > can’t call “call” on them as you have correctly observed), implementations > of Function.prototype.call and .apply are actually coded so that they do > work on them with a not terribly obvious, but correct invocation: > > var sw = "".startsWith > Function.prototype.call.call(sw, "abc", "a") > > should return true. Note that since the expression fn.call.call is totally > unbound from the fn that produced it, you can use any “fn”; I usually use > “Function” for some semblance of clarity: > > Function.call.call(sw, "abc", "a") > > Finally, .startsWith is only present on primitive String values (as > they’re java.lang.String), not on JS String objects, that’s why you were > getting results you didn’t expect from “typeof Object(string).startsWith” > > HTH, > Attila. > > > > On 16 Oct 2016, at 13:42, Esben Andreasen <es...@esbena.dk> wrote: > > > > Hi > > > > I am not sure if this is a bug or feature of the Nashorn engine. But > > it looks like some String-prototype methods are missing, yet the > > methods are somehow present when used in the right way. > > > > Minimal example: calling `startsWith` by using `call`: > > > > ``` > > 1 $ jjs -v > > 2 jjs> String.prototype.startsWith.call('abc', 'ab') > > 3 <shell>:1 TypeError: Cannot read property "call" from undefined > > ``` > > > > Expected behavior: > > > > Not a type error, for multiple reasons: > > > > 1. Other JavaScript engines do not throw a type error. > > 2. The equivalent code `"abc".startsWith("ab")` does not throw a type > error. > > > > > > Further investigation: > > > > ``` > > 1 $ jjs -v > > 2 nashorn 1.8.0_101 > > 3 jjs> "abc".startsWith('ab') > > 4 true > > 5 jjs> "abc".startsWith > > 6 [jdk.internal.dynalink.beans.OverloadedDynamicMethod > > boolean java.lang.String.startsWith(String,int) > > boolean java.lang.String.startsWith(String) > > ] > > 7 jjs> "abc".startsWith.call("abc", "ab") > > 8 <shell>:1 TypeError: "abc".startsWith.call is not a function > > 9 jjs> typeof String.prototype.startsWith > > 10 undefined > > 11 jjs> String.prototype.split.call("abc", "b") > > 12 a,c > > ``` > > > > Interpretation: > > > > It looks like `startsWith` is not present on the String-prototype, yet > > it is present on the String-primitives. Other String-prototype methods > > (`split`) are however present. > > > > Further notes: > > > > This also applies to `String.prototype.endsWith`. > > > > > > Related bug/feature: primitive values are not wrapped properly: > > > > ``` > > 1 $ jjs -v > > 2 jjs> typeof Object("abc").startsWith > > 3 undefined > > ``` > > > > - > > > > Esben > >