<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2695482042209092919</id><updated>2024-09-06T17:15:07.386-07:00</updated><category term="Become a Programmer"/><category term="self development"/><category term="JavaScript"/><category term="Стив Павлина"/><category term="настроение"/><category term="мотивация"/><category term="здоровье"/><category term="работа"/><category term="Java"/><category term="React"/><category term="time management"/><category term="утренние пробежки"/><category term="физкультура"/><category term="HTML/CSS"/><category term="как бросить курить"/><category term="переводы"/><category term="учеба"/><category term="git"/><category term="Heroku"/><category term="PHP"/><category term="jQuery"/><category term="Норбеков"/><category term="английский"/><category term="стереотипы"/><category term="Data Science"/><category term="Databases"/><category term="ExpressJS"/><category term="Python"/><category term="R"/><category term="WordPress"/><category term="initial post"/><category term="patterns"/><category term="медитация"/><title type='text'>My Own Self Development</title><subtitle type='html'>Впечатления и размышления о моих опытах в саморазвитии&lt;br&gt;Переводы некоторых соответствующих текстов</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>162</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-1053425619090198564</id><published>2022-02-11T01:36:00.005-08:00</published><updated>2022-02-11T01:37:44.793-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="self development"/><title type='text'>I am a software developer</title><content type='html'>&lt;p&gt;7 лет назал я защитил докторскую диссертацию по социологии, а год назад я вышел на работу как программист.&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEgc6FuepUdSmGV0uRcUHB8JaWPGDmQJl3ILb6AWzDFAjElVyP9SX9hGdJrOtxD3nhDv6DCQItskTl7f3tvbpys3WTXIVYFAchlM-ne5mYxfFRmpflnwMaQuDpriKczxsYK7j-8fOZQrg0KJbqJOAR2Vs8PP7TAY0hDaW6h6H6fSzKDcsVVPn4tfF_RRZw=s1334&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1334&quot; data-original-width=&quot;1334&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEgc6FuepUdSmGV0uRcUHB8JaWPGDmQJl3ILb6AWzDFAjElVyP9SX9hGdJrOtxD3nhDv6DCQItskTl7f3tvbpys3WTXIVYFAchlM-ne5mYxfFRmpflnwMaQuDpriKczxsYK7j-8fOZQrg0KJbqJOAR2Vs8PP7TAY0hDaW6h6H6fSzKDcsVVPn4tfF_RRZw=s320&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/1053425619090198564/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/1053425619090198564' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/1053425619090198564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/1053425619090198564'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2022/02/i-am-software-developer.html' title='I am a software developer'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/a/AVvXsEgc6FuepUdSmGV0uRcUHB8JaWPGDmQJl3ILb6AWzDFAjElVyP9SX9hGdJrOtxD3nhDv6DCQItskTl7f3tvbpys3WTXIVYFAchlM-ne5mYxfFRmpflnwMaQuDpriKczxsYK7j-8fOZQrg0KJbqJOAR2Vs8PP7TAY0hDaW6h6H6fSzKDcsVVPn4tfF_RRZw=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-6239899175671668505</id><published>2021-01-04T03:38:00.004-08:00</published><updated>2021-01-04T03:38:32.379-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="React"/><title type='text'> A programmer: JavaScript #29. Некоторые пробелы в образовании в React</title><content type='html'>&lt;p&gt;Когда я больше месяца назад взялся сделать тестовое заданиепо MERN, то по неопытности своей сказал, что сделаю меньше, чем за неделю. Не справился и за полторы, потому что постоянно вылазили какие-то не первый взгляд не слишком принципиальные пробелы в образовании, которые оказывались критическими в каждый данный момент времени. Разбираюсь с ними до сих пор, часто - с советами и помощью от добрых людей. Так, например, пагинацию (вывод данных постранично) делал больше недели, а затыков было несколько:&lt;/p&gt;&lt;p&gt;Во-первых, не знал, как передавать параметр в обработчик события. Во-вторых, делал setState асинхронным, хотя он предполагает колбек. В итоге посоветовали сделать так:&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;code&gt;setCurrentPage = p =&amp;gt; e =&amp;gt; this.setState({ currentPage: p }, this.registerHandler);&lt;/code&gt;&lt;/b&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Я такой записи не видел раньше, но пришлось вчитаться в документацию ещё раз (&lt;a href=&quot;https://learn-reactjs.ru/basics/handling-events&quot; target=&quot;_blank&quot;&gt;&lt;b&gt;тут&lt;/b&gt;&lt;/a&gt; и &lt;a href=&quot;https://reactjs.org/docs/react-component.html#setstate&quot; target=&quot;_blank&quot;&gt;&lt;b&gt;тут&lt;/b&gt;&lt;/a&gt;):&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;code&gt;&amp;lt;button onClick={(e) =&amp;gt; this.deleteRow(id, e)}&amp;gt;Delete Row&amp;lt;/button&amp;gt;&lt;br /&gt;&amp;lt;button onClick={this.deleteRow.bind(this, id)}&amp;gt;Delete Row&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/b&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;У меня:&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;code&gt;onClick={this.setCurrentPage(p)}&lt;/code&gt;&lt;/b&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Таки да - как видим, аргументом передается параметр, а setState колбеком вызывает то, что и нужно было выполнить после изменения state.&lt;/p&gt;&lt;p&gt;В-третьих, был затык с тем, что я сравнивал число со строкой, не замечая этого, и для того, чтобы всё работало, как надо, надо было делать приведение типов:&lt;/p&gt;&lt;b&gt;&lt;code&gt;&lt;p&gt;parseInt(this.state.currentPage) === p&lt;/p&gt;&lt;/code&gt;&lt;/b&gt;При этом это эквивалентно, если вместо parseInt просто поставить &quot;+&quot; - этого я точно нигде не встречал.&lt;p&gt;В четвертых, забыл, что в map() надо указывать уникальный ключ - поэтому при правильно работающем переключении страниц и запросах, отрисовывалось то же, что и было, потому что ключи не менялись.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Итого: Сейчас я писал через классы и без внешнего стейта, значит, надо переписать - 1) сделать внешний стейт, 2) классы заменить на функциональные компоненты и сделать всё через хуки, 3) разделить презентацию и бизнес-логику.&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/6239899175671668505/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/6239899175671668505' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/6239899175671668505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/6239899175671668505'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2021/01/a-programmer-javascript-29-react.html' title=' A programmer: JavaScript #29. Некоторые пробелы в образовании в React'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-6184829463891579138</id><published>2020-12-26T09:41:00.004-08:00</published><updated>2020-12-26T09:44:38.703-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="React"/><title type='text'> A programmer: JavaScript #28. Routing in React </title><content type='html'>&lt;p&gt;Некоторое время назад делал я тестовое задание по стеку &lt;b&gt;MERN (MongoDB, ExpressJS, React, NodeJS)&lt;/b&gt;. Сделать вовремя не сумел, но добрые люди согласились мне помочь доделать его - для себя, просто чтобы разобраться. Важный комментарий был мне дан по поводу того, что при маршрутизации моя программа перезагружает страницу, чего не должно быть, поскольку в этом случае теряется вся логика &lt;b&gt;Single Page Application&lt;/b&gt;, для чего, собственно, и разработан &lt;b&gt;React&lt;/b&gt;. Логика, напомню, состоит в том, что вместо загрузки необходимых страниц с сервера по каждому запросу, должно загружаться всё и сразу (кроме баз данных), и в зависимости от запроса - отрисовываться на клиенте то, что нужно, но без перезагрузки страницы. И понял я, что с маршрутизацией в React&#39;e мне, оказывается, ещё нужно разобраться получше.&lt;/p&gt;&lt;p&gt;Итак, для маршрутизации в React&#39;e существует модуль &lt;b&gt;react-router-dom&lt;/b&gt;, который предоставляет несколько ключевых инструментов:&lt;/p&gt;&lt;p&gt;&lt;b&gt;BrouserRouter&lt;/b&gt; (обычно импортируемый как просто &lt;b&gt;Router&lt;/b&gt;) - модуль, в котором, собственно, должна быть описана маршрутизация.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Router &lt;/b&gt;- в сущности, аналог &lt;b&gt;href &lt;/b&gt;- в нем прописывается путь, в зависимости от которого должно быть отрисовано нужное содержание.&lt;/p&gt;&lt;p&gt;Если кроме непосредственных ссылок надо обработать отсутствующую страницу, то Route&#39;ы надо обернуть в &lt;b&gt;Switch&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;Кроме того, можно использовать &lt;b&gt;Redirect&lt;/b&gt;, &lt;b&gt;Link &lt;/b&gt;и &lt;b&gt;NavLink&lt;/b&gt; (который отличается от Link тем, что в нем можно ещё и ссылаться не описание стилей для линков).&lt;/p&gt;&lt;p&gt;Так вот, в моем случае надо было использовать Link вместо Route - в этом случае страница не перезагружается, и маршрутизация осуществляется на клиенте, в противном случае идет запрос на сервер:&lt;/p&gt;&lt;b&gt;&lt;code&gt;&amp;lt;Link to=&quot;/&quot;&amp;gt;&amp;lt;button type=&quot;button&quot;&amp;gt;Home&amp;lt;/button&amp;gt;&amp;lt;/Link&amp;gt;&lt;/code&gt;&lt;/b&gt;&lt;p&gt;Информация взята &lt;a href=&quot;https://reactrouter.com/web/guides/primary-components&quot; target=&quot;_blank&quot;&gt;&lt;b&gt;отсюда&lt;/b&gt;&lt;/a&gt;, &lt;a href=&quot;https://reactgo.com/reactrouter/programaticallynavigation/&quot; target=&quot;_blank&quot;&gt;&lt;b&gt;отсюда &lt;/b&gt;&lt;/a&gt;и &lt;a href=&quot;https://www.youtube.com/watch?v=Wm62LRtxomk&quot; target=&quot;_blank&quot;&gt;&lt;b&gt;отсюда&lt;/b&gt;&lt;/a&gt;.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/6184829463891579138/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/6184829463891579138' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/6184829463891579138'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/6184829463891579138'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/12/a-programmer-javascript-28-routing-in.html' title=' A programmer: JavaScript #28. Routing in React '/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-6233800009408484010</id><published>2020-12-18T13:30:00.003-08:00</published><updated>2020-12-18T23:41:27.578-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="React"/><title type='text'>A programmer: JavaScript #27. Hooks in React</title><content type='html'>&lt;p&gt;Поскольку, грубо говоря, в JavaScript всё есть объект, то и компоненты React тоже вполне логично интерпретируются как объекты. А у объектов, как известно, есть состояние (state) и есть поведение. Состояние хранится в самом объекте, и его можно в нем же менять через this.setState. Но в последнее время разработчики React стараются отходить от такой практики и использовать компоненты как &quot;функциональные компоненты&quot;, или просто функции. А функции не имеют состояния (stateless). Но состояние - вещь необходимая, и возникшую проблему надо решать - для этого и придумали хуки (hooks). Хук - это функция, которая меняет состояние, которое хранится в локальной переменной.&lt;/p&gt;&lt;p&gt;Классический пример - использование хука useState для счетчика (сначала его
надо импортировать и библиотеки &#39;react&#39;):&lt;/p&gt;&lt;b&gt;&lt;code&gt;&lt;p&gt;const [count, setCount] = useState(0);&lt;/p&gt;&lt;/code&gt;&lt;/b&gt;&lt;p&gt;Здесь происходит &quot;деструктуризация массива&quot; - объявляются и переменная состояния (count), и собственно хук (setCount). То есть запись
эквивалентна следующей:&lt;/p&gt;&lt;b&gt;&lt;code&gt;&lt;p&gt;var countStateVariable = useState(0);&lt;/p&gt;&lt;p&gt;var count = countStateVariable[0]; // Объявление
переменной состояния&lt;/p&gt;&lt;p&gt;count = 0; // Присваивание начального значения&lt;/p&gt;&lt;p&gt;var setCount = сountStateVariable[1]; // Объявление хука&lt;/p&gt;&lt;/code&gt;&lt;/b&gt;&lt;p&gt;Теперь к ним можно обращаться в рендере:&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;code&gt;button onClick={() =&amp;gt; setCount(count + 1)}&lt;/code&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Другой классический пример – хук useEffect. Он определяет действия, которые должны быть выполнены после каждого рендера – то есть заменяет собой встроенные методы, которые связанны с жизненным циклом компонента (componentDidMount, componentDidUpdate и др.). Поскольку перерисовка компонента обычно связана с изменением состояния (за которое обычно отвечает useState), то часто оба эти хука используются вместе:&lt;/p&gt;&lt;b&gt;&lt;code&gt;&lt;p&gt;const [count, setCount] = useState(0);&lt;/p&gt;&lt;p&gt;useEffect(() =&amp;gt; { document.title = `Вы нажали ${count} раз` });&lt;/p&gt;&lt;/code&gt;&lt;/b&gt;&lt;p&gt;В данном случае document.title будет перерисовываться при каждом изменении состояния.&lt;/p&gt;&lt;p&gt;Существуют и другие хуки, а также можно написать собственные.&lt;/p&gt;&lt;p&gt;Информация взята &lt;a href=&quot;https://ru.reactjs.org/docs/hooks-intro.html&quot; target=&quot;_blank&quot;&gt;&lt;b&gt;отсюда&lt;/b&gt;&lt;/a&gt;, &lt;a href=&quot;https://www.youtube.com/watch?v=9KJxaFHotqI&amp;amp;t=1577s&quot; target=&quot;_blank&quot;&gt;&lt;b&gt;отсюда&lt;/b&gt;&lt;/a&gt;, &lt;a href=&quot;https://www.youtube.com/watch?v=P1Y8GFJa_Io&quot; target=&quot;_blank&quot;&gt;&lt;b&gt;отсюда&lt;/b&gt;&lt;/a&gt;.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/6233800009408484010/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/6233800009408484010' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/6233800009408484010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/6233800009408484010'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/12/a-programmer-javascript-27-hooks-in.html' title='A programmer: JavaScript #27. Hooks in React'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-2097297220584269679</id><published>2020-12-16T07:27:00.003-08:00</published><updated>2020-12-16T07:32:29.426-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="React"/><title type='text'>A programmer: JavaScript #26. A conditional statement in React</title><content type='html'>&lt;p&gt;Некоторое время назад мучился с небольшой проблемой: вроде бы программа работала правильно, но в консоли браузера откуда-то выскакивало сообщение &lt;b&gt;&quot;GET http://localhost:3000/undefined&quot;&lt;/b&gt;. Расследование показало, что это связано с тем, что я добавляю в базу данных объект без картинки, при этом у меня должен отрисовываться элемент, который имеет свойство&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;code&gt;backgroundImage: `url(${this.state.picture})`&lt;/code&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;То есть, когда картинки нет, он выбрасывает &lt;b&gt;undefined&lt;/b&gt;, что логично. Мне посоветовали написать так:&lt;/p&gt;&lt;b&gt;&lt;code&gt;&lt;p&gt;this.state.picture &amp;amp;&amp;amp; { backgroundImage: `url(${this.state.picture})` }&lt;br /&gt;&lt;/p&gt;&lt;/code&gt;&lt;/b&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&quot;Странная запись&quot; - подумал я, имея в виду оператор &quot;&lt;b&gt;И&lt;/b&gt;&quot;, и пошел разбираться. Оказалось, что всё логично: React читает эту строчку последовательно слева направо. Если картинка в &lt;b&gt;state &lt;/b&gt;есть, то он И отрисовывает её, а если её нет, то на операторе &quot;И&quot; прекращает читать строку, потому что вне зависимости от того, что дальше, значение будет &lt;b&gt;false&lt;/b&gt;, и до запроса на вывод картинки дело не доходит.&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/2097297220584269679/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/2097297220584269679' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/2097297220584269679'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/2097297220584269679'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/12/a-programmer-javascript-26-conditional.html' title='A programmer: JavaScript #26. A conditional statement in React'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-5088182338333014473</id><published>2020-12-15T02:01:00.004-08:00</published><updated>2020-12-15T02:05:30.517-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="ExpressJS"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><title type='text'>A programmer: JavaScript #25. Widdleware in ExpressJS</title><content type='html'>&lt;p&gt;Тема, которая почему-то вообще не попадалась мне на глаза раньше, но оказалась полезной и достаточно несложной. Напомню, что ExpressJS - это фреймворк для более простой работы с вебсервером. Грубо говоря, если в &quot;ванильном&quot; варианте надо было работать с XMLHttpRequest-объектом (XHR) NodeJS&#39;a, то в ExpressJS создается свой объект &lt;b&gt;app&lt;/b&gt;, через каторый и идет взаимодействие с сервером. Так вот, маршрутизация предполагает, что серверная часть имеет эндпойнты (например, &lt;b&gt;&quot;/api&quot;&lt;/b&gt;), при обращении к которым выполняются некоторые действия. Например:&lt;/p&gt;&lt;code&gt;&lt;p&gt;app.get(&quot;/api&quot;, (req, res) =&amp;gt; {&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // code&lt;br /&gt;&lt;/p&gt;&lt;p&gt;})&lt;br /&gt;&lt;/p&gt;&lt;/code&gt;&lt;p&gt;Так вот, существует возможность указать некоторые функции, которые должны быть выполнены ПЕРЕД выполнением данного года. Для этого определяется некоторая функция, кроме &lt;b&gt;req &lt;/b&gt;и &lt;b&gt;res&lt;/b&gt; она принимает параметр &lt;b&gt;next&lt;/b&gt;, который вызывается в конце этой функции, чтобы передать выполнение следующему middleware или собственно основному коду (если надо выдать ошибку, она передается как параметр внутри &lt;b&gt;next(error)&lt;/b&gt;, никакой другой параметр там передаваться не может). Например:&lt;br /&gt;&lt;/p&gt;&lt;code&gt;&lt;p&gt;const middleware = (req, res, next) =&amp;gt; {&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // code&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; next(); &lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;/code&gt;&lt;p&gt;Чтобы подключить middleware, надо указать:&lt;/p&gt;&lt;code&gt;&lt;p&gt;app.use(&quot;/api&quot;, middleware);&lt;br /&gt;&lt;/p&gt;&lt;/code&gt;&lt;p&gt;Если указать без указания на рут, middleware будет &quot;подключено&quot; глобально, то есть будет выполняться в любом руте:&lt;/p&gt;&lt;code&gt;&lt;p&gt;app.use(middleware);&lt;/p&gt;&lt;/code&gt;&lt;p&gt;Ну и, разумеется middleware, как и любой кусок кода можно импортировать извне, а внутри только подключать.&lt;/p&gt;&lt;p&gt;Информация взята &lt;a href=&quot;https://expressjs.com/en/guide/writing-middleware.html&quot; target=&quot;_blank&quot;&gt;&lt;b&gt;отсюда&lt;/b&gt;&lt;/a&gt;, &lt;a href=&quot;https://www.youtube.com/watch?v=lY6icfhap2o&quot; target=&quot;_blank&quot;&gt;&lt;b&gt;отсюда &lt;/b&gt;&lt;/a&gt;и &lt;a href=&quot;https://www.youtube.com/watch?v=AZDTM0DiLG8&quot; target=&quot;_blank&quot;&gt;&lt;b&gt;отсюда&lt;/b&gt;&lt;/a&gt;.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/5088182338333014473/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/5088182338333014473' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/5088182338333014473'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/5088182338333014473'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/12/a-programmer-javascript-25-widdleware.html' title='A programmer: JavaScript #25. Widdleware in ExpressJS'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-7233092726693907742</id><published>2020-11-24T11:26:00.005-08:00</published><updated>2020-11-25T00:24:06.603-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><title type='text'>A programmer: JavaScript #24. AJAX, XMLHttpRequest, fetch(), async/await</title><content type='html'>&lt;p&gt;Когда я первый раз узнал об AJAX-запросах, это было связано с необходимостью получать данные с сервера, не перезагружая страницу. И выглядело это приблизительно так:&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_1CF-58Pa6aSN-If60NxPA_NIk68rl3En_uRZpL2XMnG2VcOtUMMvCere72XGVMVVwWa8n6n_SIy6ncddSUV1S4Hq9KEo8Y0ggmCAEhG4hIsrTasnct_TtFhAJFE9zmdZHhZFRu_v4ASe/s922/code.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;586&quot; data-original-width=&quot;922&quot; height=&quot;254&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_1CF-58Pa6aSN-If60NxPA_NIk68rl3En_uRZpL2XMnG2VcOtUMMvCere72XGVMVVwWa8n6n_SIy6ncddSUV1S4Hq9KEo8Y0ggmCAEhG4hIsrTasnct_TtFhAJFE9zmdZHhZFRu_v4ASe/w400-h254/code.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;Что означало: при нажатии кнопки на клавиатуре в поле &quot;&lt;b&gt;login&lt;/b&gt;&quot;, взять данные и передать их методом POST в обработчик &lt;b&gt;ajax.php&lt;/b&gt; (название файла, разумеется, может быть любым - скрин с php-проекта), и в случае успешной отработки обработчика, вывести результат на страницу в элемент с названием &quot;&lt;b&gt;#login_warning&lt;/b&gt;&quot;.&lt;/p&gt;&lt;p&gt;И, собственно, вся асинхронность у меня стала после этого ассоциироваться с тем, что оказалось всего-лишь частью библиотеки jQuery. Но принципиально - это только частный случай &lt;span class=&quot;aCOpRe&quot;&gt;&lt;span&gt;&lt;b&gt;Asynchronous JavaScript And XML (AJAX)&lt;/b&gt;. О чем идет речь?&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span class=&quot;aCOpRe&quot;&gt;&lt;span&gt;Ранее я говорил, что&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;aCOpRe&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;promise&lt;/span&gt; &lt;/b&gt;- это способ справиться с асинхронностью - сделать так, чтобы команды выполнялись последовательно, поскольку часто бывает так, что для выполнения следующей функции нужен результат предыдущей, а в JavaScript это не гарантировано. Чаще всего это нужно при отправке http-запросов, когда данные должны быть выведены после получения ответа от сервера.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span class=&quot;aCOpRe&quot;&gt;&lt;span&gt;Без &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;aCOpRe&quot;&gt;&lt;span&gt;&lt;span&gt;promise&#39;&lt;/span&gt;ов это коротко выглядит так: создается специальный объект &lt;b&gt;XMLHttpRequest&lt;/b&gt;, не нем открывается соединение и посылается запрос. Заранее определяется, что должно выполниться при том или ином ответе сервера:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span class=&quot;aCOpRe&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwxPV0qcGC0hdx0em5F7BDt-1dVy79chj1j1h1zhoDhkbt0fHCCS-DvSdYnAwm0b7CW39k-Xpped_BrSCXDP5mml38xwFvDqZ0UskQ8EMqk6bWTFCWMyCdqGOgRizoF7zklH3wS97mZDWP/s922/code.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;548&quot; data-original-width=&quot;922&quot; height=&quot;238&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwxPV0qcGC0hdx0em5F7BDt-1dVy79chj1j1h1zhoDhkbt0fHCCS-DvSdYnAwm0b7CW39k-Xpped_BrSCXDP5mml38xwFvDqZ0UskQ8EMqk6bWTFCWMyCdqGOgRizoF7zklH3wS97mZDWP/w400-h238/code.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;fetch()&lt;/b&gt; - это интерфейс получения запросов - то есть способ сделать то же самое. &quot;Под капотом&quot; он создает объект request&#39;a, посылает его, но возвращает promise с обработкой response&#39;а:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgHqR-KZbe5gwnzcSVqQTVyKYBuLxgAEsT1i_CvZRnOri6rKOrtnbmtZF3vyVC_CelkE8G0Qs3YZ6d6dBuRzZRKNDhUsbKr4LLlNLDk_14fmIBTbOwncjZWdm_OcReahGiPEmkT7XFnI6z/s942/code.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;282&quot; data-original-width=&quot;942&quot; height=&quot;120&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgHqR-KZbe5gwnzcSVqQTVyKYBuLxgAEsT1i_CvZRnOri6rKOrtnbmtZF3vyVC_CelkE8G0Qs3YZ6d6dBuRzZRKNDhUsbKr4LLlNLDk_14fmIBTbOwncjZWdm_OcReahGiPEmkT7XFnI6z/w400-h120/code.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&amp;nbsp;&lt;p&gt;&lt;/p&gt;&lt;p&gt;На самом деле там вставляются ещё проверки, формат вывода данных, а в случае POST-запроса ещё и дополнительные параметры, но принцип таков.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;Ну и &lt;b&gt;async/await&lt;/b&gt; - это приблизительно то же самое. &lt;b&gt;async &lt;/b&gt;перед функцией указвает на то, что функция возвращает promise, соответственно, внутри функция будет ждать результата от promise&#39;a (в этом месте пишется &lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;await&lt;/b&gt;&lt;/span&gt;). Ну и поскольку promise может завершиться с ошибкой, то всё это оборачивается в try-catch:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAlTGCFfEXeZ5rHwPjhNMbRsrB-fAcT1CD8Rs-dYdBeXemV0vikRORKTOFC5oQFW5n629IijzXAwNC5Tk6qkiWVw3tAbCbl_GWs8NAdGqs-MuBjkiVe6ghj2ortyu1VAX8u34A_b4Ce1a9/s922/code.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;662&quot; data-original-width=&quot;922&quot; height=&quot;288&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAlTGCFfEXeZ5rHwPjhNMbRsrB-fAcT1CD8Rs-dYdBeXemV0vikRORKTOFC5oQFW5n629IijzXAwNC5Tk6qkiWVw3tAbCbl_GWs8NAdGqs-MuBjkiVe6ghj2ortyu1VAX8u34A_b4Ce1a9/w400-h288/code.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span class=&quot;aCOpRe&quot;&gt;&lt;span&gt;Информация - &lt;b&gt;&lt;a href=&quot;https://itgid.info/unit/javascript-2?unit=ajax-javascript&quot; target=&quot;_blank&quot;&gt;отсюда&lt;/a&gt;&lt;/b&gt;, &lt;b&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=eKCD9djJQKc&quot; target=&quot;_blank&quot;&gt;отсюда&lt;/a&gt;&lt;/b&gt;, &lt;b&gt;&lt;a href=&quot;https://learn.javascript.ru/async-await&quot; target=&quot;_blank&quot;&gt;отсюда&lt;/a&gt;&lt;/b&gt;, &lt;b&gt;&lt;a href=&quot;https://learn.javascript.ru/fetch&quot; target=&quot;_blank&quot;&gt;отсюда&lt;/a&gt;&lt;/b&gt;, &lt;b&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=eKCD9djJQKc&quot; target=&quot;_blank&quot;&gt;отсюда&lt;/a&gt;&lt;/b&gt;. На самом деле ещё много откуда, но это самые последние по времени использования ресурсы.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span class=&quot;aCOpRe&quot;&gt;&lt;span&gt;UPD:&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span class=&quot;aCOpRe&quot;&gt;&lt;span&gt;1. Нашел ещё один очень удобный ресурс - &lt;b&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=SF5yHkfiZkY&quot; target=&quot;_blank&quot;&gt;вот он&lt;/a&gt;&lt;/b&gt;. Здесь показаны разные варианты работы с асинхронными запросами в одном видео.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span class=&quot;aCOpRe&quot;&gt;&lt;span&gt;2. Про популярный нынче &lt;b&gt;axios &lt;/b&gt;ничего не писал, но там логика приблизительно такая же.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/7233092726693907742/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/7233092726693907742' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/7233092726693907742'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/7233092726693907742'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/11/a-programmer-javascript-24-ajax.html' title='A programmer: JavaScript #24. AJAX, XMLHttpRequest, fetch(), async/await'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_1CF-58Pa6aSN-If60NxPA_NIk68rl3En_uRZpL2XMnG2VcOtUMMvCere72XGVMVVwWa8n6n_SIy6ncddSUV1S4Hq9KEo8Y0ggmCAEhG4hIsrTasnct_TtFhAJFE9zmdZHhZFRu_v4ASe/s72-w400-h254-c/code.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-4609987628257843701</id><published>2020-11-19T12:04:00.009-08:00</published><updated>2020-11-19T13:35:24.729-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><title type='text'>A programmer: JavaScript #23. Prototype inheritance (Прототипное наследование)</title><content type='html'>&lt;p&gt;Если коротко, наследование - это способ получения полей и методов без того, чтобы явно декларировать их в самом объекте. Осуществляется это указанием, что данный объект является &quot;наследником&quot; какого-то другого объекта, а значит, он по умолчанию имеет те же поля и методы, что и &quot;родитель&quot;, плюс обычно добавляет какие-то собственные или переопределяет родительские. Это удобно.&lt;/p&gt;&lt;p&gt;В JavaScript используется &quot;прототипное наследование&quot;. Что это значит и в чем отличие от &quot;классического&quot; наследования. Под классическим наследованием я здесь буду понимать то, которое используется в Java. В классическом наследовании наследуются не объекты, а классы. А объект имеет те поля и методы, которые должны иметь объекты его класса (включая наследуемые от классов-родителей). Это создает структуру наследования, что имеет свои преимущества и недостатки.&lt;/p&gt;&lt;p&gt;Прототипное наследование отличается тем, что наследуются именно объекты и именно от объектов. То есть некоторый объект может объявить другой объект своим прототипом:&lt;/p&gt;&lt;p&gt;&lt;code&gt;var object = Object.create(prototypeObject);&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Здесь &lt;b&gt;object &lt;/b&gt;объявляет себя наследником объекта &lt;b&gt;prototypeObject&lt;/b&gt;, слеовательно, он имеет такие же, как у него поля и методы.&lt;/p&gt;&lt;p&gt;Собственно, можно наследовать не только объект от объекта, но и класс от класса - через конструкторы:&lt;/p&gt;&lt;p&gt;&lt;code&gt;ClassA.prototype = Object.create(ClassB.prototype);&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Только в этом случае сам конструктор тоже наследуется - и у &lt;b&gt;ClassA &lt;/b&gt;будет конструктор от &lt;b&gt;ClassB&lt;/b&gt;. Чтобы этого не происходило нужно отдельно его прописать (как бы &quot;вернуть&quot; себе обратно):&lt;/p&gt;&lt;p&gt;&lt;code&gt;ClassA.prototype.constructor = ClassA;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Технически это выглядит так, что любой объект имеет скрытое свойство &lt;b&gt;[[Prototype]]&lt;/b&gt;, которое можно явно задать (иначе оно равно null):&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;let object.__proto__ = prototypeObject;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;Здесь &lt;b&gt;__proto__&lt;/b&gt; - геттер/сеттер для &lt;b&gt;[[Prototype]]&lt;/b&gt;,в более поздних версиях языка он заменяется функциями &lt;b&gt;Object.getPrototypeOf&lt;/b&gt; и &lt;b&gt;, хотя &lt;b&gt;__proto__ &lt;/b&gt;тоже поддерживается.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Метод, которого нет в наследнике, но естьь в прототипе, может быть в переопределен в наследнике, но не в прототипе. Исключением являются вызываемые наследником геттеры и сеттеры, существующие в прототипе.&lt;/p&gt;&lt;p&gt;Важно отметить, что &lt;b&gt;this&lt;/b&gt; всегда указывает на сам объект, но не на его протоип. То есть прототип выступает для наследника как хранилище объектов. Поясняю:&lt;/p&gt;&lt;p&gt;Пусть в прототипе есть метод:&lt;/p&gt;&lt;p&gt;&lt;code&gt;setState() {&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.state = true; &lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;Если его вызвать на экземпляре наследника (&lt;b&gt;object.setState()&lt;/b&gt;), то &lt;b&gt;state = true&lt;/b&gt; будет присвоен наследнику, а не прототипу.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Информация взята &lt;b&gt;&lt;a href=&quot;https://learn.javascript.ru/prototype-inheritance&quot; target=&quot;_blank&quot;&gt;отсюда&lt;/a&gt;&lt;/b&gt;, &lt;a href=&quot;https://medium.com/devschacht/eric-elliott-common-misconceptions-about-inheritance-in-javascript-f6137fc3a45a&quot; target=&quot;_blank&quot;&gt;&lt;b&gt;отсюда&lt;/b&gt;&lt;/a&gt; и &lt;b&gt;&lt;a href=&quot;https://monsterlessons.com/project/lessons/prototipnoie-nasliedovaniie-v-javascript&quot; target=&quot;_blank&quot;&gt;отсюда&lt;/a&gt;&lt;/b&gt;.&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/4609987628257843701/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/4609987628257843701' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/4609987628257843701'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/4609987628257843701'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/11/a-programmer-javascript-23-prototype.html' title='A programmer: JavaScript #23. Prototype inheritance (Прототипное наследование)'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-3993676731324607040</id><published>2020-11-19T00:04:00.005-08:00</published><updated>2020-11-19T00:09:25.401-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><title type='text'>A programmer: JavaScript #22. Closures (Замыкания)</title><content type='html'>&lt;p&gt;Короткая и простая тема. Думал я поначалу. Есть, как минимум, два объяснения, что это такое.&lt;/p&gt;&lt;p&gt;Во-первых, замыкания - это, грубо говоря, способ создать приватное свойство. То есть есть свойство объявляется внутри функции, а сама функция его возвращает с помощию внутренней функции. Это означает, что свойство остается неизменным, кто бы ни вызывал функцию, потому что область его видимости остается внутри. Например, функция:&lt;/p&gt;&lt;code&gt;&lt;p&gt;function private() {&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; let a = 0;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return function() {&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return a;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;/p&gt;&lt;p&gt;};&lt;/p&gt;&lt;/code&gt;&lt;p&gt;В ней никто не имеет доступа к переменной &lt;b&gt;а&lt;/b&gt; извне, и потому не может её изменить.&lt;/p&gt;&lt;p&gt;Во-вторых, замыкания - это функция внутри функции. Основная польза от этого в том, что её можно присвоить какой-то переменной, а вызвать потом через эту переменную. Например, результатом присвоения
&lt;b&gt;
let variable = private();&lt;/b&gt;

