不幸的是,Errandir 的解决方案仅在您知道可用于访问要获取其属性名称的对象的全局变量名称时才有效。您需要知道此名称才能向keys
对象添加方法,并稍后使用JSObject
的call方法调用它。当然,您可以将对象的全局名称传递给 Java(如果有的话)。此解决方案看起来不太好,尤其是当您无法在全局上下文中引用您的对象时。
作为替代方案,我建议在评论中使用this
' JSObject
eval方法,假设它会完成所有工作。它确实如此。但令人失望的是,它只能在 Mozilla Firefox 和 Opera 中按预期工作。在 Internet Explorer 9 和 Google Chrome(在 Windows 7 和 Ubuntu 12.04 LTS 下测试)this
中,eval
方法总是指小程序的文档窗口,而忽略JSObject
实际代表的 JavaScript 对象实例。我不知道这是一个错误还是这些浏览器对LiveConnect的支持非常差。
好消息是在适当的上下文中执行指定函数的call
方法。JSObject
牢记这一点,我终于找到了如何检索 JavaScript 对象属性名称列表的解决方案。这个想法是使用eval
方法在全局上下文中定义一个临时函数。该函数必须接收我们想要获取其属性的 JavaScript 对象,并将这些属性的名称作为数组返回。之后,我们可以通过传递相关 JavaScript 对象的 Java 表示的JSObject
'方法调用临时函数(在我下面的方法中或在问题中听起来)。最后,可以删除临时功能。call
jsObject
args
public static ArrayList<String> getJsObjectPropertiesNames(Applet applet, JSObject jsObject) {
if (applet == null || jsObject == null)
return null;
// Retrieving global context - a JSObject representing a window applet belongs to
JSObject globalContext;
try {
globalContext = JSObject.getWindow(applet);
}
catch (JSException ex) {
return null;
}
// Checking whether passed object is not an array
try {
jsObject.getSlot(0);
return null;
}
catch (JSException e) {
}
String keysFunctionName = String.format("_getKeys%d", Calendar.getInstance().getTimeInMillis());
jsObject.eval("window['" + keysFunctionName + "'] = function(jsObject) { return Object.keys(jsObject) }");
JSObject propertiesNamesJsObject = (JSObject)globalContext.call(keysFunctionName, new Object[] { jsObject });
jsObject.eval("delete(window['" + keysFunctionName + "'])");
ArrayList<String> propertiesNames = new ArrayList<>();
try {
int slotIndex = 0;
while (true) {
Object propertyName = propertiesNamesJsObject.getSlot(slotIndex);
if (propertyName instanceof String)
propertiesNames.add((String)propertyName);
slotIndex++;
}
}
catch (JSException e) {
}
return propertiesNames;
}