Казалось бы, что может быть проще, чем написать функцию по удалению имени класса из свойства ноды. Наверное из-за того, что задачка легкая, ее решают все. Только все ее решают по-разному.
Вот как у прототайпа 1.6:
removeClassName: function(element, className) {
if (!(element = $(element))) return;
element.className = element.className.replace(
new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
return element;
},
Тут мы видим два дополнительных вызова внешних функций: $(element) и .strip(). А еще строка собирается для каждого обращения. И еще регексп компилится каждый раз и при выполнении запоминает и заполняет $1 и $2. А зачем?
А вот так у джейквери:
remove: function( elem, classNames ) {
if (elem.nodeType == 1)
elem.className = classNames !== undefined ?
jQuery.grep(elem.className.split(/\s+/), function(className){
return !jQuery.className.has( classNames, className );
}).join(" ") :
"";
},
Этот код пожестче. Здесь и split с join'ом, и поиск className в jQuery, а в className'е потом поиск has. Ну, а про вызов замыкания на каждый имеющийся класс вообще умолчим. Задача укорачивания строки решена максимально помпезно.
В обеих библиотеках эти функции оборачиваются во что-то еще. Так, в коде джейквери прямым текстом написано «internal only, use removeClass("class")». Такой подход действительно полезен, когда к библиотеке пишут плагины и расширения. Хуков можно надобавлять, потрейсить, попрофайлить или еще что-нибудь побочное прикрепить.
На наших сайтах добавление и удаление классов происходит очень часто, а иногда очень-очень часто для целой кучи элементов (где именно? — как зарелизим — покажу; UPD 03.01.2009: показываю). Когда пишешь такой код, не хочется думать о том, что вызов removeClassName() может быть дорогим. Хочется простой и быстрый метод. Например, такой:
var rexCache = {}, R = RegExp
Element.prototype.removeClassName = function (cn)
{
return this.className = this.className.replace
(
rexCache[cn] ||
(rexCache[cn] = new R('(?:^| +)(?:' + cn + '(?:$| +))+', 'g')), ' '
)
.replace(/^\s+|\s+$/g, '')
}
Тут мы убрали все, что смогли, и ничего лишнего не добавили. Даже кеш, и тот закеширован в локальной переменной. Ах да: вы только, пожалуйста, не используйте эту функцию, не протестировав ее хорошенько на своих проектах. То, что она работает у нас, еще ничего не значит. Мы же не Резиг, и не мощная тусовка рельсовиков. Мы просто Иншейкер (а как же без ссылки на мой любимый коктейльный сайт).
Понимаю, в новых браузерах и вызовы методов быстрые, и встроенное кеширование регэкспов есть, и строки там молниеносные, и вообще у них уже джит на дворе. Так что париться о таких вещах как-то неудобно. Но меня не покидает чувство, что усложнять не нужно.
Вот так не по-доброму получилось. И это при том, что я фанат всего что делает Резиг, и обожаю рельсы целиком, вместе с прототайпом.