why the third option is better than regex?
I think regex is pretty fas开发者_StackOverflow中文版t and the third option is confusing. What do you think?
http://jqfundamentals.com/book/ch09s12.html
// old way
if (type == 'foo' || type == 'bar') { ... }
// better
if (/^(foo|bar)$/.test(type)) { ... }
// object literal lookup
if (({ foo : 1, bar : 1 })[type]) { ... }
I'll humbly disagree with Rebecca Murphey and vote for simplicity, for the first option.
I think regex is pretty fast
Machine code is even faster, but we don't use it.
the third option is confusing
It's only confusing if you're unfamiliar with the trick. (And for people not used to seeing regex to compare two strings, second option will be even more confusing.)
I just made a rudimentary benchmark and I'm honestly not sure how she got those results... http://jsbin.com/uzuxi4/2/edit
Regex seems to scale the best, but the first is by far the fastest on all modern browsers. The last is excruciatingly slow. I understand the complexity theory between the three, but in practice, it doesn't seem that she's correct.
Let alone the fact that the first also has the best readability, it also seems to be the fastest. I even nested loops to take advantage of any browser caching of literal tables or constants (to no avail).
Edit: It appears that when an object is explicitly created, she is indeed correct, however: http://jsbin.com/uzuxi4/4/edit
function __hash() {
...
var type = 'bar';
var testobj = { foo : 1, bar : 1 };
var c = 0;
for (i = 0; i < 1000; i++) {
if (testobj[type]) {
for (j = 0; j < 10000; j++) {
if (testobj[type]) { c++; }
}
}
}
...
}
We see that once the object has an internal reference, the seek time drops to about 500 ms which is probably the plateau. Object key lookup may be the best for larger data-sets, but in practice I don't really see it as a viable option for every-day use.
- The first option involves potentially two string compares.
- The second option involves a parse each time.
- The third option does a simple hash of the string and then a hash table look
up, which is the most efficient in this case, in terms of the amount of work that needs to be done.
The third option also scales better than the other two as more alternative strings are added, because the first two are O(n) and the third is O(1) in the average case.
If we want to talk about which option is prettier / more maintainable, that's a whole separate conversation.
The first case should really be done with ===
to avoid any type coercions, but depending on the number of alternatives you need to check it can become O(N)
, however depending on your code most JS engines will be able to a simple pointer check for the comparison.
In the second case you use a RegExp, and while RegExps are very fast, they tend to be slower for simple equality decisions than more direct equality comparisons. Simple string comparisons like yours are likely to be a pointer compare in a modern JS engine, but if you use a regexp the regexp must read every character.
The third case is more tricky -- if you do have a lot of values to check it may be faster, especially if you cache the object rather than repeatedly recreating it as it will simply be a hash lookup -- the exact performance of the lookup depends on the engine though.
I suspect a switch statement would beat the object literal case though.
Out of curiosity I made a test (which you can see here), the fastest approach (in a webkit nightly at least) seems to be a switch statement, followed by if, followed by the object, with regexp's last.
Just wanted to weigh in here and remind everyone that this is an open-source book with contributions from many people! The section being discussed, indeed, is based on content provided by a community member. If you have suggestions for improving the section, by all means, please open an issue on the repository, or better, fork the repo and send me a pull request :)
That said, I have just set up a jsPerf test (http://jsperf.com/string-tests), and at least in Chrome, the results are the opposite of what the book says. I've opened an issue on the book, and will try to deal with this in the near future.
Finally, two things:
- I want to echo what another commenter said: perf optimizations are fun to talk about, and while there are some that really do matter, many don't. It's important to keep perspective on how much -- or little -- of a difference stuff like this makes.
- I also want to echo the commenter who said, essentially, that readability is in the eyes of the beholder. Something confusing to one person may be perfectly clear to another. I do believe we should strive for readability, but I think there's a happy medium. Reading code that was a bit perplexing to me at first opened my eyes to a lot of great techniques; I'd have hated if it had been written so the complete newb that I was at the time could understand it.
The object literal lookup is optimized with a hash lookup which only requires one logical check instead of n. In a longer list you also won't have to repeat "type == " a zillion times.
For simplicity and readability the first will win every time. It might not be as fast, but who cares unless it is in a heavily run loop.
Good compilers should optimize things like this away.
精彩评论