<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>NotionNext BLOG</title>
        <link>https://lolijk.org/</link>
        <description>这是一个由NotionNext生成的站点</description>
        <lastBuildDate>Sun, 28 Apr 2024 02:41:43 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en-US</language>
        <copyright>All rights reserved 2024, Asuhe</copyright>
        <item>
            <title><![CDATA[TypeScript进阶(一)]]></title>
            <link>https://lolijk.org/article/ff6f5aad-192a-4a05-986c-4ecd4d996d01</link>
            <guid>https://lolijk.org/article/ff6f5aad-192a-4a05-986c-4ecd4d996d01</guid>
            <pubDate>Tue, 23 Apr 2024 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-ff6f5aad192a4a05986c4ecd4d996d01"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-text notion-block-3c23391648f845ca80a1e44ae6b8ae6c">今天我们将要学习的是一些对type混合类型的常用运算函数。它们就是<b>Omit、Pick、Partial、Required。</b></div><div class="notion-text notion-block-fe40f5bf8cb04ab3a344fbb053df15a2"><b>需要注意的是这几个函数只能对type进行运算赋值，不能对interface进行运算赋值，但是可以用interface作为入参。</b>尽管interface和type很相近。</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-3a0c67a237e64f77ac47cf3e9fd198b7" data-id="3a0c67a237e64f77ac47cf3e9fd198b7"><span><div id="3a0c67a237e64f77ac47cf3e9fd198b7" class="notion-header-anchor"></div><a class="notion-hash-link" href="#3a0c67a237e64f77ac47cf3e9fd198b7" title="Omit"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Omit</span></span></h3><div class="notion-text notion-block-31ea80c9b39349c7a571f50405414483">Omit在英文里是省略的意思。有时候我们想要复制一个type，除去一些属性。遵循DRY原则，这时可以使用Omit函数快速帮助我们达到目的。若只想除去一个参数可以在Omit中直接传入该属性名，要除去多个则用｜符分割。</div><div class="notion-text notion-block-514a98f9cba14bcd83c26375b67bbaf7">首先先定义一个个人信息：</div><div class="notion-text notion-block-8a6caea9b62646d0b6052995446611af">现在我们想要忽略亲属信息</div><div class="notion-blank notion-block-d77bbf8607a8474fb3a36522ae42fd12"> </div><div class="notion-text notion-block-292c40b76334425aa0600bd65c350a3f">Omit源码</div><div class="notion-blank notion-block-06fff5ea61cb42b1aca94a6b2b943ef0"> </div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-22abde1b7cf546fd8f5690794a079a97" data-id="22abde1b7cf546fd8f5690794a079a97"><span><div id="22abde1b7cf546fd8f5690794a079a97" class="notion-header-anchor"></div><a class="notion-hash-link" href="#22abde1b7cf546fd8f5690794a079a97" title="Pick"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Pick</span></span></h3><div class="notion-text notion-block-a77aba1cbeec4da3a51eeea32dea97ff">Pick在英文里是选取的意思。有时候我们想要复制一个type，仅选取一些属性。此时我们可以使用Pick函数。</div><div class="notion-text notion-block-11673cb083044c19bc9a98ef9282b68f">比如我们想要定一个type，表明person的位置信息的type。</div><div class="notion-blank notion-block-85d6ea1d59254e1ab9452d3d51889d9a"> </div><div class="notion-text notion-block-dccef9aac64e4ebea931c07eca8bb5b7">Pick源码</div><div class="notion-blank notion-block-7bf47d2ee997478a85bca9caa3dbf570"> </div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-829e838f7114454aa7cd3ad61718719b" data-id="829e838f7114454aa7cd3ad61718719b"><span><div id="829e838f7114454aa7cd3ad61718719b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#829e838f7114454aa7cd3ad61718719b" title="Partial"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>Partial</b></span></span></h3><div class="notion-text notion-block-96a25af18f884997ab693758d8832a87">partial在英文中部分的意思。有时我们希望获取一个person类型里面所有属性都是可选的，但是上面的定义中，person类型所有属性都是必选的。使用partial可以达到我们的目的。</div><div class="notion-blank notion-block-1fe705bfd43f467ba26912d503863424"> </div><div class="notion-text notion-block-be1df8d658ac45b4a9df9a68afe0adc7">Partial源码</div><div class="notion-blank notion-block-8ef116f165384a6abb20ad3baceaeb7c"> </div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-8b2b9b38efe24249b077fbdb0fd145b7" data-id="8b2b9b38efe24249b077fbdb0fd145b7"><span><div id="8b2b9b38efe24249b077fbdb0fd145b7" class="notion-header-anchor"></div><a class="notion-hash-link" href="#8b2b9b38efe24249b077fbdb0fd145b7" title="Required"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>Required</b></span></span></h3><div class="notion-text notion-block-2f353847b7e04dfba6d15970d2dcaeb3">Required在英文里时必须的意思。它和partial操作相反，会将所有属性变为必选。</div><div class="notion-blank notion-block-9d8a3bd1f915414092a1d50a545a0c5d"> </div><div class="notion-text notion-block-ac34147d3cac48049f9d0a7e231d5005">Required源码</div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[SNI原理简介]]></title>
            <link>https://lolijk.org/article/86f2848e-7080-44ab-b399-3abef153b1bc</link>
            <guid>https://lolijk.org/article/86f2848e-7080-44ab-b399-3abef153b1bc</guid>
            <pubDate>Sat, 19 Aug 2023 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-86f2848e708044abb3993abef153b1bc"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-acb02b72e2a942668ce327632bfe75f9" data-id="acb02b72e2a942668ce327632bfe75f9"><span><div id="acb02b72e2a942668ce327632bfe75f9" class="notion-header-anchor"></div><a class="notion-hash-link" href="#acb02b72e2a942668ce327632bfe75f9" title="引言"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">引言</span></span></h3><div class="notion-text notion-block-16139fc0d0284e87a69c2334553c5b4c">众所周知P站主站是被屏蔽的，需要科学上网才能正常访问。前阵子发现有些P站第三方客户端可以做到直连P站，便心血来潮想要研究一下他们是如何实现的。同时也做一个可以直连P站的图片下载器。</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-7a7226d2c8c64267a03a0a39ee321cc8" data-id="7a7226d2c8c64267a03a0a39ee321cc8"><span><div id="7a7226d2c8c64267a03a0a39ee321cc8" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7a7226d2c8c64267a03a0a39ee321cc8" title="知己知彼"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">知己知彼</span></span></h3><div class="notion-text notion-block-073602cd7fe344119676e92b017e75eb">常言道知己知彼才能百战不殆。想要知道P站直连的原理就要先知道P站是如何被拦截的。通过查阅网上资料知道P站是被<code class="notion-inline-code">DNS污染</code> + <code class="notion-inline-code">SNI阻断</code>的方式被墙。接下来就可以从这两个方面入手。</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-dc1ea921d85444b8a7ea414c28d6ad26" data-id="dc1ea921d85444b8a7ea414c28d6ad26"><span><div id="dc1ea921d85444b8a7ea414c28d6ad26" class="notion-header-anchor"></div><a class="notion-hash-link" href="#dc1ea921d85444b8a7ea414c28d6ad26" title="DNS污染"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">DNS污染</span></span></h3><div class="notion-text notion-block-5121f6359bc742ae907701b23715694d">所谓<code class="notion-inline-code">DNS污染</code>就是污染你的DNS让你得到的DNS解析是一个错误的结果，令你最终的请求发送到一个不正确的IP以达到拦截的目的。当你想要请求某个网站时，通常会经过一下流程：</div><div class="notion-text notion-block-7040ddd7e114414491e53500e18a4b84">抓包实例：</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-55c56d1446784ce1b22e8d94a21f9f7f"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/blogImg%2FDNS%E8%BF%87%E7%A8%8B.png" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-890b732f19c8417ea1772e1ad5f0ff59"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img src="https://asuhe.fun/images/DNS%E8%BF%87%E7%A8%8B.png" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-e8c4997992174761b0d4a54559118117">DNS</div><div class="notion-text notion-block-a3cb4564a8d947c2aca34fee9b4714a3"><code class="notion-inline-code">DNS污染</code>就是在DNS服务器应答前，经过的中间路由检测到你发送的DNS请求是在GFW黑名单里的网站，中间路由器抢先给你返回一个DNS应答给你错误的IP地址。由于DNS协议设计之初没有身份鉴别机制且底层通常使用UDP协议是无连接的，它采用的策略是优先接收第一个DNS响应报文，后续到达的DNS响应报文将被丢弃，当上面的情况发生时，实际DNS服务器的报文会在后面到达，而它携带正确信息的DNS响应报文将会被你的主机丢弃。</div><div class="notion-text notion-block-3eb7d2dab6f94f1985808ef13157e52f">所以真实网络环境下的请求是下面的的流程，而不是上面的简化版。</div><div class="notion-text notion-block-a8ff316c5e2a40ff817097df1cc125df">明白了上面这个流程，就可以针对性地去解决了。</div><div class="notion-text notion-block-0405dd6c92e14bf5844ec09b72fd6de1">解决DNS污染问题可以采用下面几个方法：</div><ul class="notion-list notion-list-disc notion-block-bf9bead114eb4185b9399f3c0ba8ca09"><li>使用HTTPS。启用HTTPS后，浏览器与网站之间的通信是加密的，中间人无法读取和修改。这可以有效抵御DNS污染。</li></ul><ul class="notion-list notion-list-disc notion-block-6d38f9274a8f49729d20ffaad7c2744f"><li>使用DNS加密协议。如DNS over HTTPS、DNS over TLS等协议，可以加密DNS查询，避免DNS查询结果被劫持或污染。</li></ul><ul class="notion-list notion-list-disc notion-block-afab82d6d77742b6b16a1fb028fba2ce"><li>使用可信任的DNS服务器。选择知名的可信任DNS服务商,如Google DNS、OpenDNS等,而不使用可能被污染的本地ISP DNS。</li></ul><ul class="notion-list notion-list-disc notion-block-fa65a236baa548d19440cb82bb283a0f"><li>启用DNSSEC。DNSSEC通过数字签名防止DNS响应被修改,可以验证DNS数据的完整性和真实性。</li></ul><ul class="notion-list notion-list-disc notion-block-fa2fb324b1cb43509264411d80409134"><li>本地Hosts文件。在本地Hosts文件指定域名与IP地址映射,来绕过DNS查询。</li></ul><ul class="notion-list notion-list-disc notion-block-49b466797e144c0d874e4258883bcfd7"><li>智能选择DNS服务器。智能DNS系统可以检测异常情况,自动切换到其他正常DNS服务器。</li></ul><ul class="notion-list notion-list-disc notion-block-5f64c0c5c38f4e63868e41e1f550319d"><li>使用反向代理服务。通过中间代理服务来进行访问,避免直接暴露在污染的网络环境中。</li></ul><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-8ce1bd745eea4bd493a62c3629cbbd14" data-id="8ce1bd745eea4bd493a62c3629cbbd14"><span><div id="8ce1bd745eea4bd493a62c3629cbbd14" class="notion-header-anchor"></div><a class="notion-hash-link" href="#8ce1bd745eea4bd493a62c3629cbbd14" title="SNI阻断"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">SNI阻断</span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-c16a2e744eef40a6971ab6dfeffc96ec" data-id="c16a2e744eef40a6971ab6dfeffc96ec"><span><div id="c16a2e744eef40a6971ab6dfeffc96ec" class="notion-header-anchor"></div><a class="notion-hash-link" href="#c16a2e744eef40a6971ab6dfeffc96ec" title="什么是SNI"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">什么是SNI</span></span></h4><div class="notion-text notion-block-8b686ad05aef4ccab3891a9ab0893202"><code class="notion-inline-code">SNI</code>全称是<code class="notion-inline-code">Server Name Indication</code>，中文可以翻译为“服务器名称指示”。它是SSL/TLS协议的一个扩展，允许在建立安全连接时,客户端告诉服务器它正在访问的是哪个 hostname。</div><div class="notion-text notion-block-3ff01e7b865a4a65b163a7ca70182561">以前在一个IP地址上只能部署一个SSL证书，这样就无法在一台服务器上托管多个需要SSL证书的网站。</div><div class="notion-text notion-block-3555ae8a86194ad5b63fef9f1860f6a1">SNI的出现改变了这个限制。客户端在连接服务器时发送想要访问的hostname，这样服务器就可以根据不同的hostname选择正确的SSL证书来建立安全连接。</div><div class="notion-text notion-block-5507bb22312d4a81a004372ed1f701be">SNI扩展于2003年被提出，2005年正式成为SSL标准的一部分。SNI是在TLS 1.0版本中提出的扩展，但直到TLS 1.2版本才被正式采纳为标准。主流浏览器对SNI的支持也是从2010年开始。</div><div class="notion-text notion-block-e1f35e325c6a4f9d909e2db3d375f782">TLS 1.3版本对SNI做了优化，不再允许客户端<code class="notion-inline-code">Anonymous模式</code>，必须发送SNI来建立连接。所以综上，SNI主要是在TLS 1.2/1.3版本中使用，一般来说如果不发送SNI，服务器会根据配置返回默认证书。</div><div class="notion-text notion-block-d785a19403964bdab4d61f759774aacf">在TLS 1.3版本中,客户端必须发送SNI主要有以下两个原因:</div><ol start="1" class="notion-list notion-list-numbered notion-block-3f4f18394cd74f7494ce163188d78d88"><li>提高安全性</li></ol><div class="notion-text notion-block-50c20a17e7da4a28bad044306f49498b">早期的TLS版本允许客户端匿名连接服务器,这带来了一些安全隐患。不发送SNI,服务器无法验证客户端请求的域名,存在被攻击的风险。TLS 1.3去掉了这种客户端匿名模式,要求必须发送SNI,以提高安全性。服务器可以验证连接请求是否对应合法域名。</div><ol start="1" class="notion-list notion-list-numbered notion-block-061afd472a1c4a3fa909d82ded442237"><li>优化性能</li></ol><div class="notion-text notion-block-8b6f847bddec40c490174582f112daad">TLS 1.3改进了握手流程,服务器在收到SNI后,可以立即准备对应的证书,从而省去了额外的往返延迟。不发送SNI,服务器只能使用默认证书,需要重新协商一遍才能切换到正确的证书,降低了性能。</div><div class="notion-text notion-block-a29b3a48e5e8491bb36ebbf9b56293c7">综合考虑安全性和性能,TLS 1.3做出了需要强制SNI的设计。这尽量减少了匿名连接可能带来的风险,也优化了连接流程的效率。这项变化让SNI成为建立安全TLS连接的必备组件之一。</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-1eac24fd284e441f91975e98441a5bcd" data-id="1eac24fd284e441f91975e98441a5bcd"><span><div id="1eac24fd284e441f91975e98441a5bcd" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1eac24fd284e441f91975e98441a5bcd" title="具体细节"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">具体细节</span></span></h4><div class="notion-text notion-block-4f3b89f528a14c9797b2e5450dfa627a">SNI作为TLS扩展出现在<code class="notion-inline-code">ClientHello</code>消息中。<code class="notion-inline-code">ClientHello</code>是TLS握手过程的第一步,客户端首先发送这条消息给服务器。</div><ol start="1" class="notion-list notion-list-numbered notion-block-571cd2e635fb46a8a662af6e7b3adcf8"><li>在<code class="notion-inline-code">ClientHello消息</code>中,客户端可以发送一个<code class="notion-inline-code">Server Name Indication extension</code>(类型是0号扩展)。这个扩展包含了客户端请求访问的主机名。 <code class="notion-inline-code">Server Name</code>是可选的，如果客户端请求的是IP直接访问,就不需要带主机名。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-6a2ab66b9b6149a186397893d47f682d"><li>当服务器收到<code class="notion-inline-code">ClientHello</code>时，会检查是否有SNI扩展，如果有就取出<code class="notion-inline-code">Server Name</code>。服务器会根据这个<code class="notion-inline-code">Server Name</code>选择合适的证书去回复客户端。如果没有接收到SNI扩展,通常会返回默认证书。</li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-3d5fbac8f68748469da976781db75902"><li>之后就是标准的TLS握手流程，协商加密算法、交换证书等,来建立安全连接。如果握手成功,客户端就可以通过这个安全通道与服务器通信了。</li></ol><div class="notion-text notion-block-ccabeb9c4afc4946bcb711348b948488">其中第二步时，服务器会做出何种反应完全是由服务器配置规则决定的，通常都会采用以下几种策略：</div><ul class="notion-list notion-list-disc notion-block-d015f48343a545149c5d5818ae5b3238"><li>返回一个通配符证书，适用于服务器上的所有域名。</li></ul><ul class="notion-list notion-list-disc notion-block-b3f452cb9610466faef6d642c8bab417"><li>返回一个不存在的域名的证书，使客户端出现证书错误,强制要求使用SNI。</li></ul><ul class="notion-list notion-list-disc notion-block-e7b9f89a697b41179168365772def709"><li>返回一个第三方通用证书，如Let’s Encrypt的DST Root CA X3证书。</li></ul><ul class="notion-list notion-list-disc notion-block-3440ebf7c9994fc1aac65fcb216defbe"><li>甚至可以返回一个自签名证书作为默认证书。</li></ul><div class="notion-text notion-block-d7d4c1a3b8ad434ba41dd66f092860f7">我们可以抓包看看实际p站点的TLS流程，因为我这里没有清除电脑上原有的证书所以没有证书返回和密钥交换的过程。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-017057c0b6b342188c7e3cea5f429534"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/blogImg%2FSNI2.png" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-ec7db5abd01849f79b3e3fb03b98d224"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img src="https://asuhe.fun/images/SNI2.png" alt="notion image" loading="lazy" decoding="async"/></div></figure><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-452f7fbefb74418babe7d5033a2bd54d" data-id="452f7fbefb74418babe7d5033a2bd54d"><span><div id="452f7fbefb74418babe7d5033a2bd54d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#452f7fbefb74418babe7d5033a2bd54d" title="绕过思路"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">绕过思路</span></span></h4><div class="notion-text notion-block-aec9872cd38b4bd5af368d025e29cc1e">基于以上抓包信息，我们可以得到一个直接思路就是删除SNI扩展即直接不发送SNI，让服务器返回默认的证书供我们使用。恰巧P站返回的默认证书是<code class="notion-inline-code">*.pixiv.net</code>证书，一个泛解析的证书，这样我们就可以直接利用啦！</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-90a4a610a2d9491eb18830002f9c6afa" data-id="90a4a610a2d9491eb18830002f9c6afa"><span><div id="90a4a610a2d9491eb18830002f9c6afa" class="notion-header-anchor"></div><a class="notion-hash-link" href="#90a4a610a2d9491eb18830002f9c6afa" title="第三方客户端是怎么做的"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">第三方客户端是怎么做的</span></span></h3><div class="notion-text notion-block-fd51aca688ff48e5b0cc7080825f9360">以<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://github.com/Notsfsssf/pixez-flutter/tree/master">PixEz Flutter</a>这个客户端为例，它是支持直连P站的。而且他们的代码是开源的，我们可以随意查看。通过翻<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://github.com/Notsfsssf/pixez-flutter/blob/master/lib/er/hoster.dart">他们的代码</a>和问群里的大佬得知。</div><div class="notion-text notion-block-7c397e62ffec412a91d2e5f5d8596bf8">针对DNS污染问题，他们是用修改本地host的思路，用一些技术手段获取到了p站一个服务器的真实IP，然后直接向这个地址发请求从而绕过了DNS污染。而对于SNI阻断他们采用的方案是直接在请求过程中删除SNI，刚刚好P站采用的是TLS 1.2版本，这样就实现了直连P站。</div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[React基础(一)]]></title>
            <link>https://lolijk.org/article/753ee5c4-ff1e-4185-96ba-f70274a1fcdf</link>
            <guid>https://lolijk.org/article/753ee5c4-ff1e-4185-96ba-f70274a1fcdf</guid>
            <pubDate>Tue, 14 Jun 2022 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-753ee5c4ff1e418596baf70274a1fcdf"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-43ef59cb64ad4363a81dac71aee71c65" data-id="43ef59cb64ad4363a81dac71aee71c65"><span><div id="43ef59cb64ad4363a81dac71aee71c65" class="notion-header-anchor"></div><a class="notion-hash-link" href="#43ef59cb64ad4363a81dac71aee71c65" title="组件声明"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">组件声明</span></span></h2><div class="notion-text notion-block-902e064901c444ce8b7d80f2b8e7124a"><code class="notion-inline-code">React</code>中声明组件有两种方式，一是函数式组件，就是把一个函数作为组件的构造器；二是<code class="notion-inline-code">class</code>组件，即用<code class="notion-inline-code">ES6</code>的<code class="notion-inline-code">class</code>语法声明一个类作为组件的构造器。在<b>16.8版本</b>以前函数式组件不能使用组件的<code class="notion-inline-code">state</code>，<code class="notion-inline-code">refs</code>属性等诸多特性，这使得函数式组件只能用来定义一些简单组件，对于复杂一些的组件只能使用<code class="notion-inline-code">class</code>组件。而此版本以后<code class="notion-inline-code">React</code>加入了<code class="notion-inline-code">Hook</code>，使得函数式组件也能够使用组件的其它特性。<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://reactjs.org/docs/hooks-intro.html">官方文档</a></div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-b7758cf13ee34ac0957fd2828f69662b" data-id="b7758cf13ee34ac0957fd2828f69662b"><span><div id="b7758cf13ee34ac0957fd2828f69662b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#b7758cf13ee34ac0957fd2828f69662b" title="函数式组件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">函数式组件</span></span></h3><div class="notion-text notion-block-21ae3b894ab14f49a45f63a64ec582b6">函数式组件中我们只能用<code class="notion-inline-code">props</code>属性，定义一个函数式组件只需要创建一个开头为大写字母的函数，然后再将函数最后<code class="notion-inline-code">return</code>回一个<code class="notion-inline-code">jsx</code>标签即可。代码如下：</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-d74d2dbb62dc452593bc0ccdb221b2ac" data-id="d74d2dbb62dc452593bc0ccdb221b2ac"><span><div id="d74d2dbb62dc452593bc0ccdb221b2ac" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d74d2dbb62dc452593bc0ccdb221b2ac" title="class组件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">class组件</span></span></h3><div class="notion-text notion-block-b45a5091f3a34e3f80b53778b9617711"><code class="notion-inline-code">class</code>组件要比函数式组件强大的多，它可以完全使用组件三大属性：<code class="notion-inline-code">state</code>、<code class="notion-inline-code">props</code>、<code class="notion-inline-code">refs</code>。它还有生命周期函数可供使用，在生命周期函数中我们可以进行许多操作。但创建一个<code class="notion-inline-code">class</code>组件需要从<code class="notion-inline-code">React对象</code>中继承一个类<code class="notion-inline-code">React.Component</code>。代码如下：</div><div class="notion-text notion-block-3d14df088201458eb3dda7232b3e0b0e">当我们需要在<code class="notion-inline-code">class</code>组件上挂载事件处理函数时有两种方式，一是在<code class="notion-inline-code">constructor</code>中重写该事件处理函数，二是利用箭头函数和class语法声明函数。</div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-479b01be959c4d2ba09dceb7de2b10ad" data-id="479b01be959c4d2ba09dceb7de2b10ad"><span><div id="479b01be959c4d2ba09dceb7de2b10ad" class="notion-header-anchor"></div><a class="notion-hash-link" href="#479b01be959c4d2ba09dceb7de2b10ad" title="组件的三大属性"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">组件的三大属性</span></span></h2><div class="notion-text notion-block-490a2ba7dddf4feb80f4aa48693044bd">组件实例中有很多属性，但比较常用的就三个分别是：state、props、refs。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-614a48cd09bf407eb1eb2f8ccde03a66"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img src="C:/Users/12071/AppData/Roaming/Typora/typora-user-images/image-20220614101741901.png" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-704e105757c644d9824fb03356a16e44">image-20220614101741901</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-769f4b7c69a04b61ab0533be275a0ab9" data-id="769f4b7c69a04b61ab0533be275a0ab9"><span><div id="769f4b7c69a04b61ab0533be275a0ab9" class="notion-header-anchor"></div><a class="notion-hash-link" href="#769f4b7c69a04b61ab0533be275a0ab9" title="state"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">state</span></span></h3><div class="notion-text notion-block-cce9acf1c37a4826a119c97071d75335"><code class="notion-inline-code">state</code>属性是用来存储该组件实例的状态的。当我们使用<code class="notion-inline-code">this.setState</code>函数去修改<code class="notion-inline-code">state</code>时，页面会因为组件状态改变而同步改变。以上面的<code class="notion-inline-code">MyComponent</code>组件为例，我们可以给组件定义一个初始状态：</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-f7369f65561e48e3b307f296bcdf1363" data-id="f7369f65561e48e3b307f296bcdf1363"><span><div id="f7369f65561e48e3b307f296bcdf1363" class="notion-header-anchor"></div><a class="notion-hash-link" href="#f7369f65561e48e3b307f296bcdf1363" title="props"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">props</span></span></h3><div class="notion-text notion-block-781107b7cd8741f089df97137fe0da12"><code class="notion-inline-code">props</code>属性是用来接收外部传给组件的数据的，如果我们直接在标签上写数据，<code class="notion-inline-code">props</code>会自动接收该数据。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-d1847e9b8ec54a7faa9b2832971c6958"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/asuhe-blog-img/2024/04/44840d8849af3e7b793e947144f0f5cb.png" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-ff89ae0b673840249af4242e05f37a26"> </div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-0a9907c2c8fc4890bb1422f780985fbd" data-id="0a9907c2c8fc4890bb1422f780985fbd"><span><div id="0a9907c2c8fc4890bb1422f780985fbd" class="notion-header-anchor"></div><a class="notion-hash-link" href="#0a9907c2c8fc4890bb1422f780985fbd" title="限制props的数据类型"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">限制props的数据类型</span></span></h4><div class="notion-text notion-block-14971a4f21344ae18bfe777b8b793c4c">有时候我们希望限制传入数据的类型，此时我们需要额外加载一个<code class="notion-inline-code">prop-types.js</code>包，里面有<code class="notion-inline-code">PropTyps</code>对象以供我们使用。示例代码如下：</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-a91c20e26f6442dda91a92a2c84a2b1d" data-id="a91c20e26f6442dda91a92a2c84a2b1d"><span><div id="a91c20e26f6442dda91a92a2c84a2b1d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#a91c20e26f6442dda91a92a2c84a2b1d" title="refs"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">refs</span></span></h3><div class="notion-text notion-block-9e3a64e9d7594d70b384c52506dbf7b1">当我们需要获取标签or组件实例时，可以使用<code class="notion-inline-code">ref</code>标记。然后就可以在函数中利用<code class="notion-inline-code">this.refs</code>找到该组件or标签。<code class="notion-inline-code">ref</code>有三种形式分别是：字符串类型、回调函数类型和<code class="notion-inline-code">refs</code>对象类型。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-8f90e05f12104226a96e743c477ca08a" data-id="8f90e05f12104226a96e743c477ca08a"><span><div id="8f90e05f12104226a96e743c477ca08a" class="notion-header-anchor"></div><a class="notion-hash-link" href="#8f90e05f12104226a96e743c477ca08a" title="字符串类型的ref"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">字符串类型的ref</span></span></h4><div class="notion-text notion-block-0a3b7b843db4443f96d80b9ec338a2c3">字符串形式的ref 已经不推荐使用， ref会被自动收录进组件的refs里，如同props。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-92a0094882f84f55a54cbdda2d8d8248"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/asuhe-blog-img/2024/04/b160dc0fe2233eb7b3b93f7f0e27abd3.png" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-765092a22c8e447287dcb99351c97c04"> </div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-cb54b861993b4b62bd3009d189dadd24" data-id="cb54b861993b4b62bd3009d189dadd24"><span><div id="cb54b861993b4b62bd3009d189dadd24" class="notion-header-anchor"></div><a class="notion-hash-link" href="#cb54b861993b4b62bd3009d189dadd24" title="回调函数类型的ref"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">回调函数类型的ref</span></span></h4><div class="notion-text notion-block-80b8485b206b4905811bafe6151eb3c8">回调函数形式的ref 会将该标签DOM传给回调函数的形参，用this接住挂载在组件实例上。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-7162364f893b471dad3a23eda5b08ac4"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/asuhe-blog-img/2024/04/bb2d659a4492fb9c16690182aae9576a.png" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-a18bdaebea354a2f98e3ac689d39ce5c"> </div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-eef70059928a4688b09f52888ed9df85" data-id="eef70059928a4688b09f52888ed9df85"><span><div id="eef70059928a4688b09f52888ed9df85" class="notion-header-anchor"></div><a class="notion-hash-link" href="#eef70059928a4688b09f52888ed9df85" title="refs对象类型的ref"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">refs对象类型的ref</span></span></h4><div class="notion-text notion-block-0f794fd0271f490093fa3663184ffab1">使用自定义ref对象 ref对象内含{ current:被ref标记的标签实例 } 当多个标签使用同一个ref对象标记时，仅保留最后一个。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-cabf53bfeda44a9fa81c948e79cfdb56"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/asuhe-blog-img/2024/04/a89ef197f37448cd8034bfb0ecfd77dc.png" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-f6d7072cc5454b1dbe1843a1b92a940e"> </div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[React基础(二)]]></title>
            <link>https://lolijk.org/article/297e7e79-8301-4e03-bb68-734b0d880436</link>
            <guid>https://lolijk.org/article/297e7e79-8301-4e03-bb68-734b0d880436</guid>
            <pubDate>Mon, 20 Jun 2022 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-297e7e7983014e03bb68734b0d880436"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-e7f853357c6c4d13aaebf6ffc4dcf965" data-id="e7f853357c6c4d13aaebf6ffc4dcf965"><span><div id="e7f853357c6c4d13aaebf6ffc4dcf965" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e7f853357c6c4d13aaebf6ffc4dcf965" title="生命周期(旧)"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">生命周期(旧)</span></span></h2><div class="notion-text notion-block-646f1850db214c9d8ebb8ef3f5d4fddf"><code class="notion-inline-code">React</code>的生命周期可以为两条线，一是初始挂载阶段的生命周期，二是组件状态更新阶段的生命周期。在组件挂载阶段的生命周期只会触发一次，而组件状态更新阶段的生命周期可以多次触发。</div><div class="notion-text notion-block-ac0c34c003094861809f1133d015c2ad">在下图中，左边为挂载阶段的生命周期，右边为状态更新阶段的生命周期。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1aed0f6d6c8245aeb79f57af3e7e1a20"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/asuhe-blog-img/2024/04/2bef8adab67b899e5db5154aaf06d305.png" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-85f78220f7454f22b8901e049a7eec30"> </div><div class="notion-text notion-block-f85601d997b94a2fafb7e097f01eee24">特别说明<code class="notion-inline-code">componentWillRecevieProps</code>函数只有在父组件给子组件传递<code class="notion-inline-code">props</code>时才会被调用。而<code class="notion-inline-code">shouldComponentUpdate</code>则一定会被调用，若我们不自己指定则会默认<code class="notion-inline-code">return true</code>。</div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-79491a5f671d465196ca5dd4d895fc62" data-id="79491a5f671d465196ca5dd4d895fc62"><span><div id="79491a5f671d465196ca5dd4d895fc62" class="notion-header-anchor"></div><a class="notion-hash-link" href="#79491a5f671d465196ca5dd4d895fc62" title="生命周期(新)"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">生命周期(新)</span></span></h2><div class="notion-text notion-block-9a774bf0b5804dcf9c0e4578c61145bc">在<code class="notion-inline-code">React 16.3</code> 中引入了新的生命周期，在旧版生命周期中删除了<code class="notion-inline-code">componentWillReceiveProps</code>、<code class="notion-inline-code">componentWillMount</code>、<code class="notion-inline-code">componentWillUpdate</code>这三个生命周期。引入了两个新的生命周期<code class="notion-inline-code">getDerivedStateFromProps</code>和<code class="notion-inline-code">getSnapshotBeforeUpdate</code>。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-428f25e3bcf64de89eb07b0dff0abcb2"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/asuhe-blog-img/2024/04/4fef9a0865890d87261b6c5d3356fac3.png" alt="notion image" loading="lazy" decoding="async"/></div></figure></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[V8的GC机制]]></title>
            <link>https://lolijk.org/article/5640d174-d7c6-4658-b5a1-7158bb53f130</link>
            <guid>https://lolijk.org/article/5640d174-d7c6-4658-b5a1-7158bb53f130</guid>
            <pubDate>Thu, 01 Sep 2022 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-5640d174d7c64658b5a17158bb53f130"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-8441c88eb3be4ea7939eb45abafe3a21" data-id="8441c88eb3be4ea7939eb45abafe3a21"><span><div id="8441c88eb3be4ea7939eb45abafe3a21" class="notion-header-anchor"></div><a class="notion-hash-link" href="#8441c88eb3be4ea7939eb45abafe3a21" title="V8的GC机制"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">V8的GC机制</span></span></h2><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-1dd4597d64da442b9868b54817d6a0dd" data-id="1dd4597d64da442b9868b54817d6a0dd"><span><div id="1dd4597d64da442b9868b54817d6a0dd" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1dd4597d64da442b9868b54817d6a0dd" title="V8对JS使用内存的限制"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">V8对JS使用内存的限制</span></span></h3><div class="notion-text notion-block-a829b51709bc4e009517b24d8e942c1d">V8引擎在执行JS的过程中限制了JS可以使用内存的大小。通常在32位系统下，JS可以使用的内存大小约为0.7GB而64位系统下约为1.4GB。当我们一直申请内存，JS所使用内存超过这个限制时就会报错。造成这个问题的主要原因在于JavaScript对象基本上都是通过V8自己的方式来进行分配和管理的。</div><div class="notion-text notion-block-9366945961ab4ed18ca4c70b1d97c316"><b>在V8中，所有的JavaScript对象都是通过堆来进行分配的。</b> 当我们在代码中声明变量并赋值时，所使用对象的内存就分配在堆中。至于V8为何要限制堆的大小，表层原因为V8最初为浏览器而设计，不太可能遇到用大量内存的场景。对于网页来说，V8的限制值已经绰绰有余。</div><div class="notion-text notion-block-e47392d1e643468aaf5f4527913a66b4">深层原因是V8的垃圾回收机制的限制。<b>按官方的说法，以1.5 GB的垃圾回收堆内存为例，V8做一次小的垃圾回收需要50毫秒以上，做一次非增量式的垃圾回收甚至要1秒以上。这是垃圾回收中引起JavaScript线程暂停执行的时间，在这样的时间花销下，应用的性能和响应能力都会直线下降。 </b>这样的情况不仅仅后端服务无法接受，前端浏览器也无法接受。因此，在当时的考虑下直接限制堆内存大小是一个好的选择。</div><div class="notion-text notion-block-ddbe10bcd85348d5a1bea99679a9593c">当然，这个限制也不是不能打开，V8依然提供了选项让我们使用更多的内存。Node在启动时可以传递<code class="notion-inline-code">--max-old-space-size</code>或<code class="notion-inline-code">--max-new-space-size</code>来调整内存限制的大小，示例如下：</div><div class="notion-text notion-block-9c5c891d1b964a218fe9d50cfe5f24d3">如果遇到Node无法分配足够内存给JavaScript对象的情况，可以用这个办法来放宽V8默认的内存限制，避免在执行过程中稍微多用了一些内存就轻易崩溃。</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-aafa0ef082e445d4910a251f4b362b2b" data-id="aafa0ef082e445d4910a251f4b362b2b"><span><div id="aafa0ef082e445d4910a251f4b362b2b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#aafa0ef082e445d4910a251f4b362b2b" title="GC策略"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">GC策略</span></span></h3><div class="notion-text notion-block-e47e4b48eb8741e08fb12144affa4766"><b>V8的垃圾回收策略主要基于分代式垃圾回收机制。</b>在自动垃圾回收的演变过程中，人们发现没有一种垃圾回收算法能够胜任所有的场景。因为在实际的应用中，对象的生存周期长短不一，不同的算法只能针对特定情况具有最好的效果。为此，统计学在垃圾回收算法的发展中产生了较大的作用，现代的垃圾回收算法中按对象的存活时间将内存的垃圾回收进行不同的分代，然后分别对不同分代的内存施以更高效的算法。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-576952f2ca6649cda0a52f966470042f" data-id="576952f2ca6649cda0a52f966470042f"><span><div id="576952f2ca6649cda0a52f966470042f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#576952f2ca6649cda0a52f966470042f" title="分代式垃圾回收"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">分代式垃圾回收</span></span></h4><div class="notion-text notion-block-b16d45358c9f46ac83d8a6ad06e0e88d"><b>在V8中JavaScript对象被分为新生代和老生代。新生代通常是一些生命周期较短的对象，而老生代则通常是新生代经过一轮GC后仍然存活的对象晋升而来。</b></div><div class="notion-text notion-block-5276f11bdfd64dd7b0e9004dac4c1145">前面我们提及的<code class="notion-inline-code">--max-old-space-size</code>命令行参数可以用于设置老生代内存空间的最大值，<code class="notion-inline-code">--max-new-space-size</code>命令行参数则用于设置新生代内存空间的大小的。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-f67314c090ee4febb3dc5261efd119e2"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/blogImg%2F202211052310591.jpg" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-08f98ce913874f889134006de3cf193e"> </div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-100ba90b657c4fe9832e27569669bb27" data-id="100ba90b657c4fe9832e27569669bb27"><span><div id="100ba90b657c4fe9832e27569669bb27" class="notion-header-anchor"></div><a class="notion-hash-link" href="#100ba90b657c4fe9832e27569669bb27" title="新生代GC"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">新生代GC</span></span></h4><div class="notion-text notion-block-bc2310abd08a4bc598ff83875c106568"><b>在分代的基础上，V8新生代中的对象主要通过Scavenge算法进行垃圾回收。</b>在Scavenge的具体实现中，主要采用了Cheney算法，该算法由C. J. Cheney于1970年首次发表在ACM论文上。</div><div class="notion-text notion-block-7f31e51045ad46819fc2f9deda64c6e9">Scavange算法将新生代堆分为两部分，分别叫from-space和to-space，工作方式也很简单，就是将from-space中存活的活动对象复制到to-space中，并将这些对象的内存有序的排列起来，然后将from-space中的非活动对象的内存进行释放，完成之后，将from space 和to space进行互换，这样可以使得新生代中的这两块区域可以重复利用。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-a8fdcfff71364cdd9c89630ba944ce51"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/blogImg%2F202211052313142.jpg" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-43fadc0574344092a7256c9e8aee9af1"> </div><div class="notion-text notion-block-a6d4b093ca954894b2338e9fe08eb10e">Scavenge的缺点是只能使用堆内存中的一半，这是由划分空间和复制机制所决定的。但Scavenge由于只复制存活的对象，并且对于生命周期短的场景存活对象只占少部分，所以它在时间效率上有优异的表现。它是典型的以空间换时间的算法。</div><div class="notion-text notion-block-dd15bb85d80d44e9894c870477994d51">当一个对象经过多次复制依然存活时，它将会被认为是生命周期较长的对象。这种较长生命周期的对象随后会被移动到老生代中，采用新的算法进行管理。对象从新生代中移动到老生代中的过程称为晋升。</div><div class="notion-text notion-block-39df3aed4c7642b282f921dc3bcf683a">对象晋升的条件主要有两个，一个是对象是否经历过Scavenge回收，一个是To空间的内存占用比超过限制（25%）。</div><div class="notion-text notion-block-a227baae00f744918d9973ed117d5d28">在默认情况下，V8的对象分配主要集中在From空间中。对象从From空间复制到To空间时，会检查它的内存地址。以判断这个对象是否已经经历了一次Scavenge回收。若已经历过了，则将该对象晋升至老生代内存空间。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-15a0a41caf76491da6cea415abafd9db"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/asuhe-blog-img/2024/04/d30de0573fdc0cbd8dcc70023c30cba3.jpg" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-24b402fbf48b402dacc3d5d413ef452a"> </div><div class="notion-text notion-block-67f4c90e2b23457ba1f63ed7ed690d8e">设置25%这个限制值的原因是当这次Scavenge回收完成后，这个To空间将变成From空间，接下来的内存分配将在这个空间中进行。如果占比过高，会影响后续的内存分配。</div><div class="notion-text notion-block-60df537f6cf249d2b1d9a59f387a8217">对象晋升后，将会在老生代的内存空间中存活，由老生代的GC算法进行处理。</div><div class="notion-text notion-block-5c136b3b0a97408aa8cc503b6bc6261b">由于Scavenge是典型的牺牲空间换取时间的算法，所以无法大规模地应用到所有的垃圾回收中。但可以发现，Scavenge非常适合应用在新生代中，因为新生代中对象的生命周期较短，恰恰适合这个算法。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-84058f8a218d40b68b164ef9ac183ea3" data-id="84058f8a218d40b68b164ef9ac183ea3"><span><div id="84058f8a218d40b68b164ef9ac183ea3" class="notion-header-anchor"></div><a class="notion-hash-link" href="#84058f8a218d40b68b164ef9ac183ea3" title="老生代GC"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">老生代GC</span></span></h4><div class="notion-text notion-block-0283c98523d34e678b5d958cf672fb44">对象晋升后，将会在老生代空间中作为存活周期较长的对象来对待，接受新的回收算法处理。对于老生代中的对象，由于存活对象占较大比重，再采用Scavenge的方式会有两个问题：一个是存活对象较多，复制存活对象的效率将会很低；另一个问题依然是浪费一半空间的问题。这两个问题导致应对生命周期较长的对象时Scavenge会显得捉襟见肘。为此，<b>V8在老生代中主要采用了Mark-Sweep和Mark-Compact相结合的方式进行垃圾回收。</b></div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7a34ddd6dbda4a3fa5e8f27e79476989" data-id="7a34ddd6dbda4a3fa5e8f27e79476989"><span><div id="7a34ddd6dbda4a3fa5e8f27e79476989" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7a34ddd6dbda4a3fa5e8f27e79476989" title="Mark-Sweep"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Mark-Sweep</span></span></h4><div class="notion-text notion-block-0994556617994d9a93c8d699caf076c4">Mark-Sweep是标记清除的意思，它分为标记和清除两个阶段。与Scavenge复制活着的对象不同，Mark-Sweep在标记阶段遍历堆中的所有对象，并标记活着的对象，在随后的清除阶段中，只清除没有被标记的对象。可以看出，Scavenge中只复制活着的对象，而Mark-Sweep只清理死亡对象。活对象在新生代中只占较小部分，死对象在老生代中只占较小部分，这是两种回收方式能高效处理的原因。</div><div class="notion-text notion-block-e079fa5dc3f34c4d9b147a1d1afca891">Mark-Sweep算法最大的问题就是在进行一次标记清理回收后，会产生内存碎片，内存空间会出现不连续的状态。这种内存碎片会对后续内存分配造成影响。例如要分配一个100MB大小的对象，此时总体空闲的内存空间大小为150MB但是并没有一个连续的100MB大小的内存空间，这就会导致内存分配失败。这种情况会导致提前触发GC是程序停顿，而此次的GC是不必要的。为了解决Mark-Sweep的问题，所以Mark-Compact被提出。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-11547129c3df41c395a31b90b3582cbc" data-id="11547129c3df41c395a31b90b3582cbc"><span><div id="11547129c3df41c395a31b90b3582cbc" class="notion-header-anchor"></div><a class="notion-hash-link" href="#11547129c3df41c395a31b90b3582cbc" title="Mark-Compact"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Mark-Compact</span></span></h4><div class="notion-text notion-block-ccd61c0cbbd844189f329fa632a1de8d">Mark-Compact是标记整理的意思，是在Mark-Sweep的基础上演变而来的。它们的差别在于对象在标记为死亡后，在整理的过程中，将活着的对象往一端移动，移动完成后，直接清理掉边界外的内存。这样就可以减少内存碎片。总体上的思路就是将小碎片移动、合并成一个大块的内存空间。</div><div class="notion-text notion-block-44b3525dfdf148a1ac0606066a595794">这里将Mark-Sweep和Mark-Compact结合着介绍不仅仅是因为两种策略是递进关系，在V8的回收策略中两者是结合使用的。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-07489e9afc0d4333944700850e1c14fc" data-id="07489e9afc0d4333944700850e1c14fc"><span><div id="07489e9afc0d4333944700850e1c14fc" class="notion-header-anchor"></div><a class="notion-hash-link" href="#07489e9afc0d4333944700850e1c14fc" title="GC停顿处理"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">GC停顿处理</span></span></h4><div class="notion-text notion-block-bf996f302760408a941b74bd8caa2e73">为了避免出现JavaScript应用逻辑与垃圾回收器看到的不一致的情况，垃圾回收的3种基本算法都需要将应用逻辑暂停下来，待执行完垃圾回收后再恢复执行应用逻辑，这种行为被称为“全停顿”（stop-the-world）。</div><div class="notion-text notion-block-0a91e45375c1487d8b9fe42b87f8e92f">在V8的分代式垃圾回收中，一次小垃圾回收只收集新生代，由于新生代默认配置得较小，且其中存活对象通常较少，所以即便它是全停顿的影响也不大。但V8的老生代通常配置得较大，且存活对象较多，全堆垃圾回收（full垃圾回收）的标记、清理、整理等动作造成的停顿就会比较可怕，需要设法改善。</div><div class="notion-text notion-block-98191dbaa62c4c3d941d347fa1db5588">为了降低全堆垃圾回收带来的停顿时间，V8先从标记阶段入手，将原本要一口气停顿完成的动作改为增量标记（incremental marking），也就是拆分为许多小“步进”，每做完一“步进”就让JavaScript应用逻辑执行一小会儿，垃圾回收与应用逻辑交替执行直到标记阶段完成。</div><div class="notion-text notion-block-0f7962acef4a443aac82f50fd5168cd5">V8后续还引入了延迟清理（lazy sweeping）与增量式整理（incremental compaction），让清理与整理动作也变成增量式的。</div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Charles教程]]></title>
            <link>https://lolijk.org/article/b1ccc8ab-8c15-485e-9387-b0a89f21b522</link>
            <guid>https://lolijk.org/article/b1ccc8ab-8c15-485e-9387-b0a89f21b522</guid>
            <pubDate>Thu, 10 Nov 2022 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-b1ccc8ab8c15485e9387b0a89f21b522"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-text notion-block-498dca9719e840a084d2c31ea01eca60">因为工作上开发移动端的应用，而移动端并没有像Chrome那样好用的调试工具去查看网络请求的信息，所以需要利用抓包来进行网络请求的监控调试。在此介绍一些Charles抓包工具的基础使用，以作备份。</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-d4ed378ebbdc4b3686f984944e040fcb" data-id="d4ed378ebbdc4b3686f984944e040fcb"><span><div id="d4ed378ebbdc4b3686f984944e040fcb" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d4ed378ebbdc4b3686f984944e040fcb" title="基础抓包"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">基础抓包</span></span></h3><div class="notion-text notion-block-306abbbe1b2a4a9bbc9afcb87ef2e752">本文以抓ios手机上的流量为例。安卓手机的基本步骤也是同理。</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-b6a73c491432497eb8d65c54c1140d4e" data-id="b6a73c491432497eb8d65c54c1140d4e"><span><div id="b6a73c491432497eb8d65c54c1140d4e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#b6a73c491432497eb8d65c54c1140d4e" title="基本流程"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">基本流程</span></span></h4><div class="notion-text notion-block-1c8afe3eb1374577b6615f4afcb6e4f8">抓包基本流程：</div><ul class="notion-list notion-list-disc notion-block-bbc9aa13fac54c1686d6a8a5447b6221"><li>确保手机与抓包的电脑连接在同一局域网下</li></ul><ul class="notion-list notion-list-disc notion-block-815988603c7d4852866c7485321c9602"><li>抓包电脑开启http代理，并设置好本机的端口号</li></ul><ul class="notion-list notion-list-disc notion-block-f76e3c7d66364398b0c9acf633334d53"><li>手机设计好代理服务器为抓包电脑的ip和端口</li></ul><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-83e2c056c01c4248bd54717d2cd3def3" data-id="83e2c056c01c4248bd54717d2cd3def3"><span><div id="83e2c056c01c4248bd54717d2cd3def3" class="notion-header-anchor"></div><a class="notion-hash-link" href="#83e2c056c01c4248bd54717d2cd3def3" title="图例"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">图例</span></span></h4><ul class="notion-list notion-list-disc notion-block-cbb131a693234c6d9e2180639285a8c4"><li>设置电脑代理的端口，以<code class="notion-inline-code">192.168.6.238:8888</code>为例</li><ul class="notion-list notion-list-disc notion-block-cbb131a693234c6d9e2180639285a8c4"><li>打开Charles。</li><li>Proxy -&gt; Proxy Setting。设置端口号</li></ul></ul><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-da6eea9220b3426ea7a7b7c7e1383100"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/asuhe-blog-img/2024/04/5b04be7e3459d3465fdabb4917b9038d.png" alt="notion image" loading="lazy" decoding="async"/></div></figure><ul class="notion-list notion-list-disc notion-block-03c6f1dc380846b58835db6af43ae990"><li>手机设置代理服务器的地址与端口号</li><ul class="notion-list notion-list-disc notion-block-03c6f1dc380846b58835db6af43ae990"><li>找到代理服务器IP以及端口</li><li>设置代理</li></ul></ul><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-62bcfc6110e34f04a5aa7afb34ba693c"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/asuhe-blog-img/2024/04/0a4e2a2a5f2f8b8aeccc7e9e6b892e9b.png" alt="notion image" loading="lazy" decoding="async"/></div></figure><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-529981d437824361ac37593be37c686f" data-id="529981d437824361ac37593be37c686f"><span><div id="529981d437824361ac37593be37c686f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#529981d437824361ac37593be37c686f" title="Https抓包"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Https抓包</span></span></h3><ul class="notion-list notion-list-disc notion-block-47ef1d1bf90c44e09d65854eabfa0119"><li>根据提示在手机上安装好证书ssl</li></ul><ul class="notion-list notion-list-disc notion-block-f95ceba6c80746429a323ef7358ca971"><li>charles开启http抓包</li><ul class="notion-list notion-list-disc notion-block-f95ceba6c80746429a323ef7358ca971"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-db2c70ef5b1a442a96c99a0464ee24da"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/blogImg%2Fimage-20230115104052948.png" alt="notion image" loading="lazy" decoding="async"/></div></figure></ul></ul><div class="notion-blank notion-block-c4a05571ad6440c785cac1ef6b4edf5c"> </div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-c83087ee74a542c0a71fa05967d57409"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/blogImg%2Fimage-20230115104402665.png" alt="notion image" loading="lazy" decoding="async"/></div></figure><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-5c82b19b315f41f69ab689688116a328" data-id="5c82b19b315f41f69ab689688116a328"><span><div id="5c82b19b315f41f69ab689688116a328" class="notion-header-anchor"></div><a class="notion-hash-link" href="#5c82b19b315f41f69ab689688116a328" title="Mock数据"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Mock数据</span></span></h3><ul class="notion-list notion-list-disc notion-block-2d54689bc8af4c5e91cab50a440f5a3d"><li>选中要mock的接口右键</li></ul><ul class="notion-list notion-list-disc notion-block-ac5584af094e491d8059e25088c64504"><li>映射为本地接口或者远程接口</li></ul><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-92050dd7eec4437fa07b0c3db1d7f46c"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/blogImg%2Fimage-20230115104730170.png" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-d59e298b3205489bab4d40247cb9441e"> </div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-4061fa60dc0643ef944d93e587b6126b"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/blogImg%2Fimage-20230115105028625.png" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-aa5222c44cd7419cbb71ff6b9b7901ec"> </div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-5ba83ce1d5924f0aa2e5433d11bb6c3c"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/blogImg%2Fimage-20230115105358136.png" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-d99e72e085ff4d46b50b4ca2230f1a36"> </div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-5ea988dda4844af8a7b82c76abdbbe6f" data-id="5ea988dda4844af8a7b82c76abdbbe6f"><span><div id="5ea988dda4844af8a7b82c76abdbbe6f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#5ea988dda4844af8a7b82c76abdbbe6f" title="http拦截并修改后再发送数据"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">http拦截并修改后再发送数据</span></span></h3><ul class="notion-list notion-list-disc notion-block-1b7e045c49b34d80a2e1db834763ce3f"><li>选中要拦截的接口右键</li></ul><ul class="notion-list notion-list-disc notion-block-3ecbd5ea37d2407c9cc14c13316e5aa0"><li>设置断点</li></ul><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-ab1df3ecd3614f3da72f586041c5abd5"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/blogImg%2Fimage-20230115104852689.png" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-5dd575f8ebca40b3a57370f01d8e39ea"> </div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-b9c945384dc14f60a6a8d121a50a5990"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://img.outsider404.com/blogImg%2Fimage-20230115104934941.png" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-19453af1e25f46ffa5a4f97206e65eb2"> </div></main></div>]]></content:encoded>
        </item>
    </channel>
</rss>