будет &lt;b&gt;variable&lt;/b&gt;, которая при вызове &lt;b&gt;variable()&lt;/b&gt; будет возвращать &lt;b&gt;а&lt;/b&gt;.

Одним из самых распространенных применеий замыканий является счетчик:&lt;code&gt;&amp;nbsp;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;function private() {&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; let a = 0;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return function() {&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return a++;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;}&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;let counter = private();&amp;nbsp;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;тогда при каждом вызове &lt;b&gt;counter()&lt;/b&gt; будет возвращаться значение, на единицу большее, чем при предыдущем вызове функции.&lt;/p&gt;&lt;p&gt;Вот тут-то мне и стало непонятно: если функция отработала, то она должна была бы уничтожиться? Тогда в следующий раз заново бы создавалась и инициализировалась новая &lt;b&gt;let a = 0;&lt;/b&gt;? Тогда о каком счетчике может быть речь?&lt;/p&gt;&lt;p&gt;Ответ пришлось поискать, и вот он: объект существует пока существует ссылка на него. И здесь мы имеем, что да, функция &lt;b&gt;private()&lt;/b&gt; отработала, но внутренняя по отношению к ней функция продолжает существовать, поскольку в момент вызова &lt;b&gt;private()&lt;/b&gt; её присвоили другому объекту (где она может ожидать своего вызова). А значит, и &lt;b&gt;private()&lt;/b&gt; не уничтожена, а переменная изменила своё значение (в данном случае &lt;b&gt;а = а+1&lt;/b&gt;)!&lt;/p&gt;&lt;p&gt;Если детализировать, то:&lt;/p&gt;&lt;p&gt;1. При вызове функции создается лексическое окружение (этой функции) - &lt;b&gt;LexicalEnvironment&lt;/b&gt;, в котором, например, будут искаться переменные, если они не были найдены локально внутри. Грубо говоря, это внешняя область видимости по отношению к данной функции.&lt;/p&gt;&lt;p&gt;2. Также создании любая функции получает скрытое свойство &lt;b&gt;[[Environment]]&lt;/b&gt;, которое ссылается на её окружение (и тем самым как бы &quot;запоминает&quot; его).

Для внутренней функции окружением будет внешняя функция с теми значениями переменных, которые на данный момент в ней есть.&lt;/p&gt;&lt;p&gt;То есть в момент вызова &lt;b&gt;counter()&lt;/b&gt; значение переменной &lt;b&gt;а&lt;/b&gt; будет находится во внешней по отношению к ней &lt;b&gt;private()&lt;/b&gt;, и равняться это значение будет тому, которое существует на момент очередного вызова &lt;b&gt;counter()&lt;/b&gt;. Другими словами, каждый новый &lt;b&gt;counter()&lt;/b&gt; будет находить новую переменную &lt;b&gt;а&lt;/b&gt; в своем окружении (имеющую то значение, которое осталось в результате предыдущего вызова &lt;b&gt;counter()&lt;/b&gt;). Вот вам и счетчик.&lt;/p&gt;&lt;p&gt;Подробнее - &lt;b&gt;&lt;a href=&quot;https://learn.javascript.ru/closure&quot; target=&quot;_blank&quot;&gt;здесь&lt;/a&gt;&lt;/b&gt;. &lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/3993676731324607040/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/3993676731324607040' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/3993676731324607040'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/3993676731324607040'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/11/a-programmer-javascript-22-closures.html' title='A programmer: JavaScript #22. Closures (Замыкания)'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-6426004785944433716</id><published>2020-11-12T04:42:00.011-08:00</published><updated>2020-12-17T02:21:38.824-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><title type='text'> A programmer: JavaScript #21. Event loop + Promises </title><content type='html'>&lt;p&gt;JavaScript - однопоточный язык, то есть у него один стек, следовательно, только одна комманда может быть выполнена в единицу времени. Но если у тебя только один поток, как у JavaScript, это может привести к серьёзным задержкам. Проблема с однопоточностью решается &quot;асинхронностью&quot;. То есть&amp;nbsp;JavaScript  использует дополнительные ресурсы браузера или NodeJS или какого-либо другого окружения, кроме собственно основного движка, для того, чтобы иметь возможность что-то делегировать этим ресурсам и не ждать окончания одной операции, чтобы приступить к следующей.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Это реализуется через &quot;цикл событий&quot; (&lt;b&gt;&quot;event loop&quot;&lt;/b&gt;):&lt;/p&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Когда функция вызывается, она загружается в стек.&lt;/li&gt;&lt;li&gt;Но потом она начинает выполняться в &quot;дополнительных ресурсах&quot; пока не выполнится до конца.&lt;/li&gt;&lt;li&gt;Пока она выполняется &quot;в стороне&quot;, другие функции из стека могут быть в него загружены.&lt;/li&gt;&lt;li&gt;Когда функция выполнена, она возвращается сначала в &quot;очередь на возвращение&quot; (&lt;b&gt;&quot;task queue&quot;&lt;/b&gt;) и обратно в стек.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;b&gt;Event loop&lt;/b&gt;
 - потому что JavaScript циклом мечется между стеком, и 
&quot;очередью&quot;, проверяя, 1) пустой ли стек, и если стек пустой, то 2) есть ли в очереди то, что нужно возвращать. И если ещё 
нету, бежит дальше по кругу, если есть - помещает это (то, что первое в очереди) в стек.&lt;/p&gt;&lt;p&gt;И здесь есть большая проблема: часто мы не можем знать, в какой очередности будут выполняться функции. То есть что выполнится первым - то, что идет следующим в коде или то, что вернется из очереди?&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Так вот, чтобы избежать синхронности придумали колбеки (&lt;b&gt;&quot;callback&quot;&lt;/b&gt;). Колбек - это функция, которая передается в качестве параметра в другую функцию, если нужно, чтобы она была выполнена после той, в которую передана (или в нужном месте внутри). Например:&lt;/p&gt;&lt;code&gt;&lt;p&gt;function callback() {&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log(&#39;I am callback!&#39;);&lt;br /&gt;&lt;/p&gt;&lt;p&gt;};&lt;/p&gt;&lt;p&gt;let a = &#39;I am a parameter of anotherFunction!&#39;; &lt;br /&gt;&lt;/p&gt;&lt;p&gt;function anotherFunction(a, callback) {&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log(a);&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; callback();&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;/code&gt;&lt;p&gt;Тогда, если нам важна очередность выполнения, мы должны вкладывать колбек в колбек в колбек и т.д. В этом коде легко запутаться, особенно потому, что переданные функции могут быть описаны совершенно в другом месте, а здесь только вызваны - это называется &quot;ад колбеков&quot;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Чтобы его избежать, придумали (например) промисы (&lt;b&gt;&quot;promises&quot;&lt;/b&gt;).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Промис - это объект, который &quot;обещает&quot; выполнить то, что внутри. Он принимает функцию, которая имеет параметры resolve и reject, которые, соответственно, вызываются в случае успешного или неуспешного выполнения (вызываются с необходимыми параметрами). То есть, промис не только имеет возвращаемое значение той функции, которая выполнялась внутри него, но и состояние, успешно или нет прошло выполнение. И это состояние можно использовать - в случае неуспешного выполнения - ловить ошибку, добавив к промису через точку catch(...), а в случае успешного - вызывать следующую функцию, добавив к промису  через точку then(...). Ну и соответственно, можно промисы цеплять в цепочку один за одним, если принципиально последовательное выполнение определенных функций.&lt;/p&gt;&lt;p&gt;И поскольку я вчера тупил, и не смог написать промис на собеседовании, то вот пример:&lt;/p&gt;&lt;code&gt;&lt;p&gt;let promise = new Promise(function(resolve, request) {&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; let data = 5 + 3;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; resolve(data); &lt;br /&gt;&lt;/p&gt;&lt;p&gt;}).then(function(data) {&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; console log(data + 125);&lt;br /&gt;&lt;/p&gt;&lt;p&gt;});&lt;/code&gt;&lt;br /&gt;&lt;/p&gt;Как-то так.&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/6426004785944433716/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/6426004785944433716' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/6426004785944433716'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/6426004785944433716'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/11/a-programmer-javascript-21-event-loop.html' title=' A programmer: JavaScript #21. Event loop + Promises '/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-3948588155633746241</id><published>2020-11-09T03:40:00.012-08:00</published><updated>2020-12-17T01:48:49.639-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="patterns"/><category scheme="http://www.blogger.com/atom/ns#" term="React"/><title type='text'>A programmer: JavaScript #20. Pattern &quot;Observer&quot;</title><content type='html'>&lt;p&gt;В общих чертах петтерн &quot;observer&quot; (обозреватель, наблюдатель) предполагает, что есть некий объект, который меняет своё состояние и оповещает об этом тех, кто подписан на уведомления (&lt;b&gt;subscribers&lt;/b&gt;). Применительно к React&#39;у это более, чем актуально, поскольку при изменении состояния (данных), компоненты должны перерисовываться, а значит, должны следить за изменениями сообветствующих данных.&lt;/p&gt;&lt;p&gt;При этом компоненты, которые себя перерисовывают, получают данные, зависят от них, но &lt;b&gt;state&lt;/b&gt;, который хранит состояние, не должен зависеть от них - то есть он не должен сам вызывать метод перерисовки, находящийся в компонентах. Тогда как компоненты узнают, что &lt;b&gt;state &lt;/b&gt;изменился?&lt;/p&gt;&lt;p&gt;А вот как:&amp;nbsp;&lt;/p&gt;&lt;p&gt;С одной стороны, файл, где происходит отрисовка компонентов (допустим, index.js) вызывает &lt;b&gt;rerender()&lt;/b&gt; и передает туда &lt;b&gt;state&lt;/b&gt;, который предварительно импортирует:&lt;/p&gt;&lt;span style=&quot;color: #073763;&quot;&gt;&lt;code&gt;&lt;p&gt;&lt;b&gt;rerender(state)&lt;/b&gt;;&lt;/p&gt;&lt;/code&gt;&lt;/span&gt;&lt;p&gt;То есть &lt;b&gt;index.js&lt;/b&gt; зависит от &lt;b&gt;state&lt;/b&gt;&#39;а, как и положено.&lt;/p&gt;&lt;p&gt;Но &lt;b&gt;index.js&lt;/b&gt; также вызывает метод &lt;b&gt;subscribe &lt;/b&gt;и передает туда вызов свой &lt;b&gt;rerender():&lt;/b&gt;&lt;/p&gt;&lt;b&gt;&lt;code&gt;&lt;p&gt;&lt;span style=&quot;color: #073763;&quot;&gt;subscribe(rerender);&lt;/span&gt;&lt;/p&gt;&lt;/code&gt;&lt;/b&gt;&lt;p&gt;Теперь &lt;b&gt;rerender() &lt;/b&gt;может быть вызван прямо в &lt;b&gt;state&lt;/b&gt;, при этом &lt;b&gt;state &lt;/b&gt;от него не зависит, а только использует реализацию.&lt;/p&gt;&lt;p&gt;С другой стороны, при изменении &lt;b&gt;state &lt;/b&gt;вызывает &lt;b&gt;callSubscriber()&lt;/b&gt;, но его реализацию он получает в распоряжение из метода &lt;b&gt;subscribe():&lt;/b&gt;&lt;/p&gt;&lt;span style=&quot;color: #073763;&quot;&gt;&lt;code&gt;&lt;p&gt;&lt;b&gt;// некоторые изменения данных&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;callSubscriber();&lt;/b&gt;&lt;/p&gt;&lt;/code&gt;&lt;/span&gt;&lt;p&gt;В самом &lt;b&gt;state &lt;/b&gt;он описывается приблизительно так:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;span style=&quot;color: #073763;&quot;&gt;&lt;code&gt;export const subscribe = (observer) =&amp;gt; {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; rerender = observer;&lt;br /&gt;}&lt;/code&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;То есть теперь &lt;b&gt;callSubscriber&lt;/b&gt;&lt;b&gt;(), &lt;/b&gt;вызываемый в state, - это тот самый &lt;b&gt;rerender()&lt;/b&gt;, который реализован в &lt;b&gt;index.js&lt;/b&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Следовательно, теперь при любом изменениии state, он вызывает метод перерисовки, который он получил через &lt;b&gt;subscribе&lt;/b&gt;. Это означает, что &lt;b&gt;state &lt;/b&gt;по-преженему не зависит от UI, потому что ему всё равно, как реализована перерисовка - он её только вызывает, но не импортирует.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;P.S.: Обычно паттерн &quot;observer&quot; объясняют на примере Java. В некотором смысле оно понятнее, потому что там есть интерфейсы как отдельные сущности. Но вот мне помогло &lt;a href=&quot;https://www.youtube.com/watch?v=iN6QXbHedQc&amp;amp;list=PLcvhF2Wqh7DNVy1OCUpG3i5lyxyBWhGZ8&amp;amp;index=36&quot; target=&quot;_blank&quot;&gt;объяснение в исполнении Димыча&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/3948588155633746241/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/3948588155633746241' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/3948588155633746241'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/3948588155633746241'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/11/a-programmer-javascript-20-pattern.html' title='A programmer: JavaScript #20. Pattern &quot;Observer&quot;'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-7510861918119508579</id><published>2020-11-08T12:38:00.008-08:00</published><updated>2020-11-08T22:44:27.628-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="React"/><title type='text'>A programmer: JavaScript #19 The logic of React. Part 1</title><content type='html'>&lt;p class=&quot;MsoNormal&quot; style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span&gt;Снова про &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;React&lt;/span&gt;&lt;span&gt;. На этот раз вдохновился довольно объёмным курсом от Димыча (IT-KAMASUTRA, &quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;a class=&quot;yt-simple-endpoint style-scope yt-formatted-string&quot; dir=&quot;auto&quot; href=&quot;https://www.youtube.com/watch?v=gb7gMluAeao&amp;amp;list=PLcvhF2Wqh7DNVy1OCUpG3i5lyxyBWhGZ8&quot; spellcheck=&quot;false&quot;&gt;Курс &quot;React JS - путь самурая 1.0&quot;, уроки, практика&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span&gt;&quot;) - он объясняет всё очень подробно и понятно, действительно большой молодец, рекомендую. &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot; style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;React&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span&gt;– библиотека для фронтенда, то есть для удобной отрисовки страницы, которая
должна быть видна в браузере. Собственно, пишу только об основных принципах и
ключевых особенностях.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style=&quot;margin-left: 40px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;

&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;p class=&quot;MsoListParagraphCxSpFirst&quot; style=&quot;margin-left: 40px; text-align: left; text-indent: -18pt;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span&gt;&lt;span&gt;1.&lt;span style=&quot;font-feature-settings: normal; font-kerning: auto; font-language-override: normal; font-size-adjust: none; font-stretch: normal; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;React
&lt;/span&gt;&lt;span&gt;используется&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;для&lt;/span&gt;&lt;span&gt; &lt;span lang=&quot;EN-US&quot;&gt;Single Page Application. &lt;/span&gt;&lt;/span&gt;&lt;span&gt;«Классический вариант» работы с сайтом предполагает,
что когда нужно показать что-то с данного сайта, браузер посылает запрос на
сервер, и сервер присылает новую страницу. В свою очередь логика &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Single&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Page&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Application&lt;/span&gt;&lt;span&gt; предполагает, что практически всё необходимое
загружается в браузер сразу, и при запросах на новый контент уже сам браузер
отрисовывает его, не обращаясь к серверу.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style=&quot;margin-left: 40px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;

&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;p class=&quot;MsoListParagraphCxSpMiddle&quot; style=&quot;margin-left: 40px; text-align: left; text-indent: -18pt;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span&gt;&lt;span&gt;2.&lt;span style=&quot;font-feature-settings: normal; font-kerning: auto; font-language-override: normal; font-size-adjust: none; font-stretch: normal; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Для этого
используется модульность и виртуальный &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;DOM&lt;/span&gt;&lt;span&gt;. Если
&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;DOM&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Document&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Object&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Model&lt;/span&gt;&lt;span&gt;) – это модель документа,
то виртуальный &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;DOM&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span&gt;– это копия этой модели в памяти &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;React&lt;/span&gt;&lt;span lang=&quot;UK&quot;&gt;’&lt;/span&gt;&lt;span&gt;а. В
соответствии с виртуальным &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;DOM&lt;/span&gt;&lt;span&gt;’ом &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;React&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span&gt;«собирает»
страницу из компонентов. Если нужно что-то перерисовать, он вносит необходимые
изменения а нужный компонент, &lt;i&gt;реагирует&lt;/i&gt;
на изменения – поэтому и «&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;React&lt;/span&gt;&lt;span&gt;». В каждом компоненте
есть метод &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;render&lt;/span&gt;&lt;span&gt;(), который, собственно, и отрисовывает его. Поэтому
не затрагиваются все остальные элементы страницы, что обеспечивает быструю работу.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style=&quot;margin-left: 40px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;

&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;p class=&quot;MsoListParagraphCxSpMiddle&quot; style=&quot;margin-left: 40px; text-align: left; text-indent: -18pt;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span&gt;&lt;span&gt;3.&lt;span style=&quot;font-feature-settings: normal; font-kerning: auto; font-language-override: normal; font-size-adjust: none; font-stretch: normal; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Сложность
состоит в том, что слои отображения (&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;User&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Interface&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;UI&lt;/span&gt;&lt;span&gt;) – то, чем и являются
компоненты) и бизнес-логика должны быть разделены. Изменения &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;view&lt;/span&gt;&lt;span&gt; предполагают операции с данными, но данные не должны храниться в самих
компонентах – компоненты должны использовать &lt;i&gt;только&lt;/i&gt; те данные, которые пришли из слоя бизнес-логики. Следовательно,
их надо как-то передавать из уровня бизнес-логики в &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;UI&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span&gt;и обратно.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style=&quot;margin-left: 40px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;

