有没有办法使 Nashorn JSObject 的自定义实现与 Object.keys() 一起工作?
Is there a way to make a custom implementation of Nashorn JSObject work with Object.keys()?
我最近问了这个问题 并得到了一个帮助我在我的项目中取得更大进展的答案,但是我发现了一个我不知道如何解决的关于提供自定义 JSObject 实现的限制.
鉴于这个简单的工作 JSObject 可以处理 JS 将在其上调用的大多数方法,例如 map:
import javax.script.*;
import jdk.nashorn.api.scripting.*;
import java.util.*;
import java.util.function.*;
public class scratch_6 {
public static void main(String[] args) throws Exception {
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine e = m.getEngineByName("nashorn");
// The following JSObject wraps this list
List<Object> l = new ArrayList<>();
l.add("hello");
l.add("world");
l.add(true);
l.add(1);
JSObject jsObj = new AbstractJSObject() {
@Override
public Object getMember(String name) {
if (name.equals("map")) {
// return a functional interface object - nashorn will treat it like
// script function!
final Function<JSObject, Object> jsObjectObjectFunction = callback -> {
List<Object> res = new ArrayList<>();
for (Object obj : l) {
// call callback on each object and add the result to new list
res.add(callback.call(null, obj));
}
// return fresh list as result of map (or this could be another wrapper)
return res;
};
return jsObjectObjectFunction;
} else {
// unknown property
return null;
}
}
};
e.put("obj", jsObj);
// map each String to it's uppercase and print result of map
e.eval("print(obj.map(function(x) '\"'+x.toString()+'\"'))");
//PROBLEM
//e.eval("print(Object.keys(obj))");
}
}
如果取消注释调用 Object.keys(obj) 的最后一行,它将失败并显示错误 ... is not an Object
.
这似乎是因为 Object.keys() [ NativeObject.java:376 ] 只检查对象是 ScriptObject 还是 ScriptObjectMirror 的实例。如果两者都不是,则会抛出 notAnObject 错误。 :(
理想情况下,用户实现的 JSObject 对象应该完全等同于脚本对象。但是,用户实现的 JSObjects 几乎 脚本对象——但不完全是。这在此处记录 -> https://wiki.openjdk.java.net/display/Nashorn/Nashorn+jsr223+engine+notes
Object.keys 就是这样一种情况,它会中断。但是,如果您只想为您的对象提供 for..in javascript 迭代支持,您可以在 class.
中实现 JSObject.keySet
示例代码:
import javax.script.*;
import jdk.nashorn.api.scripting.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine e = m.getEngineByName("nashorn");
// This JSObject wraps the following Properties object
Properties props = System.getProperties();
JSObject jsObj = new AbstractJSObject() {
@Override
public Set<String> keySet() {
return props.stringPropertyNames();
}
@Override
public Object getMember(String name) {
return props.getProperty(name);
}
};
e.put("obj", jsObj);
e.eval("for (i in obj) print(i, ' = ', obj[i])");
}
}
我最近问了这个问题
鉴于这个简单的工作 JSObject 可以处理 JS 将在其上调用的大多数方法,例如 map:
import javax.script.*;
import jdk.nashorn.api.scripting.*;
import java.util.*;
import java.util.function.*;
public class scratch_6 {
public static void main(String[] args) throws Exception {
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine e = m.getEngineByName("nashorn");
// The following JSObject wraps this list
List<Object> l = new ArrayList<>();
l.add("hello");
l.add("world");
l.add(true);
l.add(1);
JSObject jsObj = new AbstractJSObject() {
@Override
public Object getMember(String name) {
if (name.equals("map")) {
// return a functional interface object - nashorn will treat it like
// script function!
final Function<JSObject, Object> jsObjectObjectFunction = callback -> {
List<Object> res = new ArrayList<>();
for (Object obj : l) {
// call callback on each object and add the result to new list
res.add(callback.call(null, obj));
}
// return fresh list as result of map (or this could be another wrapper)
return res;
};
return jsObjectObjectFunction;
} else {
// unknown property
return null;
}
}
};
e.put("obj", jsObj);
// map each String to it's uppercase and print result of map
e.eval("print(obj.map(function(x) '\"'+x.toString()+'\"'))");
//PROBLEM
//e.eval("print(Object.keys(obj))");
}
}
如果取消注释调用 Object.keys(obj) 的最后一行,它将失败并显示错误 ... is not an Object
.
这似乎是因为 Object.keys() [ NativeObject.java:376 ] 只检查对象是 ScriptObject 还是 ScriptObjectMirror 的实例。如果两者都不是,则会抛出 notAnObject 错误。 :(
理想情况下,用户实现的 JSObject 对象应该完全等同于脚本对象。但是,用户实现的 JSObjects 几乎 脚本对象——但不完全是。这在此处记录 -> https://wiki.openjdk.java.net/display/Nashorn/Nashorn+jsr223+engine+notes
Object.keys 就是这样一种情况,它会中断。但是,如果您只想为您的对象提供 for..in javascript 迭代支持,您可以在 class.
中实现 JSObject.keySet示例代码:
import javax.script.*;
import jdk.nashorn.api.scripting.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine e = m.getEngineByName("nashorn");
// This JSObject wraps the following Properties object
Properties props = System.getProperties();
JSObject jsObj = new AbstractJSObject() {
@Override
public Set<String> keySet() {
return props.stringPropertyNames();
}
@Override
public Object getMember(String name) {
return props.getProperty(name);
}
};
e.put("obj", jsObj);
e.eval("for (i in obj) print(i, ' = ', obj[i])");
}
}