>why is the practice of rerunning the same selector frowned upon?
Rerunning the same selector is frowned upon for (at least) 2 reasons:
1) It can make for more readable code.
Sometimes it makes more sense semantically to have a local variable that describes the role of an element in the particular block of code you are working on, rather than just what selector you are using to get at the element.
Also, it makes the code shorter and less complex, in your example "tabs" is shorter and easier to read than "$('a.tabs')" etc.
2) ...because it's a stupid simple optimization to make.
This goes in general for ANY JS variable that is not in local scope, is the property of an object, or is returned as the result of a function.
It's so easy to just cache it as a local variable, you should probably just do that once you are accessing it a few times.
Even that has the whiff of premature optimization, but it's so easy and has such a low impact (or even improvement) on readability, that it's no big deal.
What you're talking about is much harder to justify imho.
Re-running the same selector is an instance where you are re-running a function that will definitely return the same result that you just got.
Effectively it's the same as
function get5(){ return 5; };
var x = 4 + get5();
var y = 35 + get5();
...etc etc...so obviously it's better to just cache the return value and save the work of running a function.
It's hard to say because your examples aren't entirely clear to me, but I don't think your version as is is any better, perhaps even worse in some respects.
$('a.tab') returns A jQuery object that has a context that is a collection of DOM elements.
Your map function (which has the arguments reversed fyi) return's an array of jQuery objects (plural); each with a context of a single DOM element.
So you're creating a bunch of new instances of jQuery objects to possibly save an insignificant amount of context lookup time (getting the context of a jQuery object is not as heavy as selector lookup).
Again in the each you're creating a new jQuery object for each tab element, even though it was already in one. A jQuery object which will stick around via the closure.
So this is all to save looking up the index each click event for the tab (btw, something like $(this).index() would probably be cleaner) which may or may not be worth it.
I can see where you're going, and think you've got the right idea, but I also think what you use really depends on the situation.
I would say just write clean and idiomatic code first...that should be the default.... and then if you hit problems you can start optimizing based on the situation.
If looking up the index and context each click really is a problem (could be in some situations) you could find a solution based on the situation using strategies like event delegation, strategic naming, caching the index, associating them in a data structure of some kind, of any combination thereof.