views:

142

answers:

2

In JavaScript, you can define a callback handler in regex string replace operations:

str.replace(/str[123]|etc/, replaceCallback); 

Imagine you have a lookup object of strings and replacements.

var lookup = {"str1": "repl1", "str2": "repl2", "str3": "repl3", "etc": "etc" };

and this callback function:

var replaceCallback = function(match) { 
  if (lookup[match])
    return lookup[match]; 
  else
    return match;
}

How would you assess the performance of the above callback? Are there solid ways to improve it? Would

if (match in lookup) //....

or even

return lookup[match] || match;

lead to opportunities for the JS compiler to optimize, or is it all the same thing?

+3  A: 

You can use a benchmark tool like JSLitmus to benchmark different approaches. Be sure to test different browsers.

Annie
Yeah, that's the pragmatic approach. I was looking for some in-depth guru knowledge of how JS would handle this. I appreciate that it may very well be too implementation-specific to give a generalized answer.
Tomalak
+1  A: 

+1 to Annie about perf benchmarks.

But I would go with

return lookup[match] || match;

Not only is it just a single retrieval of the property (rather than -- barring optimization -- two, as in your earlier examples), but it's also shorter and (this is not always true of shorter code) clearer to any half-experienced JavaScript coder. It will tend to throw novices a bit, but one of the first things you want to teach novices is how the special (and excellent) || and && work in JavaScript, so...

It also works around a couple of (very) edge cases in some implementations. (Example: 'toString' in {} should be true [all objects inherit toString from the Object prototype], but it's false in Microsoft's JScript.)

Regarding optimizing: Barring the glaringly obvious (don't make your loop condition a function that has to go count things if it can be an invariant, avoid duplicating lookups unnecessarily), even absent the general discussion of whether it's worth worrying about this stuff before you see a problem (sometimes called "premature optimization"), it's especially true of JavaScript for the general web. Different micro-optimizations have different results in different implementations, sometimes conflicting results ("A" being better in Internet Explorer but much worse in FireFox, and the converse). Mostly it's a matter of wait until you see a specific problem, then address that specific problem.

I prefer simplicity and clarity, unless I have a strong reason to believe that something clunkier is going to give me a measurable, real-world improvement.

T.J. Crowder
+1 As object member lookups go, the compiler might very well be able to optimize that into a single call, even in the `if ...` variant (?). This is exactly the thing I want to know. P.S.: I'm very aware that this quite some micro-management. It *is* an academical question at the core.
Tomalak
@Tomalek: I wouldn't count on it, some implementations are shockingly un-optimized. In the ones that are (Chrome, for instance, is freakishly fast), you can get away with almost anything. :-) So you worry about the slow ones, if and when you see them.
T.J. Crowder
If you paste the if/else version of the function into the Closure Compiler, it spits out T.J.'s version--so I would guess that JS parsers might be able to make the same optimization. Not sure. Link to compiler so you can try it yourself: http://closure-compiler.appspot.com
Annie
@Annie: Yes, but again, you can't assume implementions are optimized to even that degree. Some are. Google's certainly is. In my experience, some really are not. (And for lurkers: The Closure Compiler and Chrome's V8 JavaScript engine -- which is *freaky* fast -- are both from the same people, the nice folks at Google with a major vested interest in web apps being fast.)
T.J. Crowder
@Annie: Wow, the Closure Compiler is neat. Thanks for that :)
Tomalak
@Tomalak: It is, it's very neat indeed. With the advanced options it does some things that can impact the function of your code, so you need to be aware of that. But when you know what it does (and the doc is pretty good for that), and you allow for it, it's a really cool tool.
T.J. Crowder
@T.J: Agreed 100%, some JS implementations are not optimized at all.
Annie
I think this answer is the bottom line. My preference would go with `return lookup[match] || match;` as well, and obviously there is no telling how JS engines handle this case internally.
Tomalak