<script type="text/javascript">
/* Font Face Observer v2.0.13 - © Bram Stein. License: BSD-3-Clause */(function(){'use strict';
var f,g=[];
function l(a){g.push(a);
1==g.length&&f()}function m(){for(;
g.length;
)g[0](),g.shift()}f=function(){setTimeout(m)};
function n(a){this.a=p;
this.b=void 0;
this.f=[];
var b=this;
try{a(function(a){q(b,a)},function(a){r(b,a)})}catch(c){r(b,c)}}var p=2;
function t(a){return new n(function(b,c){c(a)})}function u(a){return new n(function(b){b(a)})}function q(a,b){if(a.a==p){if(b==a)throw new TypeError;
var c=!1;
try{var d=b&&b.then;
if(null!=b&&"object"==typeof b&&"function"==typeof d){d.call(b,function(b){c||q(a,b);
c=!0},function(b){c||r(a,b);
c=!0});
return}}catch(e){c||r(a,e);
return}a.a=0;
a.b=b;
v(a)}}
function r(a,b){if(a.a==p){if(b==a)throw new TypeError;
a.a=1;
a.b=b;
v(a)}}function v(a){l(function(){if(a.a!=p)for(;
a.f.length;
){var b=a.f.shift(),c=b[0],d=b[1],e=b[2],b=b[3];
try{0==a.a?"function"==typeof c?e(c.call(void 0,a.b)):e(a.b):1==a.a&&("function"==typeof d?e(d.call(void 0,a.b)):b(a.b))}catch(h){b(h)}}})}n.prototype.g=function(a){return this.c(void 0,a)};
n.prototype.c=function(a,b){var c=this;
return new n(function(d,e){c.f.push([a,b,d,e]);
v(c)})};
function w(a){return new n(function(b,c){function d(c){return function(d){h[c]=d;
e+=1;
e==a.length&&b(h)}}var e=0,h=[];
0==a.length&&b(h);
for(var k=0;
k<a.length;
k+=1)u(a[k]).c(d(k),c)})}function x(a){return new n(function(b,c){for(var d=0;
d<a.length;
d+=1)u(a[d]).c(b,c)})};
window.Promise||(window.Promise=n,window.Promise.resolve=u,window.Promise.reject=t,window.Promise.race=x,window.Promise.all=w,window.Promise.prototype.then=n.prototype.c,window.Promise.prototype["catch"]=n.prototype.g);
}());
(function(){function l(a,b){do***ent.addEventListener?a.addEventListener("scroll",b,!1):a.attachEvent("scroll",b)}function m(a){do***ent.body?a():do***ent.addEventListener?do***ent.addEventListener("DOMContentLoaded",function c(){do***ent.removeEventListener("DOMContentLoaded",c);
a()}):do***ent.attachEvent("onreadystatechange",function k(){if("interactive"==do***ent.readyState||"complete"==do***ent.readyState)do***ent.detachEvent("onreadystatechange",k),a()})};
function r(a){this.a=do***ent.createElement("div");
this.a.setAttribute("aria-hidden","true");
this.a.appendChild(do***ent.createTextNode(a));
this.b=do***ent.createElement("span");
this.c=do***ent.createElement("span");
this.h=do***ent.createElement("span");
this.f=do***ent.createElement("span");
this.g=-1;
this.b.style.cssText="max-width:none;
display:inline-block;
position:absolute;
height:100%;
width:100%;
overflow:scroll;
font-size:16px;
";
this.c.style.cssText="max-width:none;
display:inline-block;
position:absolute;
height:100%;
width:100%;
overflow:scroll;
font-size:16px;
";
this.f.style.cssText="max-width:none;
display:inline-block;
position:absolute;
height:100%;
width:100%;
overflow:scroll;
font-size:16px;
";
this.h.style.cssText="display:inline-block;
width:200%;
height:200%;
font-size:16px;
max-width:none;
";
this.b.appendChild(this.h);
this.c.appendChild(this.f);
this.a.appendChild(this.b);
this.a.appendChild(this.c)}
function t(a,b){a.a.style.cssText="max-width:none;
min-width:20px;
min-height:20px;
display:inline-block;
overflow:hidden;
position:absolute;
width:auto;
margin:0;
padding:0;
top:-999px;
white-space:nowrap;
font-synthesis:none;
font:"+b+";
"}function y(a){var b=a.a.offsetWidth,c=b+100;
a.f.style.width=c+"px";
a.c.scrollLeft=c;
a.b.scrollLeft=a.b.scrollWidth+100;
return a.g!==b?(a.g=b,!0):!1}function z(a,b){function c(){var a=k;
y(a)&&a.a.parentNode&&b(a.g)}var k=a;
l(a.b,c);
l(a.c,c);
y(a)};
function A(a,b){var c=b||{};
this.family=a;
this.style=c.style||"normal";
this.weight=c.weight||"normal";
this.stretch=c.stretch||"normal"}var B=null,C=null,E=null,F=null;
function G(){if(null===C)if(J()&&/Apple/.test(window.navigator.vendor)){var a=/AppleWebKit\/([0-9]+)(?:\.([0-9]+))(?:\.([0-9]+))/.exec(window.navigator.userAgent);
C=!!a&&603>parseInt(a[1],10)}else C=!1;
return C}function J(){null===F&&(F=!!do***ent.fonts);
return F}
function K(){if(null===E){var a=do***ent.createElement("div");
try{a.style.font="condensed 100px sans-serif"}catch(b){}E=""!==a.style.font}return E}function L(a,b){return[a.style,a.weight,K()?a.stretch:"","100px",b].join(" ")}
A.prototype.load=function(a,b){var c=this,k=a||"BESbswy",q=0,D=b||3E3,H=(new Date).getTime();
return new Promise(function(a,b){if(J()&&!G()){var M=new Promise(function(a,b){function e(){(new Date).getTime()-H>=D?b():do***ent.fonts.load(L(c,'"'+c.family+'"'),k).then(function(c){1<=c.length?a():setTimeout(e,25)},function(){b()})}e()}),N=new Promise(function(a,c){q=setTimeout(c,D)});
Promise.race([N,M]).then(function(){clearTimeout(q);
a(c)},function(){b(c)})}else m(function(){function u(){var b;
if(b=-1!=
f&&-1!=g||-1!=f&&-1!=h||-1!=g&&-1!=h)(b=f!=g&&f!=h&&g!=h)||(null===B&&(b=/AppleWebKit\/([0-9]+)(?:\.([0-9]+))/.exec(window.navigator.userAgent),B=!!b&&(536>parseInt(b[1],10)||536===parseInt(b[1],10)&&11>=parseInt(b[2],10))),b=B&&(f==v&&g==v&&h==v||f==w&&g==w&&h==w||f==x&&g==x&&h==x)),b=!b;
b&&(d.parentNode&&d.parentNode.removeChild(d),clearTimeout(q),a(c))}function I(){if((new Date).getTime()-H>=D)d.parentNode&&d.parentNode.removeChild(d),b(c);
else{var a=do***ent.hidden;
if(!0===a||void 0===a)f=e.a.offsetWidth,
g=n.a.offsetWidth,h=p.a.offsetWidth,u();
q=setTimeout(I,50)}}var e=new r(k),n=new r(k),p=new r(k),f=-1,g=-1,h=-1,v=-1,w=-1,x=-1,d=do***ent.createElement("div");
d.dir="ltr";
t(e,L(c,"sans-serif"));
t(n,L(c,"serif"));
t(p,L(c,"monospace"));
d.appendChild(e.a);
d.appendChild(n.a);
d.appendChild(p.a);
do***ent.body.appendChild(d);
v=e.a.offsetWidth;
w=n.a.offsetWidth;
x=p.a.offsetWidth;
I();
z(e,function(a){f=a;
u()});
t(e,L(c,'"'+c.family+'",sans-serif'));
z(n,function(a){g=a;
u()});
t(n,L(c,'"'+c.family+'",serif'));
z(p,function(a){h=a;
u()});
t(p,L(c,'"'+c.family+'",monospace'))})})};
"object"===typeof module?module.exports=A:(window.FontFaceObserver=A,window.FontFaceObserver.prototype.load=A.prototype.load);
}());
(function( w ){
if( w.do***ent.do***entElement.className.indexOf( "fonts-loaded" ) > -1 ){ return;
}
var html = do***ent.do***entElement;
var FS500 = new w.FontFaceObserver("Fira Sans", { weight: 500
});
FS500.load().then(function() {
html.classList.add('fonts-loaded');
sessionStorage.fontsLoaded = true;
console.log('FS500-loaded');
}).catch(function () {
sessionStorage.fontsLoaded = false;
console.log('FS500-unloaded');
});
if (sessionStorage.fontsLoaded) {
html.classList.add('fonts-loaded');
}
}(this));
</script>
<script type="text/javascript" src="https://dr.habracdn.net/habrcom/javascripts/1575787116/libs/jquery-1.8.3.min.js"></script>
habrahabr.ru is using jquery
<script type="text/javascript" src="https://cdn.onthe.io/io.js/Tn4LrERWU1qX"></script>
<script type="text/javascript">
window._io_config = window._io_config || {};
window._io_config["0.2.0"] = window._io_config["0.2.0"] || [];
window._io_config["0.2.0"].push({
"page_url": "https:\/\/habr.com\/ru\/",
"page_url_canonical": "https:\/\/habr.com\/ru\/",
"page_title": "Лучшие публикации за сутки",
"page_type": "main",
"page_language": "ru"
});
</script>
<script type="text/javascript">
window.create_callback_for_blocked = function(key) {
return function() {
googletag.cmd.push(function () {
googletag.display(key);
});
}
}
window.habr_blockers_checker = new function() {
var result;
var callbacksQueue = [];
var calledOnce = false;
function fireCallbacks() {
callbacksQueue.forEach(function(callback) {
callback(result);
});
callbacksQueue = [];
}
this.detect = function(imgUrl, callback) {
var checksRemain = 2;
var detected = false;
var error1 = false;
var error2 = false;
if (typeof callback !== 'function') {
return;
};
callbacksQueue.push(callback);
if (typeof result !== 'undefined') {
fireCallbacks();
};
if (calledOnce) {
return;
}
calledOnce = true;
imgUrl += '?ch=*&rn=*';
function beforeCheck(timeout) {
if (checksRemain === 0 || timeout > 1E3) {
result = checksRemain === 0 && detected;
fireCallbacks();
} else {
setTimeout(function() {
beforeCheck(timeout * 2)
}, timeout * 2);
}
}
function checkImages() {
if (--checksRemain) {
return;
};
detected = !error1 && error2;
}
var random = Math.random() * 11;
var img1 = new Image;
img1.onload = checkImages;
img1.onerror = function() {
error1 = true;
checkImages()
};
img1.src = imgUrl.replace(/\*/, 1).replace(/\*/, random);
var img2 = new Image;
img2.onload = checkImages;
img2.onerror = function() {
error2 = true;
checkImages()
};
img2.src = imgUrl.replace(/\*/, 2).replace(/\*/, random);
beforeCheck(250, callback)
};
this.detectWrapper = function(callback) {
return this.detect('/images/px.gif', callback);
};
};
window.display_dfp_slot = function(key) {
if (window.habr_blockers_checker) {
window.habr_blockers_checker.detectWrapper(window.create_callback_for_blocked(key));
} else {
window.create_callback_for_blocked(key)();
}
};
</script>
<script type="text/javascript" src="https://dr.habracdn.net/habrcom/javascripts/1575787116/libs/raven.min.js"></script>
<script type="text/javascript">
Raven.config('https://830576edd4b7478086093f693a5a0df5@s.tmtm.ru/37').install()
</script>
<script type="text/javascript" src="https://dr.habracdn.net/habrcom/javascripts/1575787116/_parts/advertise.js"></script>
<script type="text/javascript" src="https://dr.habracdn.net/habrcom/javascripts/1575787116/_parts/adriver.js"></script>
<script type="text/javascript" src="https://www.googletagservices.com/tag/js/gpt.js"></script>
<script type="text/javascript" src="https://static.criteo.net/js/ld/publishertag.js"></script>
<script type="text/javascript">
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
</script>
<script type="text/javascript">
// TODO: move this code to module
// move dot in chains to start of line and use one indent level:
// ```
// start()
// .chainEnd()
// ```
function display_yandex_rtb(yandexId, divId) {
$('#' + divId).show();
(function(w, d, n, s, t) {
w[n] = w[n] || [];
w[n].push(function() {
Ya.Context.AdvManager.render({
blockId: yandexId,
renderTo: divId,
async: true
});
});
t = d.getElementsByTagName('script')[0];
s = d.createElement('script');
s.type = 'text/javascript';
s.src = '//an.yandex.ru/system/context.js';
s.async = true;
t.parentNode.insertBefore(s, t);
})(this, this.do***ent, 'yandexContextAsyncCallbacks');
}
function listen_googletag_and_render_yandex(yandexId, targetDivId) {
if (!window.googletag || !window.googletag.cmd) {
return;
}
window.googletag.cmd.push(function() {
if (!window.googletag.pubads) {
return;
}
window.googletag.pubads()
.addEventListener('slotRenderEnded', function(event) {
var divId = event.slot.getSlotElementId();
if (divId === targetDivId && event.isEmpty) {
window.display_yandex_rtb(yandexId, divId);
}
});
});
}
function getRoxotItem(storageKey, config) {
if (config) {
var { randomVal, returnCode
} = config;
} else {
var randomVal = 100,
returnCode = '101';
}
try {
var groupId = localStorage.getItem(storageKey);
if (groupId === null) {
groupId = 1 + Math.floor(Math.random() * randomVal);
localStorage.setItem(storageKey, groupId);
}
return '' + groupId;
}
catch (e) {
return returnCode;
}
}
function getRoxotEvent() {
return '' + (1 + Math.floor(Math.random() * 100));
}
function leftpad(str, len, ch) {
str = String(str);
var i = -1;
if (!ch && ch !== 0) {
ch = ' ';
};
len = len - str.length;
while (++i < len) {
str = ch + str;
}
return str;
}
var WEEK_DAYS = ['su', 'mo', 'tu', 'we', 'th', 'fr', 'sa'];
function initializeDFP(usesABP) {
var currentDate = new Date();
var hours = currentDate.getHours();
var hoursStr = leftpad(hours, 2, '0');
var weekDayCode = WEEK_DAYS[currentDate.getDay()];
googletag.cmd.push(function() {
if (usesABP) {
googletag.defineSlot('/235032688/HH/HH02_inpage_wide', [[1, 1], [780, 130], [780, 200], [780, ***0], [780, 110], [728, 90]], 'div-gpt-hh-inpage-wide').addService(googletag.pubads());
window.listen_googletag_and_render_yandex('R-A-149298-32', 'div-gpt-hh-inpage-wide');
} else {
googletag.defineSlot('/235032688/HH/HH02_inpage_wide', [[1, 1], [780, 200], [780, 130], [780, ***0], [780, 110], [728, 90], [780, 195], [780, 210], [780, 260]], 'div-gpt-hh-inpage-wide').addService(googletag.pubads());
window.listen_googletag_and_render_yandex('R-A-149298-36', 'div-gpt-hh-inpage-wide');
}
if (usesABP) {
googletag.defineSlot('/235032688/HH/HH01_ATF_Poster', [[1, 1], [300, 500], [300, 250], [300, 300], [300, 400], [300, 200], [300, 100], [240, 400]], 'div-gpt-hh-atf').addService(googletag.pubads());
window.listen_googletag_and_render_yandex('R-A-149298-31', 'div-gpt-hh-atf');
} else {
googletag.defineSlot('/235032688/HH/HH01_ATF_Poster', [[1, 1], [300, 500], [300, 600], [300, 250], [300, 300], [300, 400], [300, 200], [300, 150], [300, 100], [240, 400]], 'div-gpt-hh-atf').addService(googletag.pubads());
window.listen_googletag_and_render_yandex('R-A-149298-35', 'div-gpt-hh-atf');
}
googletag.pubads().enableSingleRequest();
if (!usesABP) {
googletag.pubads().disableInitialLoad();
//We will wait for the Criteo Bidder Call before calling the adserver
}
googletag.pubads().collapseEmptyDivs();
googletag.pubads().
setTargeting('roxot-group-id', getRoxotItem('roxot-gid', { randomVal: 10000, returnCode: '10001'})).
setTargeting('roxot-sector-id', getRoxotItem('roxot-sid')).
setTargeting('roxot-deep', getRoxotItem('roxot-deep')).
setTargeting('roxot-event-group-id', getRoxotEvent()).
setTargeting('roxot-event', getRoxotEvent()).
setTargeting('roxot-event-deep', getRoxotEvent()).
setTargeting('roxot-minutes', (new Date).getUTCMinutes().toString()).
setTargeting('roxot-hours', (new Date).getUTCHours().toString()).
setTargeting('roxot-day', (new Date).getUTCDay().toString()).
setTargeting('chr', hoursStr).
setTargeting('cwd', weekDayCode).
setTargeting('aa', (usesABP) ? 'yes' : 'no').
setTargeting('path', window.location.pathname + window.location.search).
setTargeting('feedtype', ["top_daily","posts"]).
setTargeting('dev', [0]).
setTargeting('user', ["guest","registered"]).
setTargeting('pagetype', ["feed"]);
googletag.enableServices();
if (!usesABP) {
window.Criteo = window.Criteo || {};
window.Criteo.events = window.Criteo.events || [];
var launchAdServer = function () {
googletag.cmd.push(function () {
Criteo.SetDFPKeyValueTargeting();
//This will append Criteo keywords to the adserver call
googletag.pubads().refresh();
//This will trigger the adserver call
});
};
Criteo.events.push(function () {
var adUnits = {
'placements': [
{'slotid': 'div-gpt-hh-inpage-wide', 'zoneid': 1173491}, // TMTM - RU - CDB - SA - Habr - 780x***0
{'slotid': 'div-gpt-hh-atf', 'zoneid': 1173489}, // TMTM - RU - CDB - SA - Habr - 300x600
]
};
// Define the price band range
Criteo.SetLineItemRanges('0..599:1;
600..1398:2;
1400..3000:5');
// Call Criteo and execute the callback function for a given timeout
Criteo.RequestBids(adUnits, launchAdServer, 750);
});
}
});
}
if (window.habr_blockers_checker) {
window.habr_blockers_checker.detectWrapper(initializeDFP);
} else {
initializeDFP(false);
}
</script>
<script type="text/javascript">
$(do***ent).ready(function () {
if (!$.cookie('split201901')) {
$.cookie(
'split201901',
'B',
{
expires: 3 * 7,
domain: 'habr.com',
path: '/',
secure: true
}
);
}
});
</script>
<script type="text/javascript">
window.display_dfp_slot('div-gpt-hh-inpage-wide');
</script>
<script type="text/javascript">
window.display_dfp_slot('div-gpt-hh-atf');
</script>
<script type="text/javascript">
$(do***ent).ready(function () {
window.voteReasonsList = JSON.parse('{"1":{"id":"1","title":"Низкий технический уровень материала","order":1},"2":{"id":"2","title":"Больше рекламы, чем пользы","order":2},"3":{"id":"3","title":"Не соответствует тематике Хабра","order":3},"4":{"id":"4","title":"В тексте много ошибок и опечаток","order":4},"5":{"id":"5","title":"Пост небрежно оформлен","order":5},"6":{"id":"6","title":"Личная неприязнь к автору или компании","order":6},"7":{"id":"7","title":"В статье нет новой для меня информации","order":7},"8":{"id":"8","title":"Ничего не понял после прочтения","order":8},"9":{"id":"9","title":"Другое","order":9}}');
});
</script>
<script type="text/javascript">
// global vars
var g_base_url = 'habr.com/ru';
var g_base_fullurl = 'https://habr.com/ru/';
var g_tmid_fullurl = 'https://account.habr.com/';
var g_is_guest = false;
var g_show_xpanel = false;
var g_is_enableShortcuts = '1';
var g_current_hl = 'ru';
var g_current_fl = 'ru';
</script>
<script type="text/javascript" src="https://dr.habracdn.net/habrcom/javascripts/1575787116/vendors.bundle.js"></script>
<script type="text/javascript" src="https://dr.habracdn.net/habrcom/javascripts/1575787116/main.bundle.js"></script>
<script type="text/javascript">
MathJax.Hub.Config({
showProcessingMessages: false,
showMathMenu: true,
tex2jax: {
inlineMath: [['$inline$','$inline$']],
displayMath: [['$$display$$','$$display$$']],
processEscapes: true
},
MathMenu: {
showRenderer: true,
showContext: true
}
});
MathJax.Extension.Img2jax = {
PreProcess: function (element) {
var hasMath = false;
var images = element.querySelectorAll('[data-tex]');
for (var i = images.length - 1;
i >= 0;
i--) {
var img = images[i];
var tex = img.alt.replace(/(\r\n|\n|\r)/gm, " ");
if (tex && tex[0] === '$'){
var script = do***ent.createElement("script");
script.type = "math/tex";
hasMath = true;
if (img.getAttribute('data-tex') == "display"){script.type += ";
mode=display"}
MathJax.HTML.setScript(script, tex.substring(1,tex.length-1));
img.parentNode.replaceChild(script,img);
}
}
}
};
MathJax.Hub.Register.PreProcessor(["PreProcess", MathJax.Extension.Img2jax]);
</script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS_SVG-full&locale=ru"></script>
<script type="text/javascript">
</script>
<script type="text/javascript" src="https://dr.habracdn.net/habrcom/javascripts/1575787116/check-login.js"></script>
<script type="text/javascript">
(function(m,e,t,r,i,k,a){
m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)
})(window, do***ent, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(24049213, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<script type="text/javascript">
function callGA(usesABP) {
if (typeof window.adb1 === 'undefined') {
window.adb1 = 'yes';
}
if (usesABP) {
window.adb1 = 'aa';
}
var user_type = 'guest';
var page_type = "other";
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;
i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();
a=s.createElement(o),
m=s.getElementsByTagName(o)[0];
a.async=1;
a.src=g;
m.parentNode.insertBefore(a,m)
})(window,do***ent,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-726094-1', 'auto');
ga('create', 'UA-726094-24', 'auto', {'name': 'HGM', 'allowLinker': true});
ga('HGM.require', 'linker');
ga('HGM.linker:autoLink', ['toster.ru', 'habr.com', 'account.habr.com', 'm.habr.com']);
ga('require', 'displayfeatures');
ga('set', 'dimension1', user_type);
// user type - guest/readonly/habrauser
ga('set', 'dimension2', page_type);
ga('set', 'dimension3', 'na');
ga('set', 'dimension4', window.adb1);
ga('set', 'dimension6', 'ru');
ga('set', 'dimension7', 'B');
(function() {
var removeUtms = function(){
var location = window.location;
if (location.search.indexOf('utm_') != -1 && history.replaceState) {
var currentUrl = location.toString();
var strippedUrl = currentUrl.replace(/\?([^#]*)/, function(_, search) {
var result = search.split('&').map(function(param) {
if (/^utm_/.test(param)) {
return '';
}
return param;
}).filter(Boolean).join('&');
return result ? '?' + result : '';
});
history.replaceState({}, '', strippedUrl);
}
};
ga('require', 'GTM-559GVC8');
ga('send', 'pageview', { 'hitCallback': removeUtms
});
})();
ga('HGM.set', 'dimension1', user_type);
ga('HGM.set', 'dimension2', "habrahabr");
ga('HGM.set', 'dimension4', window.adb1);
ga('HGM.send', 'pageview');
}
if (window.habr_blockers_checker) {
window.habr_blockers_checker.detectWrapper(callGA);
} else {
callGA(false)
}
</script>