JavaScript: The Definitive Guide

Previous Chapter 19
LiveConnect: JavaScript and Java
Next
 

19.4 JavaScript Conversion of JavaObjects

Having worked your way through that dense data conversion section above you may have hoped that we were through with the topic of data conversion. But there is more to be discussed. It has to do with how JavaScript converts JavaObjects to various JavaScript primitive types. Notice in Figure 19.3 that quite a few Java data types, including Java strings (instances of java.lang.String) are converted to JavaObject objects in JavaScript rather than being converted to actual JavaScript primitive types, such as strings. This means that when you use LiveConnect, you'll commonly be working with JavaObject objects.

Refer back to Table 9.1. You may also want to re-read the section of Chapter 9, Further Topics in JavaScript, that Table 9.1 is contained in. The table shows how various JavaScript data types are converted when used in various "contexts." For example, when a number is used in a string context, it is converted to a string. And when an object is used in a Boolean context, it is converted to the value false if it is null and true otherwise. These conversion rules don't apply to JavaObject objects. JavaObject objects are converted using their own rules, as follows:

Because of these different conversion rules, and for other reasons as well, JavaObjects behave differently than other JavaScript objects, and there are some common pitfalls that you need to beware of. First, it is not uncommon to work with a JavaObject that represents an instance of a java.lang.Double or some other numeric object. In many ways, such a JavaObject will behave like a primitive number value, but be careful when using the + operator. When you use a JavaObject (or any JavaScript object) with +, it constitutes a string context, and the object is converted to a string for string concatenation, instead of being converted to a number for addition.

When we described this same problem above when working with a Number object, we said that the workaround was to explicitly call valueOf() to convert the Number to a primitive number. Because of another difference between JavaObjects and other JavaScript objects, this workaround doesn't work in this case. Recall that the JavaObject object has no properties of its own; all of its properties represent fields and methods of the Java object it represents. This means that JavaObjects don't even have the valueOf() method recommended above! So when you've got a JavaObject representing an instance of java.lang.Double, or something similar, you'll have to call the doubleValue() method when you need to force it to a primitive value.

Another difference between JavaObjects and other JavaScript data types is that JavaObjects can only be used in a Boolean context if they define a booleanValue() method. Suppose button is a JavaScript variable that may contain null or may hold a JavaObject that represents an instance of the java.awt.Button class. If you want to check whether the variable contains null, you might write code like this, out of old habit:

if (!button) { ... }
If button is null, this will work fine. But if button actually contains a JavaObject representing a java.awt.Button instance, then LiveConnect will try to invoke the booleanValue() method. When it discovers that the java.awt.Button class doesn't define one, it will cause a JavaScript error. The workaround in this case is to be explicit about what you are testing for, to avoid using the JavaObject in a Boolean context:

if (button != null) { ... }
This is a good habit to get into, in any case, since it makes your code easier to read and understand.


Previous Home Next
LiveConnect Data Conversion Book Index Scripting Java with JavaScript

HTML: The Definitive Guide CGI Programming JavaScript: The Definitive Guide Programming Perl WebMaster in a Nutshell