&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;p class=&quot;MsoListParagraphCxSpMiddle&quot; style=&quot;margin-left: 40px; text-align: left; text-indent: -18pt;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span&gt;&lt;span&gt;4.&lt;span style=&quot;font-feature-settings: normal; font-kerning: auto; font-language-override: normal; font-size-adjust: none; font-stretch: normal; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Из уровня бизнес-логики
в &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;UI&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span&gt;данные передаются через &lt;/span&gt;&lt;b&gt;&lt;span lang=&quot;EN-US&quot;&gt;props&lt;/span&gt;&lt;/b&gt;&lt;span&gt;’ы – атрибуты компонентов.
Они могут передаваться от родительских компонентов в наследников, в которых они
становятся элементами &lt;/span&gt;&lt;b&gt;&lt;span lang=&quot;EN-US&quot;&gt;state&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;/b&gt;&lt;span&gt;– состояния данного компонента.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style=&quot;margin-left: 40px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;

&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;p class=&quot;MsoListParagraphCxSpMiddle&quot; style=&quot;margin-left: 40px; text-align: left; text-indent: -18pt;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span&gt;&lt;span&gt;5.&lt;span style=&quot;font-feature-settings: normal; font-kerning: auto; font-language-override: normal; font-size-adjust: none; font-stretch: normal; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Нюанс состоит
в том, что если нужно передать &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;props&lt;/span&gt;&lt;span&gt;’ы на несколько уровней,
то и прописывать их нужно на каждом уровне, что неудобно. Чтобы этого не
делать, используют &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Context&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span&gt;– некоторое хранилище данных. Компонент, в котором он создаётся, помещается
в обёртку &lt;/span&gt;&lt;b&gt;&lt;span lang=&quot;EN-US&quot;&gt;Context&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Provider&lt;/span&gt;&lt;/b&gt;&lt;span&gt;, который и передаёт
необходимые &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;props&lt;/span&gt;&lt;span&gt;’ы, а остальные помещаются в обёртку &lt;/span&gt;&lt;b&gt;&lt;span lang=&quot;EN-US&quot;&gt;Context&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Consumer&lt;/span&gt;&lt;/b&gt;&lt;span&gt;. Что означает, что
они имеют доступ ко всем &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;props&lt;/span&gt;&lt;span&gt;’ам, которые предоставляет &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Context&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Provider&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style=&quot;margin-left: 40px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;

