The Now Platform® Washington DC release is live. Watch now!

Help
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
SlightlyLoony
Tera Contributor

find_real_file.pngA string is a string, right? Ah, if only 'twas so!

JavaScript all by itself has two different kinds of strings: there's the primitive "string" (with a lower case 's') and then there's the "String" class (which you can create instances of. For example:


var x = 'this is a primitive string';
var y = new String('this is a String instance');
gs.log(x + ': ' + typeof x); // this will show typeof 'string'
gs.log(y + ': ' + typeof y); // this will show typeof 'object'

In the code above, the variable x has a primitive string and the variable y has a String instance. In practical usage, the two behave nearly identically — with the obvious exception of the result of the typeof operator.

But what about the third flavor?

The third flavor of string results from the fact that JavaScript code can call Java code. When that Java code returns a string, it will show up in JavaScript as a Java String instance. This flavor can have some unexpected consequences. Consider the following code:

var id = Packages.com.glide.util.GlideUtil.getSystemId();
gs.log(id + ': ' + id.length());
id = '' + id;
gs.log(id + ': ' + id.length());

which produces this output when run on my demo instance:

*** Script: bosdemo02.service-now.com:maelstrom_16079: 41
Evaluator: org.mozilla.javascript.EcmaError: 41 is not a function.
Caused by error in script at line 4

1: var id = Packages.com.glide.util.GlideUtil.getSystemId();
2: gs.log(id + ': ' + id.length());
3: id = '' + id;
==> 4: gs.log(id + ': ' + id.length());

What's going on here?

Well, as you might guess, that call to GlideUtil.getSystemId() returns a Java String instance. What might not be so obvious is that the Java String class has different methods and properties than the JavaScript String class. In fact, the String case is particularly confusing, as there ARE many methods in common between Java and JavaScript, but each has some methods that the other doesn't.

In my example above, I'm getting the length of the Java class in line 2 with a method (length()) that JavaScript doesn't have — it has a property (length) instead. In line 3 I'm concatenating an empty JavaScript string primitive with the Java String instance, and the result will always be a JavaScript string primitive. In fact, this is a handy trick for coercing Java String instances into JavaScript strings. When I then try to call the same length() method on line 4, it fails, because JavaScript strings don't have that method.

What's the takeaway from this lesson? It's an easy one: if you call a method on a Java class, or on a class that MIGHT be a Java class (meaning you're not sure it's JavaScript), then always concatenate the return value with an empty string. This is always safe to do, and it always returns a JavaScript string...