Reserved JavaScript Words in Safari
I ran into a problem today where the RIA I’m building works for all browsers except Safari – specifically Safari 4, not sure about 3.
The error happens when a certain page loads, and all I’m greeted with in Safar is `SyntaxError: Parser Error`. Nice.
After a little debugging and Googling, I realized that one of the objects I had setup used a property that was a JavaScript reserved word. For whatever reason, SquirrelFish (Safari 4’s JS engine) was the only engine to throw this error.
So something like this would work in all browsers except Safari:
// Parse Error in Safari 4
var myObject = {
enum: 1,
class: 'foobar',
faz: 'baz'
};
Instead, you need to wrap reserved words around quotation marks.
// Works in Safari 4 now
var myObject = {
'enum': 1,
'class': 'foobar',
faz: 'baz'
};
I’m not sure if SquirrelFish is correct, or the other engines. The inconsistency is a bit annoying though.
Not all jQuery selectors are created equal 2
The good thing about JavaScript libraries such as jQuery is that developers can focus on functionality without having to worry too much about cross-browser compatibility. However, often times it is still very useful to know why happens behind the abstractions.
The most used feature in jQuery is the CSS selector. Instead of selecting elements using pure DOM (e.g. document.getElementById(‘myId’)), you’re able to use jQuery’s CSS selector (e.g. $(‘#myId’)). This makes life much, much easier.
There are cases, however, where not knowing what happens behind the scenes can lead to poor implementations, causing big performance hits. One such case is the class selector (e.g. $(‘.someClass’)).
The reason why class selector is slow is because it has to go through the entire DOM to find those elements. Of course, some browsers like Firefox 3+ has native support for document.getElementsByClassName. And as John Resig analyzed, the native method is much faster than the next fastest implementation (XPath). But if you want your applications to run as fast as possible on as many browsers as possible, it’s better to avoid the class selector all-together (at least for now).
What you can do instead is to use the next fastest selector (behind ID selector), the tag name selector.
So instead of doing $(‘.someClass’), use $(‘div.someClass’), or whichever HTML tag name you want to use. This selector is faster because instead of checking the entire DOM, now it only needs to check against elements with that particular tag name. That is, it first does a document.getElementsByTagName(‘div’), then iterates through that list.
Or why not make it even faster by specifying an ancestor element by its ID? (e.g. $(‘#ancestor div.someClass’))
The thing to keep in mind is, no matter what abstractions come about, it’s still a very good idea to understand what happens underneath the hood. :)
JavaScript: Optimizing loops
When looping through very large arrays, you may find this tip useful: it’s much fast to use a while loop to iterate through an array than a for loop.
For example, if you take this code:
var myArray = new Array(10000);
for (var i=0; i<myArray.length; i++) {
myArray[i] = i;
}
You can make it run faster by using a while loop instead.
var myArray = new Array(10000);
var n = myArray.length;
while (n--) {
myArray[n] = n;
}
This works because n-- will return the value of n and then decrement it. So when it approaches index zero, it’ll coerce 1 to true, then decrement n before the line myArray[n] = n;.
Of course, this while-loop is looping backwards, so if the order of iteration does matter then you can’t use this method. You could however, still optimize the first example by first assigning myArray.length to a variable, then using that in the for-loop’s exit condition. This will make it run slightly faster (depending on which browser you’re using) because it avoids a property lookup at every loop iteration.
var myArray = new Array(10000);
var n = myArray.length;
for (var i=0; i<n; i++) {
myArray[i] = i;
}
Java control flow exercises
I came upon an interesting blog post about Java control flow. The author listed six examples (from LASER 2009 summer school on Software Testing) of pseudo Java code, and you have to determine what the value of the int b is, as well as whether an Exception is thrown or not. You can assume the program will execute with proper syntax, and proper throws Exception on the method signature.
Here are my answers, and explanations. The actual answers will be posted in the author’s next blog entry.
1. What is the value of b at the end of this code:
foo () {
int b = 1;
b++;
}
My answer: b is 2
2. What is the value of b at the end of this code:
foo () {
int b = 1;
while (true) {
b++;
break;
}
}
My answer: b is 2 because it gets incremented one first iteration of the while loop, then the loop breaks.
3. What is the value of b at the end of this code and tell us if this executes normally or with an exception:
foo () {
int b = 1;
try {
throw new Exception();
}
finally {
b++;
}
}
My answer: The exception is thrown, and then b is incremented to 2. And since the exception in not caught, it is thrown from the method.
4. What is the value of b at the end of this code and tell us if this executes normally or with an exception:
foo () {
int b = 1;
while (true) {
try {
b++;
throw new Exception();
}
finally {
b++;
break;
}
}
b++;
}
My answer: b is incremented in the try block, then exception is thrown. In the finally block, b is incremented again, then a static return from break brings control flow to the end of the method where b is once again incremented, and no exception is thrown from the method. So, b is 4 at the end, and no exception is thrown… in fact, you don’t even need a throws Exception in the method signature because this method cannot throw Exception.
5. The previous sample was too long, what does this return:
int foo () {
try {
return 1;
}
finally {
return 2;
}
}
My answer: the return 2 is the last statement executed in the method, so it returns 2.
6. If you have answered properly to the above questions, then you are definitely quite an expert. To prove it, tell us the value of b at the end of the call as well as the return value:
int b;
int foo () {
b = 0;
try {
b++;
return b;
}
finally {
b++;
}
}
My answer: b is incremented in the try block, then returned; return value is 1 from the method. Then the finally block executes and increments b, so it is 2 at the end (but return value is still 1).
I think that made sense. Nes pas?
Unix history and bang commands
The Unix bash shell provides many useful tools, one of them being then history command.
To see a list of previously executed commands, execute history into your shell. You can also supply an integer argument to limit the number of commands to show.
history 10
This can be piped into other commands, which can be useful for many purposes. For example, if I just finished a series of steps to get something working and wish to write a how-to entry for it, I could execute this:
history | cut -d ' ' -f 5- # cut out only the commands
The bash shell also provides the bang (!) command to execute the last command matching the provided command name.
$ echo foo foo $ !echo echo foo foo
Or you can use bang-bang (!!) to execute the last command
$ echo bar bar $ !! echo bar bar
This is useful when you get a permission denied error because you forgot to sudo.
$ Make me a sandwich. What? Make it yourself. $ sudo !! Okay.
You can also print the matching command without executing it via the :p modifier. This will also copy that matching command to the end of your history.
$ echo faz faz $ !!:p echo faz $ !! echo faz faz
To substitute certain parts of a command, you can use the :s modified.
$ echo baz baz $ !!:s/baz/Hello, World/
You can combine both modifiers as well, to preview a command before executing… might be a good idea if the command may cause damage.
Retrieving only arguments from a command can be done using the :$ :^, :n, and :* modifiers. The $ and ^ will look familiar to anyone who knows regex, they match the last and first arguments respectively. The :n modifier will match argument at position n (first argument being :1), and :* retrieves all arguments.
$ mkdir foobar && cd foobar # make temp dir $ touch file1 file2 file3 file23 file20 # dummy files $ ls file1 file2 file3 file23 file20 $ ls file2* # list files match pattern file2 file20 file23 $ rm !!:* # remove previously matched files rm file2*$ ls file1 file3
You can also use the :0 modifier to match the command name, but I don’t really see the use in that.
One last thing about history. You can start an interactive search through history by press Ctrl+r (^R), which will interactively display commands matching what you are typing (in reverse history order).