&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;p class=&quot;MsoListParagraphCxSpMiddle&quot; style=&quot;margin-left: 40px; text-align: left; text-indent: -18pt;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span&gt;&lt;span&gt;6.&lt;span style=&quot;font-feature-settings: normal; font-kerning: auto; font-language-override: normal; font-size-adjust: none; font-stretch: normal; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Для того,
чтобы передать некоторые данные из &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;UI&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span&gt;на уровень бизнес-логики, в тех же &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;props&lt;/span&gt;&lt;span&gt;’ах компонентам передаются и необходимые методы. Сами методы прописаны на
уровне бизнес-логики, но передаётся возможность их вызова.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style=&quot;margin-left: 40px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;

&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;p class=&quot;MsoListParagraphCxSpMiddle&quot; style=&quot;margin-left: 40px; text-align: left; text-indent: -18pt;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span&gt;&lt;span&gt;7.&lt;span style=&quot;font-feature-settings: normal; font-kerning: auto; font-language-override: normal; font-size-adjust: none; font-stretch: normal; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;На уровне бизнес-логики создают &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;store&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span&gt;–
хранилище данных (состояний компонентов). С помощью переданных им методов
компоненты передают туда данные. С помощью переданных компонентам &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;props&lt;/span&gt;&lt;span&gt;’ов компоненты перерисовывают себя – это постоянно работающий цикл. Такое «архитектурное
решение» называется &lt;/span&gt;&lt;span lang=&quot;UK&quot;&gt;Flux&lt;/span&gt;&lt;span&gt;. Для его реализации существуют «системы управления состоянием» («&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;state&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;management&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;system&lt;/span&gt;&lt;span&gt;»), наиболее известная из них – &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Redux&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style=&quot;margin-left: 40px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;

