Организация и производительность кода jQuery
После ряда исследований по этому вопросу я много экспериментировал с шаблонами для упорядочивания кода jQuery (Ребекка Мерфи сделала презентация на этом на конференции jQuery, например).
Вчера я проверил шаблон (показательный) модуля. Результат выглядит немного напоминающим синтаксис YUI:
//global namespace MyNameSpace
if(typeof MNS=="undefined"||!MNS){var MNS={};}
//obfuscate module, just serving as a very simple example
MNS.obfuscate = function(){
//function to create an email address from obfuscated '@'
var email = function(){
$('span.email').each(function(){
var emailAddress = $(this).html().replace(' [ @ ] ','@');
$(this).html('<a href="mailto:' + emailAddress + '">' + emailAddress + '</a>');
});
};
return {
email: email
};
}();
//using the module when the dom ready
jQuery(document).ready(function($){
MNS.obfuscate.email();
});
В конце концов у меня было несколько модулей. Некоторые из них, естественно, включали "частные члены", которые в этом случае означают переменные и/или функции, которые были важны только для других функций в этом модуле и, таким образом, не попадали в оператор return.
Я думал, что связанные части моего кода (все, что связано с поиском, например), объединенное в модуле, имеет смысл, дает всю структуру.
Но после написания этого, я прочитал статью статьи от Джона (Resig), где он также пишет о производительности шаблона модуля:
"Создание функции с множеством свойств прототипа очень, очень быстро, полностью удаляет шаблон модуля и т.д. из воды. Таким образом, если у вас есть функция частого доступа (возвращающая объект) что вы хотите, чтобы люди взаимодействовали, тогда вам в ваших интересах, чтобы свойства объекта находились в цепочке прототипов и создавали его экземпляр. Вот он в коде:
// Very fast
function User(){}
User.prototype = { /* Lots of properties ... */ };
// Very slow
function User(){
return { /* Lots of properties */ };
}
(Джон упоминает, что он не против шаблона модуля "как таковой" - просто чтобы вы знали:)
Тогда я уже не был уверен, что с моим кодом я пойду в правильном направлении. Дело в том, что я не действительно нужен всем частным членам, и я также не думаю, что мне нужно наследование на данный момент.
Все, что я хочу сейчас, является читаемым/поддерживаемым шаблоном. Я предполагаю, что это сводится к личным предпочтениям в определенной степени, но я не хочу получать читаемый код, который имеет (довольно серьезные) проблемы с производительностью.
Я не эксперт по JavaScript и, тем более, эксперт, когда дело доходит до тестирования производительности. Итак, во-первых, я не знаю, насколько далеко сказались слова, о которых говорил Джон ( "часто доступная функция (возвращение объекта), с которой вы хотите, чтобы люди взаимодействовали с", множество свойств и т.д.) Применимы к моему коду. Документы, с которыми взаимодействует мой код, не являются огромными, с 100 или 1000 элементами. Так что, возможно, это не проблема.
Но мне показалось, что вместо того, чтобы просто
$('span.email').each(function(){
var emailAddress = $(this).html().replace(' [ @ ] ','@');
$(this).html('<a href="mailto:' + emailAddress + '">' + emailAddress + '</a>');
});
(внутри функции domready), я создаю две "дополнительные" функции, обфускацию и электронную почту из-за использования шаблона модуля. Создание дополнительных функций стоит некоторое время. Вопрос в следующем: будет ли это измеримо в моем случае?
Я не уверен, что в моем примере выше создано закрытие (в интересной записи на форуме jQuery я читал следующее: "Существует философская дискуссия о том, создает ли внутренняя функция замыкание, если оно не ссылаться на что-либо на объект внешней переменной функции..." ), но у меня были замыкания в моем реальном коде. И хотя я не думаю, что у меня были какие-либо циркулярные ссылки, я не знаю, как далеко это может привести к высокому потреблению/проблемам памяти с сборкой мусора.
Мне бы очень хотелось услышать ваши данные об этом и, возможно, увидеть некоторые примеры вашего кода. Кроме того, какие инструменты вы предпочитаете получать информацию о времени выполнения, памяти и использовании ЦП?
Ответы
Ответ 1
Я также не думаю, что мне нужно наследование на данный момент
Действительно. Это не относится к использованию модулей в качестве пространства имен. Это о аналогах экземпляров класса.
Объекты, созданные вами, создавая каждый экземпляр из полностью нового объекта {name: member}
, менее эффективны, чем созданные вами объекты с помощью new Class
с Class.prototype.name= member
. В случае прототипа значение member
является общим, что приводит к более легким экземплярам.
В вашем примере MNS
является одноэлементным, поэтому нет никакой пользы от совместного использования элементов через прототип.
Я не уверен, что в моем примере выше создается закрытие
Да, это так. Даже когда переменные не определены во внешней функции, по-прежнему существует объект LexicalEnvironment и scope, созданный для внешней функции, с привязкой this
и arguments
. Умный JS-движок может оптимизировать его, поскольку каждая внутренняя функция должна скрывать this
и arguments
своими собственными копиями, но я не уверен, что любая из существующих реализаций JS на самом деле это делает.
Разница в производительности в любом случае должна быть необнаруживаемой, поскольку вы не добавляете ничего существенного в аргументы. Для простого шаблона модуля я не считаю, что там есть какой-либо вред.
Кроме того, какие инструменты вы предпочитаете получать информацию о времени выполнения, памяти и использовании ЦП?
Запущенное место - это просто выполнить код 10000 раз в цикле for и посмотреть, сколько у него больше new Date().getTime()
, выполняется несколько раз на столько разных браузеров, сколько вы можете получить.
$(this).html(). replace ('[@]', '@');
(Что это должно делать? В настоящий момент он прочитает HTML-код span в новый String
, заменит только первый экземпляр [ @ ]
на @
и вернет новый String
Это не изменит существующий контент в DOM.)
Ответ 2
Сколько у вас Javascript? По моему опыту, на сайтах с большим количеством кода Javascript на страницах проблемы производительности обычно исходят из кода, который на самом деле что-то делает. Как правило, проблемы связаны с попытками сделать слишком много вещей или пытаться сделать что-то очень плохое. Примером может быть попытка сделать такие вещи, как обработчики привязки, к элементам в строках таблицы (большие таблицы) вместо использования чего-то вроде "живого".
Моя точка зрения состоит в том, что такие вещи, как то, как ваши модули или функции или что-то вроде организованного, почти наверняка не будут представлять собой какую-либо реальную проблему с производительностью на ваших страницах. Что побуждает вас идти на все эти неприятности?