Ð jQuery Ð´Ð»Ñ Ñ ÑÐ°Ð½ÐµÐ½Ð¸Ñ Ð¾Ð±ÑабоÑÑиков ÑобÑÑий и дÑÑÐ³Ð¸Ñ Ð²ÑпомогаÑелÑнÑÑ Ð´Ð°Ð½Ð½ÑÑ , ÑвÑзаннÑÑ Ñ DOM-ÑлеменÑами, иÑполÑзÑеÑÑÑ Ð²Ð½ÑÑÑенний обÑекÑ, коÑоÑÑй в jQuery 1 доÑÑÑпен ÑеÑез $.data.
Ð jQuery 2 доÑÑÑп к Ð½ÐµÐ¼Ñ Ð·Ð°ÐºÑÑÑ ÑеÑез замÑкание, он ÑÑал локалÑной пеÑеменной внÑÑÑи jQuery Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ data_priv, но в оÑÑалÑном вÑÑ ÑабоÑÐ°ÐµÑ ÑоÑно Ñак, как опиÑано, и Ñ Ñеми же поÑледÑÑвиÑми.
$.data
ÐÑÑÑÐ¾ÐµÐ½Ð½Ð°Ñ ÑÑнкÑÐ¸Ñ $.data позволÑÐµÑ Ñ
ÑаниÑÑ Ð¸ пÑивÑзÑваÑÑ Ð¿ÑоизволÑнÑе знаÑÐµÐ½Ð¸Ñ Ðº DOM-Ñзлам.
ÐапÑимеÑ:
// пÑиÑвоиÑÑ
$(document).data('prop', { anything: "лÑбой обÑекÑ" })
// пÑоÑиÑаÑÑ
alert( $(document).data('prop').anything ) // лÑбой обÑекÑ
Реализована она Ñ Ð¸ÑÑÑм обÑазом. ÐаннÑе не Ñ ÑанÑÑÑÑ Ð² Ñамом ÑлеменÑе, а во внÑÑÑеннем обÑекÑе jQuery.
jQuery-вÑзов elem.data(prop, val) Ð´ÐµÐ»Ð°ÐµÑ ÑледÑÑÑее:
-
ÐÐ»ÐµÐ¼ÐµÐ½Ñ Ð¿Ð¾Ð»ÑÑÐ°ÐµÑ ÑникалÑнÑй иденÑиÑикаÑоÑ, еÑли Ñ Ð½ÐµÐ³Ð¾ Ñакого еÑÑ Ð½ÐµÑ:
elem[jQuery.expando] = id = ++jQuery.uuid; // ÑÑедÑÑвами jQuery
jQuery.expando â ÑÑо ÑлÑÑÐ°Ð¹Ð½Ð°Ñ ÑÑÑока, ÑгенеÑиÑÐ¾Ð²Ð°Ð½Ð½Ð°Ñ jQuery один Ñаз пÑи вÑ
оде на ÑÑÑаниÑÑ. УникалÑное ÑвойÑÑво, ÑÑÐ¾Ð±Ñ Ð½Ð¸Ñего важного не пеÑезапиÑаÑÑ.
-
â¦Ð Ñами даннÑе ÑÐ¾Ñ ÑанÑÑÑÑÑ Ð² ÑпеÑиалÑном обÑекÑе
jQuery.cache:jQuery.cache[id]['prop'] = { anything: "лÑбой обÑекÑ" };
Ðогда даннÑе ÑÑиÑÑваÑÑÑÑ Ð¸Ð· ÑлеменÑа:
- УникалÑнÑй иденÑиÑикаÑÐ¾Ñ ÑлеменÑа извлекаеÑÑÑ Ð¸Ð·
id = elem[ jQuery.expando]. - ÐаннÑе ÑÑиÑÑваÑÑÑÑ Ð¸Ð·
jQuery.cache[id].
СмÑÑл ÑÑого API в Ñом, ÑÑо DOM-ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð½Ð¸ÐºÐ¾Ð³Ð´Ð° не ÑÑÑлаеÑÑÑ Ð½Ð° JavaScript обÑÐµÐºÑ Ð½Ð°Ð¿ÑÑмÑÑ. ÐадейÑÑвÑеÑÑÑ Ð¸Ð´ÐµÐ½ÑиÑикаÑоÑ, а Ñами даннÑе Ñ
ÑанÑÑÑÑ Ð² jQuery.cache. УÑеÑек в IE не бÑдеÑ.
Ð ÑÐ¾Ð¼Ñ Ð¶Ðµ вÑе даннÑе извеÑÑÐ½Ñ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñеке, Ñак ÑÑо можно клониÑоваÑÑ Ñ Ð½Ð¸Ð¼Ð¸ и Ñ.п.
Ðак побоÑнÑй ÑÑÑÐµÐºÑ â Ð²Ð¾Ð·Ð½Ð¸ÐºÐ°ÐµÑ ÑÑеÑка памÑÑи, еÑли ÑÐ»ÐµÐ¼ÐµÐ½Ñ ÑдалÑн из DOM без дополниÑелÑной оÑиÑÑки.
ÐÑимеÑÑ ÑÑеÑек в jQuery
СледÑÑÑÐ°Ñ ÑÑнкÑÐ¸Ñ leak ÑоздаÑÑ jQuery-ÑÑеÑÐºÑ Ð²Ð¾ вÑеÑ
бÑаÑзеÑаÑ
:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<div id="data"></div>
<script>
function leak() {
$('<div/>')
.html(new Array(1000).join('text'))
.click(function() {})
.appendTo('#data');
document.getElementById('data').innerHTML = ''; // (*)
}
var interval = setInterval(leak, 10)
</script>
УÑеÑка идÑÑ...
<input type="button" onclick="clearInterval(interval)" value="stop" />
УÑеÑка пÑоиÑÑ
Ð¾Ð´Ð¸Ñ Ð¿Ð¾ÑомÑ, ÑÑо обÑабоÑÑик ÑобÑÑÐ¸Ñ Ð² jQuery Ñ
ÑаниÑÑÑ Ð² даннÑÑ
ÑлеменÑа. Ð ÑÑÑоке (*) ÑÐ»ÐµÐ¼ÐµÐ½Ñ ÑдалÑн оÑиÑÑкой ÑодиÑелÑÑкого innerHTML, но в jQuery.cache даннÑе оÑÑалиÑÑ.
Ðолее Ñого, ÑиÑÑема обÑабоÑки ÑобÑÑий в jQuery ÑÑÑÑоена Ñак, ÑÑо вмеÑÑе Ñ Ð¾Ð±ÑабоÑÑиком в даннÑÑ Ñ ÑаниÑÑÑ Ð¸ ÑÑÑлка на ÑлеменÑ, Ñак ÑÑо в иÑоге оба â и обÑабоÑÑик и ÑÐ»ÐµÐ¼ÐµÐ½Ñ â оÑÑаÑÑÑÑ Ð² памÑÑи вмеÑÑе Ñо вÑем замÑканием!
ÐÑÑ Ð±Ð¾Ð»ÐµÐµ пÑоÑÑой пÑÐ¸Ð¼ÐµÑ ÑÑеÑки:
ÐÑÐ¾Ñ ÐºÐ¾Ð´ Ñакже ÑоздаÑÑ ÑÑеÑкÑ:
function leak() {
$('<div/>')
.click(function() {})
}
â¦Ð¢Ð¾ еÑÑÑ, Ð¼Ñ ÑоздаÑм ÑлеменÑ, веÑаем на него обÑабоÑÑик⦠РвÑÑ.
Такой код ведÑÑ Ðº ÑÑеÑке памÑÑи как Ñаз поÑомÑ, ÑÑо ÑÐ»ÐµÐ¼ÐµÐ½Ñ <div> Ñоздан, но нигде не ÑазмеÑÑн :). ÐоÑле вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÑÑнкÑии ÑÑÑлка на него ÑеÑÑеÑÑÑ. Ðо обÑабоÑÑик ÑобÑÑÐ¸Ñ click Ñже ÑоÑ
Ñанил даннÑе в jQuery.cache, коÑоÑÑе заÑÑÑеваÑÑ Ñам навÑегда.
ÐÑполÑзÑем jQuery без ÑÑеÑек
ЧÑÐ¾Ð±Ñ Ð¸Ð·Ð±ÐµÐ¶Ð°ÑÑ ÑÑеÑек, опиÑаннÑÑ Ð²ÑÑе, Ð´Ð»Ñ ÑÐ´Ð°Ð»ÐµÐ½Ð¸Ñ ÑлеменÑов иÑполÑзÑйÑе ÑÑнкÑии jQuery API, а не ÑиÑÑÑй JavaScript.
ÐеÑÐ¾Ð´Ñ remove(), empty() и html() пÑовеÑÑÑÑ Ð´Ð¾ÑеÑние ÑлеменÑÑ Ð½Ð° налиÑие даннÑÑ Ð¸ оÑиÑаÑÑ Ð¸Ñ . ÐÑо неÑколÑко замедлÑÐµÑ Ð¿ÑоÑедÑÑÑ ÑдалениÑ, но заÑо оÑвобождаеÑÑÑ Ð¿Ð°Ð¼ÑÑÑ.
Ð ÑÑаÑÑÑÑ Ð¾Ð±Ð½Ð°ÑÑжиÑÑ Ñакие ÑÑеÑки легко. ÐÑовеÑÑÑе ÑÐ°Ð·Ð¼ÐµÑ $.cache. ÐÑли он болÑÑой и ÑаÑÑÑÑ, Ñо изÑÑиÑе кÑÑ, поÑмоÑÑиÑе, какие запиÑи оÑÑаÑÑÑÑ Ð¸ поÑемÑ.
УлÑÑÑение пÑоизводиÑелÑноÑÑи jQuery
У ÑпоÑоба оÑганизаÑии внÑÑÑÐµÐ½Ð½Ð¸Ñ Ð´Ð°Ð½Ð½ÑÑ , пÑименÑнного в jQuery, еÑÑÑ Ð²Ð°Ð¶Ð½Ñй побоÑнÑй ÑÑÑекÑ.
ФÑнкÑии, ÑдалÑÑÑие ÑлеменÑÑ, Ñакже Ð´Ð¾Ð»Ð¶Ð½Ñ ÑдалиÑÑ Ð¸ ÑвÑзаннÑе Ñ Ð½Ð¸Ð¼Ð¸ внÑÑÑенние даннÑе. ÐÐ»Ñ ÑÑого нÑжно Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ ÑдалÑемого ÑлеменÑа пÑовеÑиÑÑ â а Ð½ÐµÑ Ð»Ð¸ Ñего во внÑÑÑеннем Ñ ÑанилиÑе? Ð, еÑли еÑÑÑ â ÑдалиÑÑ.
ÐÑедÑÑавим, ÑÑо Ñ Ð½Ð°Ñ ÐµÑÑÑ Ð±Ð¾Ð»ÑÑÐ°Ñ ÑаблиÑа <table>, и Ð¼Ñ Ñ
оÑим обновиÑÑ ÐµÑ ÑодеÑжимое на новое. ÐÑзов $('table').html(новÑе даннÑе) пеÑед вÑÑавкой новÑÑ
даннÑÑ
аккÑÑаÑно ÑÐ´Ð°Ð»Ð¸Ñ ÑÑаÑÑе: пÑÐ¾Ð±ÐµÐ¶Ð¸Ñ Ð¿Ð¾ вÑем ÑÑейкам и пÑовеÑÐ¸Ñ Ð²Ð½ÑÑÑеннее Ñ
ÑанилиÑе.
ÐÑли ÑÑо болÑÑÐ°Ñ ÑаблиÑа, Ñо обÑабоÑÑики, ÑкоÑее вÑего, ÑÑоÑÑ Ð½Ðµ на ÑÑейкаÑ
, а на Ñамом ÑлеменÑе <table>, Ñо еÑÑÑ Ð¸ÑполÑзÑеÑÑÑ Ð´ÐµÐ»ÐµÐ³Ð¸Ñование. Ð, знаÑиÑ, ÑÑаÑиÑÑ Ð²ÑÐµÐ¼Ñ Ð½Ð° пÑовеÑÐºÑ Ð²ÑеÑ
подÑлеменÑов ни к ÑемÑ.
Ðо jQuery-Ñо об ÑÑом не знаеÑ!
ЧÑÐ¾Ð±Ñ Â«Ð³ÑÑзно» ÑдалиÑÑ ÑлеменÑ, без ÑиÑÑки, Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ ÑделаÑÑ ÑÑо ÑеÑез «обÑÑнÑе» DOM-вÑÐ·Ð¾Ð²Ñ Ð¸Ð»Ð¸ воÑполÑзоваÑÑÑÑ Ð¼ÐµÑодом detach(). Ðго оÑиÑиалÑное назнаÑение â в Ñом, ÑÑÐ¾Ð±Ñ ÑбÑаÑÑ ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð¸Ð· DOM, но ÑÐ¾Ñ ÑаниÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑÑ Ð´Ð»Ñ Ð²ÑÑавки (и, ÑооÑвеÑÑÑвенно, оÑÑавиÑÑ Ð½Ð° нÑм вÑе даннÑе). РнеоÑиÑиалÑное â бÑÑÑÑо ÑбÑаÑÑ ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð¸Ð· DOM, без ÑиÑÑки.
Ðозможен и пÑомежÑÑоÑнÑй ваÑианÑ: никÑо не меÑÐ°ÐµÑ ÑделаÑÑ elem.detach() и помеÑÑиÑÑ Ð²Ñзов elem.remove() в setTimeout. Ð ÑезÑлÑÑаÑе оÑиÑÑка бÑÐ´ÐµÑ Ð¿ÑоиÑÑ
одиÑÑ Ð°ÑинÑ
Ñонно и незамеÑно.
ÐÑого
- УÑеÑки памÑÑи пÑи иÑполÑзовании jQuery возможнÑ, еÑли ÑеÑез DOM-меÑÐ¾Ð´Ñ ÑдалÑÑÑ ÑлеменÑÑ, к коÑоÑÑм пÑивÑÐ·Ð°Ð½Ñ Ð´Ð°Ð½Ð½Ñе или обÑабоÑÑики.
- ЧÑÐ¾Ð±Ñ ÑÑеÑки не бÑло, доÑÑаÑоÑно ÑбедиÑÑÑÑ, ÑÑо ÑÐ»ÐµÐ¼ÐµÐ½Ñ ÑдалÑеÑÑÑ Ð¿Ñи помоÑи меÑодов jQuery.
- ÐобоÑнÑй ÑÑÑÐµÐºÑ â пÑи Ñдалении ÑлеменÑов jQuery должна пÑовеÑиÑÑ Ð½Ð°Ð»Ð¸Ñие даннÑÑ Ð´Ð»Ñ Ð½Ð¸Ñ . ÐÑо ÑилÑно замедлÑÐµÑ Ð¿ÑоÑеÑÑ ÑÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð±Ð¾Ð»ÑÑого поддеÑева DOM.
- ÐÑли Ð¼Ñ Ð·Ð½Ð°ÐµÐ¼, ÑÑо обÑабоÑÑиков и даннÑÑ
Ð½ÐµÑ â гоÑаздо бÑÑÑÑее ÑдалÑÑÑ ÑлеменÑÑ Ð¿Ñи помоÑи вÑзова
detachили обÑÑного DOM.

ÐомменÑаÑии
<code>, Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÑÑÑок кода — Ñег<pre>, еÑли болÑÑе 10 ÑÑÑок — ÑÑÑÐ»ÐºÑ Ð½Ð° пеÑоÑниÑÑ (plnkr, JSBin, codepenâ¦)