&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;p class=&quot;MsoListParagraphCxSpMiddle&quot; style=&quot;margin-left: 40px; text-align: left; text-indent: -18pt;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span&gt;&lt;span&gt;8.&lt;span style=&quot;font-feature-settings: normal; font-kerning: auto; font-language-override: normal; font-size-adjust: none; font-stretch: normal; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;В &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;React&lt;/span&gt;&lt;span&gt; возможет функциональный и объектно-ориентированный (ООП) подходы. В первом
случае оперируют функциями, во втором – классами. Классы могут содержать и
собственный &lt;/span&gt;&lt;b&gt;&lt;span lang=&quot;EN-US&quot;&gt;state&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;/b&gt;&lt;span&gt;– состояние, и собственные функции. Если объект вызывает собственный метод,
используется &lt;/span&gt;&lt;b&gt;&lt;span lang=&quot;EN-US&quot;&gt;this&lt;/span&gt;&lt;/b&gt;&lt;span&gt;. Но если мы передаем метод куда-либо, то контекст
выполнения меняется, тогда &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;this&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span&gt;будет указывать на другой объект. Чтобы не
происходило путаницы, метод привязывают к его контексту с помощью метода &lt;/span&gt;&lt;b&gt;&lt;span lang=&quot;EN-US&quot;&gt;bind()&lt;/span&gt;&lt;/b&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style=&quot;margin-left: 40px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;

&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;p class=&quot;MsoListParagraphCxSpLast&quot; style=&quot;margin-left: 40px; text-align: left; text-indent: -18pt;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span&gt;&lt;span&gt;9.&lt;span style=&quot;font-feature-settings: normal; font-kerning: auto; font-language-override: normal; font-size-adjust: none; font-stretch: normal; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;В &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Store&lt;/span&gt;&lt;span&gt; кроме данных содержатся методы для работы с данными. Обычно их выносят в
общий метод, называемый &lt;/span&gt;&lt;b&gt;&lt;span lang=&quot;EN-US&quot;&gt;dispatch&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;b&gt;()&lt;/b&gt;, и передают ему (кроме необходимых данных) объект
&lt;/span&gt;&lt;b&gt;&lt;span lang=&quot;EN-US&quot;&gt;action&lt;/span&gt;&lt;/b&gt;&lt;span&gt;, который имеет определенный тип. В зависимости от
типа &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;dispatch&lt;/span&gt;&lt;span&gt;() выполняет нужный функционал. Это сокращает
запись в компонентах (вместо того, чтобы прописывать разные отдельные методы).&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoListParagraphCxSpLast&quot; style=&quot;margin-left: 40px; text-align: left; text-indent: -18pt;&quot;&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span&gt;&amp;nbsp;Продолжение следует. &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;font-family: arial;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;

&lt;/span&gt;&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/7510861918119508579/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/7510861918119508579' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/7510861918119508579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/7510861918119508579'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/11/a-programmer-javascript-19-logic-of.html' title='A programmer: JavaScript #19 The logic of React. Part 1'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-6993271097301878946</id><published>2020-08-21T08:10:00.000-07:00</published><updated>2020-08-21T08:10:41.583-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="PHP"/><category scheme="http://www.blogger.com/atom/ns#" term="WordPress"/><title type='text'>A programmer: PHP #2 Странный WordPress</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Вопрос был вот в чем. Есть сайт на WordPress, точнее - интернет-магазин. Страница выводит товары с помощью цикла и функции &lt;span style=&quot;color: blue;&quot;&gt;&lt;b&gt;get_posts()&lt;/b&gt;&lt;span style=&quot;color: black;&quot;&gt;, и делает этот вывод для каждой категории товаров, чтобы можно было дальше взаимодействовать с ними уже на странице.&lt;/span&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAySWtFi9wTwtwjPlPlypzgOpC77qS7mnunRhTKOcVai7vF1bGU0uF-b-DqhaHAQmneKAq1NmHWm2uM7YS6uQD60z7m-gYv51NxNDE_JoaWyXkBSlhiP4ElrpYjNBj7XLMB88tdNcJPNAa/s1600/code.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1600&quot; data-original-width=&quot;1059&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAySWtFi9wTwtwjPlPlypzgOpC77qS7mnunRhTKOcVai7vF1bGU0uF-b-DqhaHAQmneKAq1NmHWm2uM7YS6uQD60z7m-gYv51NxNDE_JoaWyXkBSlhiP4ElrpYjNBj7XLMB88tdNcJPNAa/s640/code.png&quot; width=&quot;423&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Но в админке WordPress&#39;а категории товаров указаны нормальными человеческими словами, а тут, как мы видим, ID. Возникает вопрос, как соотнести названия категорий и их ID?&lt;br /&gt;
&lt;br /&gt;
Ответ оказался весьма интересным:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&quot;Как посмотреть ID категории?- Зайдите в Консоль-&amp;gt; Записи Рубрики, 
кликните на заданную рубрику и в адрресной строке после ID= будет номер 
категории&quot;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Огромное спасибо автору, а полный текст статьи &lt;a href=&quot;https://www.wptheme.us/2014/09/kak-vyvesti-zapisi-opredelennoj-kategorii-v-wordpress/&quot; target=&quot;_blank&quot;&gt;здесь&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/6993271097301878946/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/6993271097301878946' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/6993271097301878946'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/6993271097301878946'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/08/a-programmer-php-2-wordpress.html' title='A programmer: PHP #2 Странный WordPress'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAySWtFi9wTwtwjPlPlypzgOpC77qS7mnunRhTKOcVai7vF1bGU0uF-b-DqhaHAQmneKAq1NmHWm2uM7YS6uQD60z7m-gYv51NxNDE_JoaWyXkBSlhiP4ElrpYjNBj7XLMB88tdNcJPNAa/s72-c/code.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-4239327730842038390</id><published>2020-08-03T10:28:00.002-07:00</published><updated>2020-08-03T10:28:17.976-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="git"/><category scheme="http://www.blogger.com/atom/ns#" term="Heroku"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="React"/><title type='text'>A programmer: JavaScript #18 Heroku</title><content type='html'>&lt;div&gt;Пару слов об опыте решения проблемы, которая, в общем, оказалась проблемой невнимательности (как часто бывает). Дело в том, что запушенное мной на Heroku приложение, написанное на React&#39;e, не запускалось. Смотрел логи, гуглил ошибки и прочее - непонятно. В итоге оказалось, что не подумал о двух вещах. Во-первых, для запуска вебприложения нужен вебсервер! Вот ведь новость какая :) Написал, добавил в проект. Во-вторых (и это было неочевидно), его нужно было явно прописать в Procfile&#39;e. Значит, надо его создать в нем написать (в моем случае):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt; &lt;b&gt;&lt;span style=&quot;color: #073763;&quot;&gt;web: node server.js&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Где &lt;b&gt;&lt;span style=&quot;color: #073763;&quot;&gt;web&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #073763;&quot;&gt;&lt;span style=&quot;color: black;&quot;&gt; - тип &lt;/span&gt;&lt;/span&gt;контейнера, &lt;b&gt;&lt;span style=&quot;color: #073763;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #073763;&quot;&gt;server.js &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;- название файла с сервером.&lt;b&gt;&lt;span style=&quot;color: #073763;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #073763;&quot;&gt; &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;И еще: чтобы не заморачиваться с отдельным гитом для Heroku, можно подключить собственный гитха, с которого он будет брать код, а потом либо вручную либо автоматически деплоить его. В документации это всё есть.&lt;/div&gt;&lt;div&gt;&lt;br /&gt; &lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span style=&quot;color: #073763;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #073763;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/4239327730842038390/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/4239327730842038390' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/4239327730842038390'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/4239327730842038390'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/08/a-programmer-javascript-18-heroku.html' title='A programmer: JavaScript #18 Heroku'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-4858667512567921669</id><published>2020-07-09T09:03:00.000-07:00</published><updated>2020-08-03T10:28:39.830-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="Heroku"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="React"/><title type='text'>A programmer: JavaScript #17 React + Heroku</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Хочется похвастаться. Я искал бесплатный или недорогой сервер, на котором можно было бы запускать Node.js и на нем всё остальное. Давно слышал про Heroku, но только сегодня руки дошли разобраться - создал один тестовый проект прямо там и второй просто туда задеплоил, оба на React&#39;е. Собственно, пересказывать, как это делать, смысла не вижу, поскольку есть очень понятный мануал: &lt;a href=&quot;https://devcenter.heroku.com/articles/getting-started-with-nodejs&quot;&gt;https://devcenter.heroku.com/articles/getting-started-with-nodejs&lt;/a&gt;. А ещё - отличное видео:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;iframe width=&quot;320&quot; height=&quot;266&quot; class=&quot;YOUTUBE-iframe-video&quot; data-thumbnail-src=&quot;https://i.ytimg.com/vi/vuVs7MypC8Y/0.jpg&quot; src=&quot;https://www.youtube.com/embed/vuVs7MypC8Y?feature=player_embedded&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/4858667512567921669/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/4858667512567921669' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/4858667512567921669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/4858667512567921669'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/07/a-programmer-javascript-17-react-heroku.html' title='A programmer: JavaScript #17 React + Heroku'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img.youtube.com/vi/vuVs7MypC8Y/default.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-5363801131091496567</id><published>2020-07-07T09:59:00.000-07:00</published><updated>2020-07-07T10:00:04.135-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="React"/><title type='text'>A programmer: JavaScript #16 React (vs. Angular)</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Продолжаю метаться между JavaScript&#39;ом и Data Science. В первом случае интересны работающие программы, во втором - извлечение информации. Имея в виду лучшые возможности найти работу, JavaScript побеждает. Поэтому решил разобраться с React&#39;ом Angular&#39;ом. Сегодня про React.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHp8E-CF_GB_DuhbG9B6uJC2rfpjD6iaODpR83QqZ9o1lLYpahvWBLfALieoHCzx39YtP5J-wbxIbAR0dbgG0OMPAUYLDgpI6bR7kMJ8lWPT0qdx9ShNh_jXlrGZOmwLfiKy4zdbd8P0Ao/s1600/react.jpeg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;534&quot; data-original-width=&quot;1600&quot; height=&quot;212&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHp8E-CF_GB_DuhbG9B6uJC2rfpjD6iaODpR83QqZ9o1lLYpahvWBLfALieoHCzx39YtP5J-wbxIbAR0dbgG0OMPAUYLDgpI6bR7kMJ8lWPT0qdx9ShNh_jXlrGZOmwLfiKy4zdbd8P0Ao/s640/react.jpeg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Итак, React - это фреймворк для web development&#39;а. Ключевая особенность - модульность. То есть ты создаешь компоненты (куски твоего сайта) и вставляешь из в один общий элемент. Всё это с помощью JavaScript, разумеется:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&amp;nbsp;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEis3YVcPTJmUmDEW1tWY07YEMxMFgLvQBGBFYEBYid-MgKVHabZGQCkl21a3aGMn5SJJwz8ek6S34O1i-KCRPFiAH501pNnfS1lMU27rHqDle4OHXp7c5YtSSZ4cUr6v-gun9d9mxxYT6V4/s1600/code.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;662&quot; data-original-width=&quot;954&quot; height=&quot;222&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEis3YVcPTJmUmDEW1tWY07YEMxMFgLvQBGBFYEBYid-MgKVHabZGQCkl21a3aGMn5SJJwz8ek6S34O1i-KCRPFiAH501pNnfS1lMU27rHqDle4OHXp7c5YtSSZ4cUr6v-gun9d9mxxYT6V4/s320/code.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Здесь функция render получает параметры 1) что вставлять и 2) куда вставлять. Сами вставляемые компонеты структурно состоят из двух файлов, один из которых отрисовывает кусок страницы, а второй - стили к нему:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgticA7eBVkrGTBBCz6NdevMo6EI5k6-scmIEVLrGCXC4Olm7qGiu3iF9AjKXsBItRHVLXfs9zQTwvI8_Y3iB57MBW1v1OHeSqK966n4oGbcqXn2JB5okwD8BMz-PVlIskIJWStXWfqfaAV/s1600/code.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;624&quot; data-original-width=&quot;954&quot; height=&quot;209&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgticA7eBVkrGTBBCz6NdevMo6EI5k6-scmIEVLrGCXC4Olm7qGiu3iF9AjKXsBItRHVLXfs9zQTwvI8_Y3iB57MBW1v1OHeSqK966n4oGbcqXn2JB5okwD8BMz-PVlIskIJWStXWfqfaAV/s320/code.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
То же самое можно делать не через функции, а через классы. При отрисовке компонента на странице можно передавать специфические для него данные (props), которые передаются в конструктор как параметры. Значения внутри компонента (класса) называются state. По сути, это локальная пересенная (объект), для доступа к которому извне, соответственно, нужны сеттеры и геттеры. Ну и плюс особенности маршрутизации (свой js-пакет) и синтаксиса (jsx). В общем, мне понравилось - ничего сложного.&lt;br /&gt;
&lt;br /&gt;
В Angular, в свою очередь, тоже модульность, тоже особенности синтаксиса и маршрутизации, но:&lt;br /&gt;
&amp;nbsp;- очень большой фреймворк - занимает много места;&lt;br /&gt;
&amp;nbsp;- его надо отдельно запускать (кроме веб-сервера на node.js, например);&lt;br /&gt;
&amp;nbsp;- долго запускается;&lt;br /&gt;
&amp;nbsp;- очень зависит от настроек - и своих, и браузера (в этом месте у меня случился затык, поэтому дальше я пока не пошел).&lt;br /&gt;
&lt;br /&gt;
Пока что так.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/5363801131091496567/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/5363801131091496567' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/5363801131091496567'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/5363801131091496567'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/07/a-programmer-javascript-16-react-vs.html' title='A programmer: JavaScript #16 React (vs. Angular)'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHp8E-CF_GB_DuhbG9B6uJC2rfpjD6iaODpR83QqZ9o1lLYpahvWBLfALieoHCzx39YtP5J-wbxIbAR0dbgG0OMPAUYLDgpI6bR7kMJ8lWPT0qdx9ShNh_jXlrGZOmwLfiKy4zdbd8P0Ao/s72-c/react.jpeg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-4494000300031658373</id><published>2020-06-02T07:35:00.001-07:00</published><updated>2020-06-02T07:41:23.577-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="Data Science"/><category scheme="http://www.blogger.com/atom/ns#" term="Databases"/><category scheme="http://www.blogger.com/atom/ns#" term="Python"/><category scheme="http://www.blogger.com/atom/ns#" term="R"/><title type='text'>Data Science mini-courses - Done</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Во время карантина прошел 6 миникурсов по Data Science на &lt;a href=&quot;http://datacamp.org/&quot;&gt;&lt;span dir=&quot;ltr&quot;&gt;&lt;span class=&quot;_3l3x&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;a data-lynx-mode=&quot;asynclazy&quot; data-lynx-uri=&quot;https://l.facebook.com/l.php?u=https%3A%2F%2Fwww.datacamp.com%2F%3Ffbclid%3DIwAR36ASsZAqljwxbXgQgAhjEID5QOLqfuCD5ZRVmm7U9-rokhpKbWzPQNBK4&amp;amp;h=AT0vKyUL4hNcjiandgAAa7YL6glmeHdxS_9W3dgo8NtAQPjjALAj79rrBO0U1r5pZphyLQJPhsMlxBWxNCEGKTgy5zQZu_qr36T4UkxGVGPZ01RH1hP4ynTXHzTIN6KVLuY&quot; href=&quot;https://www.datacamp.com/&quot; rel=&quot;nofollow noopener&quot; target=&quot;_blank&quot;&gt;http://www.datacamp.com/&lt;/a&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdk-KLvBLnNHai-JM9kiedo0K-TA4uDdnKQgZTFJ4JeOrlFC-azpkGZAZslTgSULzMES15Rjr1QDC3lT5a6MMLU2otRJPKJdWoyz5t4pp4REclROiwMyrLDlZKpaiRrX469UGDlIWGg_Hb/s1600/DatabaseDesign.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;572&quot; data-original-width=&quot;991&quot; height=&quot;184&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdk-KLvBLnNHai-JM9kiedo0K-TA4uDdnKQgZTFJ4JeOrlFC-azpkGZAZslTgSULzMES15Rjr1QDC3lT5a6MMLU2otRJPKJdWoyz5t4pp4REclROiwMyrLDlZKpaiRrX469UGDlIWGg_Hb/s320/DatabaseDesign.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSgbLtexIAuu1Oc8XYQZfq2LS8RypfHNJAaGN8X_6_LoRhNt2-ZsQnZrpqVFIm501H07GaveZjHtt_Qp8i_GfyLYXqlLUG5h1DJiO2-y53VeRgdF-XAGSh5JOenB7mZitPjbzJMwi-euuC/s1600/DataScience.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;552&quot; data-original-width=&quot;958&quot; height=&quot;184&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSgbLtexIAuu1Oc8XYQZfq2LS8RypfHNJAaGN8X_6_LoRhNt2-ZsQnZrpqVFIm501H07GaveZjHtt_Qp8i_GfyLYXqlLUG5h1DJiO2-y53VeRgdF-XAGSh5JOenB7mZitPjbzJMwi-euuC/s320/DataScience.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJ0UgQvYXoaLNE7WqDYA_nOBLuCGgpqNZybofBwprHZ2L2uAT_9MJLAKcDI3tkOtglpRnpTmzCDDo3Je5zt1ns1O2EDGtmcMriiTkgmOCV08yAhfZ0ymT7IYYj_rz3D9uTfjej_Drp8Kuc/s1600/IntermPython.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;609&quot; data-original-width=&quot;1059&quot; height=&quot;184&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJ0UgQvYXoaLNE7WqDYA_nOBLuCGgpqNZybofBwprHZ2L2uAT_9MJLAKcDI3tkOtglpRnpTmzCDDo3Je5zt1ns1O2EDGtmcMriiTkgmOCV08yAhfZ0ymT7IYYj_rz3D9uTfjej_Drp8Kuc/s320/IntermPython.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioR8-WH_mW5bzXRsmvneGKhcCnpGpqSurXTsEHMxmHh4hcIhuRvQa2OrIyGjNtgVN3ovjzqaMn8vuXrMYZ8O24WZA20ioKDNHfzLfFcsEFSUEr73GI7n_hLPKyooe6BkwT0VUf73TCa7yf/s1600/IntroDSPython.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;605&quot; data-original-width=&quot;1061&quot; height=&quot;182&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioR8-WH_mW5bzXRsmvneGKhcCnpGpqSurXTsEHMxmHh4hcIhuRvQa2OrIyGjNtgVN3ovjzqaMn8vuXrMYZ8O24WZA20ioKDNHfzLfFcsEFSUEr73GI7n_hLPKyooe6BkwT0VUf73TCa7yf/s320/IntroDSPython.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNxw4F2g8_BrawqFLkEPpLi5JNfCIB9YnIpQoYYZHJNwuKyOn7XZHsWHaiNsTMUYZprmIUSsloNKnNOIbMjj1ZsaYmzTVoh60MMgej26Jz2xP-EZIWTY-LEf42f0bvMC8zi3zaXShPHvhF/s1600/IntroPython.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;607&quot; data-original-width=&quot;1063&quot; height=&quot;182&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNxw4F2g8_BrawqFLkEPpLi5JNfCIB9YnIpQoYYZHJNwuKyOn7XZHsWHaiNsTMUYZprmIUSsloNKnNOIbMjj1ZsaYmzTVoh60MMgej26Jz2xP-EZIWTY-LEf42f0bvMC8zi3zaXShPHvhF/s320/IntroPython.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAgVryjIi2cxBiIwIuaWL4rMpnHEMzWUoutzi6odzc71Aom3VlFepaWvmkOiU5Ky9-blGNZUK-fhMgFuG5z8LueSTiEGXUBglWN38cANNWNkMW5SEjVqWNFgO6Nqc3e7Iac79eSEerPrae/s1600/IntroR.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;571&quot; data-original-width=&quot;995&quot; height=&quot;183&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAgVryjIi2cxBiIwIuaWL4rMpnHEMzWUoutzi6odzc71Aom3VlFepaWvmkOiU5Ky9-blGNZUK-fhMgFuG5z8LueSTiEGXUBglWN38cANNWNkMW5SEjVqWNFgO6Nqc3e7Iac79eSEerPrae/s320/IntroR.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/4494000300031658373/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/4494000300031658373' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/4494000300031658373'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/4494000300031658373'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/06/data-science-mini-courses-done.html' title='Data Science mini-courses - Done'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdk-KLvBLnNHai-JM9kiedo0K-TA4uDdnKQgZTFJ4JeOrlFC-azpkGZAZslTgSULzMES15Rjr1QDC3lT5a6MMLU2otRJPKJdWoyz5t4pp4REclROiwMyrLDlZKpaiRrX469UGDlIWGg_Hb/s72-c/DatabaseDesign.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-524483840251750665</id><published>2020-05-31T08:06:00.001-07:00</published><updated>2020-05-31T08:06:18.399-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><title type='text'>Facebook sharing problem solved</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Вчера столкнулся с проблемой: при расшаривании вебстраницы в Фейсбуке превьюшка отражала неправильную информацию. Мне посоветовали &lt;a href=&quot;https://developers.facebook.com/docs/sharing/webmasters/&quot; target=&quot;_blank&quot;&gt;A Guide to Sharing for Webmasters&lt;/a&gt;. И за это спасибо, потому что там есть информация о том, как сделать правильно. Если коротко, но надо прописать нужные &lt;b&gt;&lt;span style=&quot;color: blue;&quot;&gt;property &lt;/span&gt;&lt;/b&gt;в &lt;span style=&quot;color: blue;&quot;&gt;&lt;b&gt;meta&lt;/b&gt;&lt;/span&gt; в &lt;b&gt;&lt;span style=&quot;color: blue;&quot;&gt;head&lt;/span&gt;&lt;/b&gt; сайта, что я и сделал. Но! Ничего не менялось!&lt;br /&gt;
&lt;br /&gt;
Потому что фейсбуковский краулер, который индексирует страницы, посещает их раз в 30 дней. Но есть выход! На странице &lt;a href=&quot;https://developers.facebook.com/tools/debug/&quot; target=&quot;_blank&quot;&gt;Sharing Debugger&lt;/a&gt; вы не только можете посмотреть, какую информацию проиндексировал краулер, и как давно, но и нажать кнопочку &quot;Scrape again&quot; - и он проиндексирует вашу страницу прямо сейчас. Solved.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/524483840251750665/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/524483840251750665' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/524483840251750665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/524483840251750665'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/05/facebook-sharing-problem-solved.html' title='Facebook sharing problem solved'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-4840429135404966459</id><published>2020-04-20T08:17:00.001-07:00</published><updated>2020-04-20T08:18:11.423-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="time management"/><title type='text'>Карантин и интроверты</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Вообще-то карантин для меня обернулся, скорее, благом, чем злом по разным причинам (по крайней мере, пока). Среди прочего, потому, что я интроверт, и мне обычно не надо много общения - в большинстве случаев социальных сетей и мессенджеров мне вполне хватает. Плюс моя работа - это работа за компьютером, в основном. Но, как известно, работа дома оказывается сложной потому, что сложно переключаться в рабочее состояние. Так вот, на прошлой неделе я натолкнулся на интересное - один товарищ стримил свой рабочий процесс из дома. Не то, что именно он делал, а сам процесс сидения за компьютером, чего-то делания, слушания фоном музыки, периодических отлучек из-за стола и т.д. То есть того, что ты мог бы наблюдать, работая в офисе. Имея к тому же возможность этот виртуальный офис выключить в любой момент, такой стрим - идеальный способ войти в рабочее состояние: &quot;Вот он что-то делает, а я-то что тунеядствую?!&quot; Жаль, что зрителей было мало, и товарищ прекратил эту практику. Так кто же этот таинственный незнакомец? Рекомендую - youtube-канал &lt;a href=&quot;https://www.youtube.com/channel/UCeObZv89Stb2xLtjLJ0De3Q&quot; target=&quot;_blank&quot;&gt;АйТиБорода&lt;/a&gt;. Там периодически встречаются интересные интервью. Мне вот, например, понравилось:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;iframe allowfullscreen=&quot;&quot; class=&quot;YOUTUBE-iframe-video&quot; data-thumbnail-src=&quot;https://i.ytimg.com/vi/v0ttYrw3KjA/0.jpg&quot; frameborder=&quot;0&quot; height=&quot;266&quot; src=&quot;https://www.youtube.com/embed/v0ttYrw3KjA?feature=player_embedded&quot; width=&quot;320&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/4840429135404966459/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/4840429135404966459' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/4840429135404966459'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/4840429135404966459'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/04/blog-post.html' title='Карантин и интроверты'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img.youtube.com/vi/v0ttYrw3KjA/default.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-3083696623286364815</id><published>2020-03-25T03:58:00.001-07:00</published><updated>2020-04-20T07:59:35.942-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="git"/><title type='text'>Снова про git</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;br /&gt;
Когда-то я писал про основы git:&lt;a href=&quot;https://myownselfdevelopment.blogspot.com/2018/09/a-programmer-javascript-8.html&quot; target=&quot;_blank&quot;&gt; https://myownselfdevelopment.blogspot.com/2018/09/a-programmer-javascript-8.html&lt;/a&gt;. Есть необходимость кое-что добавить.&lt;br /&gt;
&lt;br /&gt;
Например, мне пришлось переключаться с githab&#39;a на gitlab. Это оказалось несколько нетривиальной задачей почему-то. В итоге оказалось, что надо просто переназначить url:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;color: blue;&quot;&gt;git remote set-url origin https://gitlab.com/oleksiy76/phpwebapp.git&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
А посмотреть, куда ты подключен можно так:&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;
&lt;span style=&quot;color: blue;&quot;&gt;&lt;b&gt;git remote -v&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
UPD: Ещё один неплохой курс про git:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;iframe allowfullscreen=&quot;&quot; class=&quot;YOUTUBE-iframe-video&quot; data-thumbnail-src=&quot;https://i.ytimg.com/vi/Fq9gDH_u2no/0.jpg&quot; frameborder=&quot;0&quot; height=&quot;266&quot; src=&quot;https://www.youtube.com/embed/Fq9gDH_u2no?feature=player_embedded&quot; width=&quot;320&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/3083696623286364815/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/3083696623286364815' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/3083696623286364815'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/3083696623286364815'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/03/git.html' title='Снова про git'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img.youtube.com/vi/Fq9gDH_u2no/default.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-1704224040484380715</id><published>2020-03-25T02:28:00.002-07:00</published><updated>2020-03-25T02:28:58.058-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="self development"/><category scheme="http://www.blogger.com/atom/ns#" term="time management"/><category scheme="http://www.blogger.com/atom/ns#" term="Стив Павлина"/><title type='text'>How to work from home</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
На самом деле это просто перепост видео:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;iframe width=&quot;320&quot; height=&quot;266&quot; class=&quot;YOUTUBE-iframe-video&quot; data-thumbnail-src=&quot;https://i.ytimg.com/vi/EhDYJUSYoXg/0.jpg&quot; src=&quot;https://www.youtube.com/embed/EhDYJUSYoXg?feature=player_embedded&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Эти советы очень часто повторяются, но к ним Стив Павлина, например, добавляет ещё один. Я сейчас быстро не нашел ссылку, где именно об этом говорит - можете поискать здесь: &lt;a href=&quot;https://www.stevepavlina.com/&quot;&gt;https://www.stevepavlina.com/&lt;/a&gt;. Совет такой: натренируйте себе &quot;bad eye&quot; - строгий взгляд, которым вы будете отпугивать домашних, когда они будут приходить отвлекать вас (а они будут).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/1704224040484380715/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/1704224040484380715' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/1704224040484380715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/1704224040484380715'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/03/how-to-work-from-home.html' title='How to work from home'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img.youtube.com/vi/EhDYJUSYoXg/default.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-4312239769582641211</id><published>2020-02-29T10:26:00.000-08:00</published><updated>2020-02-29T11:50:18.908-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="PHP"/><title type='text'>A programmer: PHP #1</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Проблема с тем, что бесплатный хостинг доступен почти исключительно на Apahe и заточен под PHP и MySQL, решилась тем, что пришлось разбираться с этим стеком.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGV7I8F8Me71t9Sa026gxJXWcl7X7U69LeNl33COdx_qHimqnuHxCzrqOy8fPLJS1qM14e_aJ9Vjly4ze5osLxtkAupQESYdamXWnsImuFQ3tSiOhjGzv-P9tdg8yEnbLGBajRk_pXRUN6/s1600/1280px-PHP-logo.svg.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;691&quot; data-original-width=&quot;1280&quot; height=&quot;172&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGV7I8F8Me71t9Sa026gxJXWcl7X7U69LeNl33COdx_qHimqnuHxCzrqOy8fPLJS1qM14e_aJ9Vjly4ze5osLxtkAupQESYdamXWnsImuFQ3tSiOhjGzv-P9tdg8yEnbLGBajRk_pXRUN6/s320/1280px-PHP-logo.svg.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Во-первых, учил PHP, точнее, переписывал свой сайт, где это было необходимо. Всё, на самом деле, довольно просто - прописываешь кусок кода прямо внутри вёрстки, что удобно, подключаешь куда надо другие файлы. Единственное, с чем бился долго - это проверка длины имени при вводе в форму, но только потому, что долго не мог правильно сформулировать запрос. Дело в том, что у меня уже было это реализовано на JavaScript&#39;e - жалко было отказываться, но никуда не денешься. Плюс хотелось, чтобы всё это проверялось без перезагрузки страницы. JavaScript&#39;овые варианты выходили как-то криво, плюс они ведь работают только на клиенте, а мне нужно было, чтобы была связь с сервером. Оказалось, нужны AJAX-запросы - разобрался с ними.&lt;br /&gt;
&lt;br /&gt;
Во-вторых, устанавливал локально всё - Apahe, PHP, MySQL и phpMyAdmin. С MySQL долго бился, потому что имя моего компьютера содержало кириллические буквы. А с phpMyAdmin - потому что настройки шифрования клиента (phpMyAdmin ) и сервера не совпадали (MySQL). Но в итоге всё получилось, и я доволен собой в конце концов.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/4312239769582641211/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/4312239769582641211' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/4312239769582641211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/4312239769582641211'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2020/02/a-programmer-php-1.html' title='A programmer: PHP #1'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGV7I8F8Me71t9Sa026gxJXWcl7X7U69LeNl33COdx_qHimqnuHxCzrqOy8fPLJS1qM14e_aJ9Vjly4ze5osLxtkAupQESYdamXWnsImuFQ3tSiOhjGzv-P9tdg8yEnbLGBajRk_pXRUN6/s72-c/1280px-PHP-logo.svg.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-7393129866796280899</id><published>2019-08-19T10:59:00.002-07:00</published><updated>2019-08-19T11:03:54.933-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="HTML/CSS"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="jQuery"/><title type='text'>A programmer: JavaScript #15</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Написал скрипт с для проверки длины имени и фамилии на стороне клиента. Файл &lt;b&gt;javascript &lt;/b&gt;с использованием &lt;b&gt;eventListener&lt;/b&gt;. Но получалось, что для двух разных полей (имени и фамилии) нужно писать два идентичных скрипта, что неправильно. Я решил заменить два скрипта на один, заменив, соответственно, &lt;b&gt;eventListener &lt;/b&gt;в скрипте на &lt;b&gt;onchange &lt;/b&gt;в тэге. Но получалась странная ситуация: судя по туториалам, надо или внешний скрипт подключать ко всей странице, или писать &lt;b&gt;onchang&lt;/b&gt;, но тогда скрипт надо писать в &lt;b&gt;html&lt;/b&gt;&#39;e. Или-или.&lt;/div&gt;
&lt;br /&gt;
&lt;span class=&quot;tL8wMe EMoHub&quot; dir=&quot;ltr&quot; id=&quot;:9a.co&quot; style=&quot;text-align: left;&quot;&gt;Посоветовали (дословно): &quot;&lt;/span&gt;&lt;span class=&quot;tL8wMe EMoHub&quot; dir=&quot;ltr&quot; id=&quot;:9a.co&quot; style=&quot;text-align: left;&quot;&gt;&lt;b&gt;&lt;span class=&quot;tL8wMe EMoHub&quot; dir=&quot;ltr&quot; id=&quot;:a2.co&quot; style=&quot;text-align: left;&quot;&gt;во внешнем файле функцию имей, файл подключи, а функцию эту вызывай&lt;/span&gt;&lt;/b&gt;&quot;. И вот получилось!&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;tL8wMe EMoHub&quot; dir=&quot;ltr&quot; id=&quot;:9a.co&quot; style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3OAgIAHmxHGJpGj-nwKDmFDiIGwLnY4eUBKFASmNdrJd0Qm0ixtYZV1E3nYCfrKoY-fV0IZ8Ib5_zVWUdCisxDrEUyuLbWMtPWi0FhtOISAQTU_aILq1Vp0whCQDqd_KnE6yQjaZXOr_J/s1600/validation.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;422&quot; data-original-width=&quot;601&quot; height=&quot;280&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3OAgIAHmxHGJpGj-nwKDmFDiIGwLnY4eUBKFASmNdrJd0Qm0ixtYZV1E3nYCfrKoY-fV0IZ8Ib5_zVWUdCisxDrEUyuLbWMtPWi0FhtOISAQTU_aILq1Vp0whCQDqd_KnE6yQjaZXOr_J/s400/validation.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;span class=&quot;tL8wMe EMoHub&quot; dir=&quot;ltr&quot; id=&quot;:9a.co&quot; style=&quot;text-align: left;&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;tL8wMe EMoHub&quot; dir=&quot;ltr&quot; id=&quot;:9a.co&quot; style=&quot;text-align: left;&quot;&gt;Разумеется, файл был подключен, &lt;/span&gt;&lt;span class=&quot;tL8wMe EMoHub&quot; dir=&quot;ltr&quot; id=&quot;:9a.co&quot; style=&quot;text-align: left;&quot;&gt;&lt;span class=&quot;tL8wMe EMoHub&quot; dir=&quot;ltr&quot; id=&quot;:an.co&quot; style=&quot;text-align: left;&quot;&gt;а в полях было указано:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;tL8wMe EMoHub&quot; dir=&quot;ltr&quot; id=&quot;:9a.co&quot; style=&quot;text-align: left;&quot;&gt;&lt;span class=&quot;tL8wMe EMoHub&quot; dir=&quot;ltr&quot; id=&quot;:an.co&quot; style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: blue;&quot;&gt;&lt;b&gt;onchange=&quot;listen(&#39;first_name&#39;)&quot;&lt;br /&gt;onchange=&quot;listen(&#39;last_name&#39;)&quot;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
День прожит не зря :)&lt;br /&gt;
&lt;span class=&quot;tL8wMe EMoHub&quot; dir=&quot;ltr&quot; id=&quot;:9a.co&quot; style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/7393129866796280899/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/7393129866796280899' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/7393129866796280899'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/7393129866796280899'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2019/08/a-programmer-javascript-15.html' title='A programmer: JavaScript #15'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3OAgIAHmxHGJpGj-nwKDmFDiIGwLnY4eUBKFASmNdrJd0Qm0ixtYZV1E3nYCfrKoY-fV0IZ8Ib5_zVWUdCisxDrEUyuLbWMtPWi0FhtOISAQTU_aILq1Vp0whCQDqd_KnE6yQjaZXOr_J/s72-c/validation.png" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-454877184278208181</id><published>2019-08-14T11:41:00.001-07:00</published><updated>2019-08-14T11:41:07.156-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><title type='text'>A programmer: JavaScript #14</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Хотел я, значит, запустить веб-сервер на NodeJS на удаленном сервере, чтобы протестировать одну штуку. Ну а там крутится Apache, разумеется. Сделать это (как выяснилось после долгих разбирательств) можно. Но если всякие разные настройки Апача для конкретный папок можно прописывать в файле .htaccess, то конкретно эти настройки нельзя - только в httpd.config, доступ к которому - только root. Следовательно, или обходиться апачем, или искать хостинг, который поддерживает Node JS, или покупать выделенный сервер, где сам себе root и делай, что хочешь.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/454877184278208181/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/454877184278208181' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/454877184278208181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/454877184278208181'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2019/08/a-programmer-javascript-14.html' title='A programmer: JavaScript #14'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2695482042209092919.post-4157291495218105062</id><published>2019-08-04T00:45:00.003-07:00</published><updated>2019-08-04T00:49:59.290-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Become a Programmer"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><title type='text'>A programmer: JavaScript #13</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;br /&gt;
Сегодня речь о нескольких нюансах, которые знатокам покажутся очевидными, но у меня вызвали затруднения в последние дни.&lt;br /&gt;
&lt;br /&gt;
1.&lt;br /&gt;
Когда мы экспортируем модуль, экспортируется не функция, а объект:&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;module.exports = { message: message }&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
то есть когда мы хотим вызвать функцию message из этого модуля, надо писать не &lt;span style=&quot;color: blue;&quot;&gt;message();,&lt;/span&gt; а &lt;span style=&quot;color: blue;&quot;&gt;message.message()&lt;/span&gt;;.&lt;br /&gt;
&lt;br /&gt;
Разумеется, предполагается, что модуль импортирован:&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;var message = require(&#39;./module.js&#39;);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
2.&lt;br /&gt;
В других языках ответ на этот вопрос находился быстро, а тут пришлось поискать, как сравнить два объекта (а не значения переменных). Ответ вот:&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;Object.is(value1, value2);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
3.&lt;br /&gt;
Ну и по мелочи - проверять все мелочи. Например, не путать атрибуты html-формы &lt;span style=&quot;color: blue;&quot;&gt;&quot;id&quot;&lt;/span&gt; и &lt;span style=&quot;color: blue;&quot;&gt;&quot;name&quot;&lt;/span&gt;. Или не забывать про &lt;span style=&quot;color: blue;&quot;&gt;urlencodedParser&lt;/span&gt;, когда пишешь обработчик для POST-метода (а то у меня был шок, когда &lt;span style=&quot;color: blue;&quot;&gt;body &lt;/span&gt;вообще не обнаруживалось). Или просто уточнять синтаксис.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://myownselfdevelopment.blogspot.com/feeds/4157291495218105062/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2695482042209092919/4157291495218105062' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/4157291495218105062'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2695482042209092919/posts/default/4157291495218105062'/><link rel='alternate' type='text/html' href='http://myownselfdevelopment.blogspot.com/2019/08/a-programmer-javascript-13.html' title='A programmer: JavaScript #13'/><author><name>Oleksiy Musiyezdov</name><uri>http://www.blogger.com/profile/08448866771044815897</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry></feed>