ScarSu - 终身成长,前端技术,信息源96女性程序员,以终身成长为人生意义,热爱前端技术,喜欢读各种书,关注自我管理、心智成长、认知提升、极简生活。https://www.scarsu.com/View Transition API - 实现HTML视图的过渡动画https://www.scarsu.com/view_transition_api/https://www.scarsu.com/view_transition_api/无需使用CSS精确指定动效”元素“、实现MPA跳转页面动效Thu, 19 Sep 2024 00:00:00 GMT<h2>触发视图动效的方法&amp;时机:</h2> <ul> <li> <p>对于SPA,将更新DOM的方法<code>updateDomTrigger</code>作为参数传递给<a><code>document.startViewTransition(updateDomTrigger)</code></a>方法,浏览器会&lt;u&gt;先截取&lt;/u&gt;当前页面DOM元素的快照(声明了 <a><code>view-transition-name</code></a> CSS属性的DOM元素,默认是:root),&lt;u&gt;再执行&lt;/u&gt;<code>updateDomTrigger</code>方法,然后&lt;u&gt;再执行过渡动效&lt;/u&gt;。</p> </li> <li> <p>对于MPA,添加以下CSS规则,过渡效果会在导航到下一个同源页面的时候自动触发。</p> <pre><code>@view-transition { navigaion: auto; } </code></pre> </li> </ul> <h2>默认的过渡效果是&lt;u&gt;交叉淡化&lt;/u&gt;:</h2> <p>旧视图快照<code>opacity</code>从1 到 0,新视图快照<code>opacity</code>从0 到 1。</p> <h2>如何自定义动效:</h2> <p>HTML会针对视图动效生成以下伪元素树:</p> <pre><code>::view-transition └─ ::view-transition-group(root) └─ ::view-transition-image-pair(root) ├─ ::view-transition-old(root) └─ ::view-transition-new(root) </code></pre> <ul> <li>可以通过在多个 DOM 元素上设置不同的 <a><code>view-transition-name</code></a> CSS属性,对不同的元素使用不同的自定义动效。因此,每一个 <a><code>view-transition-name</code></a>都对应一个<code>view-transition-group</code>(默认是<code>root</code>)</li> <li><code>view-transition-old</code>指向动效前元素的静态快照</li> <li><code>view-transition-new</code>指向动效后元素的实时快照</li> </ul> <p>具体的动画效果由CSS animation设置:</p> <pre><code> /* 只需要添加以下@view-transition规则,就会在切换页面时,触发默认的“淡化”动效 */ @view-transition { navigation: auto; } /* 自定义默认的动画行为 */ ::view-transition-group(root) { animation-duration: 0.5s; } /* 创建自定义动画 */ @keyframes move-out { from { transform: translateY(0%); } to { transform: translateY(-100%); } } @keyframes move-in { from { transform: translateY(100%); } to { transform: translateY(0%); } } /* 将自定义动画应用到新旧元素 */ ::view-transition-old(root) { animation: 0.4s ease-in both move-out; } ::view-transition-new(root) { animation: 0.4s ease-in both move-in; } </code></pre> <h2>用JavaScript控制动效:</h2> <p>对于SPA,<a><code>document.startViewTransition()</code></a> 方法会返回一个 <a><code>ViewTransition</code></a> 对象实例,这个实例包含多个 promise:</p> <ul> <li><a><code>ViewTransition.ready</code></a> 在创建伪元素树且动画即将开始时执行。</li> <li><a><code>ViewTransition.finished</code></a> 在动画完成后、且新的页面视图对用户可见且具有交互性时执行。</li> </ul> <p>对于MPA:</p> <ul> <li>旧页面在即将unload之前,会触发<a><code>pageswap</code></a> 事件,事件的event对象上的<a><code>PageSwapEvent.viewTransition</code></a> 属性包含了 <code>ViewTransition</code> 实例, <a><code>PageSwapEvent.activation</code></a> 包含当前切换页面的导航类型、当前文档和目标文档历史记录。</li> <li>新页面初次渲染时, 会触发<a><code>pagereveal</code></a> 事件,事件的event对象上的<a><code>PageSwapEvent.viewTransition</code></a> 属性包含了 <code>ViewTransition</code> 实例。</li> <li>要注意的是,为了确保处理<a><code>pagereveal</code></a> 事件的script脚本在渲染动效之前执行,需要给脚本添加 <a><code>blocking=“render”</code></a> 属性;</li> <li>另外,为了确保动效执行之前,元素是可视的,需要添加标签<code>&lt;link rel="expect" href="#lead-content" blocking="render" /&gt;</code>,其中<code>#lead-content</code>指向对应元素。</li> </ul> <h2>浏览器兼容性</h2> <p><img src="https://prod-files-secure.s3.us-west-2.amazonaws.com/5e915be4-bfc2-464c-9c97-ee926a121cf1/caaf8df9-de8e-4db8-9105-6f8d2de2e242/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&amp;X-Amz-Credential=AKIAT73L2G45HZZMZUHI%2F20240919%2Fus-west-2%2Fs3%2Faws4_request&amp;X-Amz-Date=20240919T160947Z&amp;X-Amz-Expires=3600&amp;X-Amz-Signature=872495ce4514afe71f22e589e72c68f6d14672586a903ff2baf2b0bde129dd80&amp;X-Amz-SignedHeaders=host&amp;x-id=GetObject" alt="image.png" /></p> <h2>参考</h2> <ul> <li><a>MDN - </a><a><strong>Using the View Transitions API</strong></a></li> </ul> <hr /> <p>本篇文章使用<a>Notion</a>创作,由我的<a>自动化工具</a>从Notion同步。</p> 前端https://www.scarsu.com/view_transition_api/#post-comment/Stacking Context - DOM元素的层级关系https://www.scarsu.com/stacking_context/https://www.scarsu.com/stacking_context/理解DOM元素在网页z轴上的“竞争”Wed, 04 Sep 2024 00:00:00 GMT<h2>不是z-index越大的元素越在上层</h2> <p>通过z-index来控制层级是很常见的前端需求,</p> <p>但是你是否遇到过,无论z-index设置多大,仍然无法将一个元素移到最上层的情况?</p> <p>这是因为z-index依赖于一个抽象的概念:Stacking Context</p> <h2>Stacking Context是什么?</h2> <p>stacking context是层叠上下文,决定了DOM元素上下层级关系</p> <h2>Stacking Context的根元素</h2> <p>每个层叠上下文都由一个元素创建,这个元素被称为stacking context的根元素</p> <h2>什么情况会创建Stacking Context?</h2> <ul> <li>html根元素</li> <li>fixed定位的元素</li> <li>其他任何<code>z-index</code>不是默认值<code>auto</code>的元素(z-index=0也会创建层叠上下文)</li> <li>CSS <ul> <li>有透明度的元素:opacity&lt;1</li> <li>有二维/三维变幻的元素:transform不为none,或者will-change</li> <li>有滤镜的元素:filter不为none</li> <li><code>isolation: isolate;</code>:创建一个新的堆叠上下文,隔离混合效果</li> </ul> </li> </ul> <h2>Stacking Context之间的层级顺序</h2> <ul> <li>对于同级(根元素是兄弟元素)的stacking context,层级由z-index值决定,z-index大的在上层;</li> <li>同级stacking context如果z-index相同,由DOM中出现的顺序决定,出现晚的在上层;</li> <li>对于嵌套的stacking context,子stacking context在上层;</li> </ul> <h2>Stacking Context内部层级顺序</h2> <ul> <li>最底层:元素的背景色、背景图、边框</li> <li>子元素由底层到顶层的顺序: <ul> <li>z-index&lt;0的元素</li> <li>块级盒子</li> <li>浮动盒子</li> <li>内联盒子</li> <li>z-index:0或auto的定位盒子</li> <li>z-index&gt;0的元素</li> </ul> </li> </ul> <h2>例子🌰</h2> <p>DOM结构:</p> <pre><code>div1 div2 div3 -&gt; div4 -&gt; div5 -&gt; div6 </code></pre> <p>最终的层级顺序:</p> <p><img src="https://prod-files-secure.s3.us-west-2.amazonaws.com/5e915be4-bfc2-464c-9c97-ee926a121cf1/3f528781-3642-4a43-8531-6c8ad362289a/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&amp;X-Amz-Credential=AKIAT73L2G45HZZMZUHI%2F20240905%2Fus-west-2%2Fs3%2Faws4_request&amp;X-Amz-Date=20240905T160916Z&amp;X-Amz-Expires=3600&amp;X-Amz-Signature=4a51eecc58c81e55b2093473bcab93b4996cc0b3fa50bc208a592bd50cbd6ff4&amp;X-Amz-SignedHeaders=host&amp;x-id=GetObject" alt="image.png" /></p> <h2>一个有用的浏览器扩展:CSS Stacking Context inspector</h2> <p><img src="https://prod-files-secure.s3.us-west-2.amazonaws.com/5e915be4-bfc2-464c-9c97-ee926a121cf1/fe7e85f8-ad4a-499d-acd6-c727feda0e52/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&amp;X-Amz-Credential=AKIAT73L2G45HZZMZUHI%2F20240905%2Fus-west-2%2Fs3%2Faws4_request&amp;X-Amz-Date=20240905T160916Z&amp;X-Amz-Expires=3600&amp;X-Amz-Signature=7255fd56b56f4f2370eb2aaf52deb598058cfcf3313c43480bb76e142410ccec&amp;X-Amz-SignedHeaders=host&amp;x-id=GetObject" alt="image.png" /></p> <p>这个扩展在浏览器devtools中列出了网页上的stacking context。在遇到z-index和层级问题时,可以让我们更快的定位问题。</p> <hr /> <p>本篇文章使用<a>Notion</a>创作,由我的<a>自动化工具</a>从Notion同步。</p> 前端https://www.scarsu.com/stacking_context/#post-comment/2023热门JS语法新特性https://www.scarsu.com/2023_javascript_syntax/https://www.scarsu.com/2023_javascript_syntax/JS Syntax Feature from 《state of js 2023》Mon, 02 Sep 2024 00:00:00 GMT<h2>Nullish Coalescing</h2> <p>空值合并运算符(??),识别null和undefined值;<a>MDN</a></p> <pre><code>const foo = null ?? 'default string'; console.log(foo); // Expected output: "default string" const baz = 0 ?? 42; console.log(baz); // Expected output: 0 </code></pre> <h2>Dynamic Import</h2> <p>动态引入,import函数支持异步引入js模块;<a>MDN</a></p> <pre><code>import(moduleName) import(moduleName, options) await import('/modules/my-module.js') </code></pre> <h2>Private Field</h2> <p>类私有属性,以<code>#</code>为前缀,无法在类的外部引用;<a>MDN</a></p> <pre><code>class ClassWithPrivateField { #privateField } </code></pre> <h2>Logical Assignment</h2> <p>逻辑与赋值<code>&amp;&amp;=</code>,逻辑或赋值<code>||=</code>;<a>MDN</a></p> <pre><code>const a = { duration: 50, title: '' }; a.duration ||= 10; console.log(a.duration); // expected output: 50 a.title ||= 'title is empty.'; console.log(a.title); // expected output: "title is empty" let a = 1; let b = 0; a &amp;&amp;= 2; console.log(a); // Expected output: 2 b &amp;&amp;= 2; console.log(b); // Expected output: 0 </code></pre> <h2>Hashbang Comments</h2> <p><code>#!</code> HashBang注释,用于在shell中执行js时,指定js解释器</p> <p>是单行注释,只能写在js代码的第一行;<a>MDN</a></p> <pre><code>#!/usr/bin/env node console.log("Hello world"); </code></pre> <h2>error.cause</h2> <p>error实例中cause属性,指示了引起错误的具体原因;<a>MDN</a></p> <pre><code>try { connectToDatabase(); } catch (err) { throw new Error('Connecting to database failed.', { cause: err }); } </code></pre> <h2>array.toSpliced(),toSorted(),toReversed()</h2> <p>不改变数组原始值,创建新数据作为返回值</p> <h2>array.with()</h2> <p>相对于直接用<code>[索引]</code>更新数组,with方法不改变原始值、返回新数组</p> <pre><code>const arr = [1, 2, 3, 4, 5]; console.log(arr.with(2, 6)); // [1, 2, 6, 4, 5] console.log(arr); // [1, 2, 3, 4, 5] </code></pre> <hr /> <p>本篇文章使用<a>Notion</a>创作,由我的<a>自动化工具</a>从Notion同步。</p> 前端https://www.scarsu.com/2023_javascript_syntax/#post-comment/Notion到博客的自动化更新https://www.scarsu.com/notion_to_blog/https://www.scarsu.com/notion_to_blog/在notion写文章,自动化更新到git 代码仓库,再自动化部署到网站Sat, 29 Jul 2023 00:00:00 GMT<p>我在上周的文章<a>《</a><a><strong>程序员一定要有自己的博客</strong></a><a>》</a>中写了我博客工具链的5步:</p> <ol> <li>在趁手的工具写笔记(Notion PC端、移动端)</li> <li>工具将笔记转化为md文档</li> <li>自动推送md文档到我的博客git仓库</li> <li>git仓库更新,触发部署工具(netlify、vercel、jenkins)自动部署</li> <li>更新博客</li> </ol> <p>当时只实现了其中1245步,经过两天的探索我完成了第3步,让这个工具链实现了完整的自动化,这篇文章大致介绍一下。</p> <h2>从Notion到Git仓库</h2> <p>我的博客代码仓库使用Github托管,Github提供了一个十分有用的自动化工作流的工具:<a>Github Actions</a>。</p> <p>Github Actions 可以定时执行我提供的脚本,通过脚本,实现了从Notion到代码仓库的更新。大致逻辑是这样的:</p> <ol> <li>Github Actions 负责每天凌晨00:00执行脚本</li> <li>在脚本中,使用Notion API接口获取Notion特定数据库的数据,筛选出前一天更新的文章</li> <li>为每一篇文章,在代码仓库创建一个md文件</li> <li>将文章的attributes,转化为博客md文件的frontmatter</li> <li>将文章正文的md字符串,转化为md文件的正文内容</li> <li>将所有md文件通过git命令提交到github仓库中</li> <li>如果脚本执行失败,github会发邮件通知我</li> </ol> <p>通过以上脚本,实现了 notion文章数据库到git仓库的更新。</p> <p>脚本执行的频率是可以自由更改的,我偏向于损失一些时效性,保证环境稳定性,所以选择了一天一更新。</p> <p>以上脚本可以在我的博客开源仓库中看到,<a>链接在这里</a> 和 <a>这里</a>。</p> <p>由于我们的notion数据库字段、md文件的frontmatter配置很可能不同,我的脚本无法直接被你复用,有几个需要考虑变更的点:</p> <ul> <li>在你的git仓库中,需要配置几个脚本中需要使用的secrets。配置的地方在<code>你的github仓库首页 - settings - secrests and variables - actions</code>,参数名是<code>NOTION_DATABASE_ID</code>和<code>NOTION_KEY</code>,前者是你在Notion中文章所在数据库的id(可以通过copy link获得),后者是你开通的notion api的key(notion api的开通详见<a>这个文档</a>)。</li> <li>从notion page attributes到md frontmatter的映射,可以在<a>这个脚本</a>的<code>postToMDFile</code>中找到,逻辑比较简单,按照你的需求修改即可。</li> <li>脚本中的git信息,例如name、email、branch 可以按照你的需求修改。</li> <li>按照你的需求筛选notion数据,filter写在<a>这个脚本</a>的<code>getPosts</code>中。</li> <li>有一个可能踩坑的点在于,必须要将workflow读写仓库的权限开启,否则脚本会因为缺少git push权限而报错,开启权限的地方在:<code>github仓库首页-settings-actions-general-workflow permission - 开启read and write permissions</code></li> <li>脚本的执行周期,可以在上<a>述yml脚本</a>的cron字段中配置,注意脚本中的时间使用的是UTC时间,要考虑当地时区的时间差,例如UTC=北京时间-8,我希望在凌晨0点执行,所以写的小时是16。</li> </ul> <h2>从Git仓库到博客网站</h2> <p>这一步我使用的是Vercel工具,监听Git仓库的push事件,自动拉取代码更新,打包部署到网站。</p> <p>这一步Vercel的配置很简单,推荐查看<a>官方文档</a>,不做赘述。</p> <hr /> <p>本篇文章使用<a>Notion</a>创作,由我的<a>自动化工具</a>从Notion同步。</p> 个人成长https://www.scarsu.com/notion_to_blog/#post-comment/时钟准确的定时轮询函数https://www.scarsu.com/accurate_setinterval/https://www.scarsu.com/accurate_setinterval/js的单线程异步机制决定了setInterval和setTimeout函数的时钟不准确性Fri, 28 Jul 2023 00:00:00 GMT<p>浏览器原生的setTimeout(fn,timeout)函数的原理,是保证timeout时间后,将回调函数fn加入event loop的消息队列,不是保证timeout时间后一定执行。</p> <p>回调函数加入的消息队列后,实际的执行时间要等到 调用栈中已有函数 + 消息队列已有消息执行完毕。</p> <p>所以回调函数的实际执行时间与设定的timeout有偏差。</p> <p>setInterval函数也同样有偏差。</p> <p>以下实现了一个时间准确的定时轮询函数。</p> <h2>setClockInterval 函数</h2> <pre><code>/** * setClockInterval是时钟准确的定时轮询函数(原生setInterval时钟不准确) * @param func 与原生setInterval参数一致 * @param interval 与原生setInterval参数一致 * @return timer 类型为number */ const timerMap = new Map() export function setClockInterval(func: Function, interval: number) { let start: number let tick: number let clockTimer: number | null const timerId = Math.floor(Math.random() * 1e10) const recurFunc = () =&gt; { func() const realExcuTime = new Date().getTime() if (!start) { start = realExcuTime } tick = tick || start // bias是本次实际执行时间戳 与 理论执行时间戳tick之间的偏差 // bias一定&gt;=0,因为浏览器的setTimeout setInterval只会准时或者延迟执行,不会提前执行 // 经过本地浏览器统计 bias平均值在10ms以内,最大值在20ms左右 const bias = realExcuTime - tick console.log(`实际执行时间戳${realExcuTime},理论计划执行时间戳${tick},本次偏差${bias}ms`); // 下次tick时间戳 tick += interval // 因为本次实际执行时间有bias的延迟,所以下次执行提前 clockTimer = window.setTimeout(recurFunc, interval - bias) timerMap.set(timerId, clockTimer) } recurFunc() return timerId } </code></pre> <h2>clearClockInterval 函数</h2> <pre><code>/** * clearClockInterval 用于终止 setClockInterval 的定时轮询 * @param timer 是 setClockInterval 的返回值 */ export function clearClockInterval(timerId: number) { if (timerMap.has(timerId)) { window.clearTimeout(timerMap.get(timerId)) } else { console.warn(`timerId${timerId}not found`); } } </code></pre> <h2>demo执行效果</h2> <p>bias平均值在10ms以内,最大值在20ms左右</p> <pre><code>09:45:39.557 util.ts:23 实际执行时间戳1690508739557,理论计划执行时间戳1690508739550,本次偏差7ms 09:45:40.555 util.ts:23 实际执行时间戳1690508740555,理论计划执行时间戳1690508740550,本次偏差5ms 09:45:41.561 util.ts:23 实际执行时间戳1690508741561,理论计划执行时间戳1690508741550,本次偏差11ms 09:45:42.559 util.ts:23 实际执行时间戳1690508742559,理论计划执行时间戳1690508742550,本次偏差9ms 09:45:43.559 util.ts:23 实际执行时间戳1690508743559,理论计划执行时间戳1690508743550,本次偏差9ms 09:45:44.560 util.ts:23 实际执行时间戳1690508744560,理论计划执行时间戳1690508744550,本次偏差10ms 09:45:45.556 util.ts:23 实际执行时间戳1690508745555,理论计划执行时间戳1690508745550,本次偏差5ms 09:45:46.552 util.ts:23 实际执行时间戳1690508746552,理论计划执行时间戳1690508746550,本次偏差2ms 09:45:47.562 util.ts:23 实际执行时间戳1690508747562,理论计划执行时间戳1690508747550,本次偏差12ms 09:45:48.561 util.ts:23 实际执行时间戳1690508748561,理论计划执行时间戳1690508748550,本次偏差11ms </code></pre> 前端https://www.scarsu.com/accurate_setinterval/#post-comment/程序员一定要有自己的博客https://www.scarsu.com/why_blog_and_how_to_choose/https://www.scarsu.com/why_blog_and_how_to_choose/聊聊为什么要有博客,以及选择博客工具链的目标Wed, 19 Jul 2023 00:00:00 GMT<p>最近用astro对自己的博客进行了重构,投入了很大的热情和很多的时间,导致耽误了这个月的读书任务,于是反思了一下是否值得这么做。</p> <p><img src="/images/picgo/20230720232416.png" alt="" /></p> <h2>为什么要有博客</h2> <p>博客之于程序员意义重大,因为,<strong>输出</strong>是一个程序员的基本素养和技能,<strong>开源分享</strong>是科学技术发展和人类社会进步的重要美德和推动力,而博客正是输出分享的重要途径之一。</p> <p>为什么输出分享对程序员来说十分重要,我有以下几点看法。</p> <ul> <li> <p>从技术角度考虑,技术的提升依赖于专业知识的学习以及实际经验的积累,而人的大脑需要不断地进行重复记忆,才能将这些知识经验留在自己的知识库里。因此,无论是学习新知识还是通过实践得到的经验,有了即时的输出记录,才便于复盘与巩固。</p> </li> <li> <p>在实际工作中,当我们面临复杂大型的项目,和其中大量的代码时,如果只根据个人喜好而不根据代码规范去开发,写完后不留存开发文档以及接口文档,必然给项目的维护带来更高的代价,给团队中的其他开发者带来困扰。因此,代码规范和开发文档的输出也相当必要。</p> </li> </ul> <p>如果你还不相信,坚持输出给程序员带来好处的例子很多,我随意举几个。</p> <ul> <li> <p>例如 IT 圈出名的<a>阮一峰</a>,<a>张鑫旭</a>,stormzhang(这位已经不再分享技术了)等等大佬,他们有今天这种影响力的一个重要因素就是输出分享;</p> </li> <li> <p>我也曾不止一次收到前辈的建议,前端圈的<a>小爝</a>大佬在知乎的某个<a>回答</a>当中提到过“长期坚持技术输出和总结分享”在找工作面试中是一个亮点和加分项;</p> </li> <li> <p>“前端桃园”公号的运营者桃翁也十分提倡坚持输出,他在他星球小圈子中给我们分享过他自己 因为坚持输出提升了影响力 而多次收到阿里面试邀请的经历。</p> </li> </ul> <p>还有很多例子,不一一例举,分享本文的原因也就写到这,不再赘述。</p> <p>(当然输出分享的途径很多,本文以介绍博客为目的,如果选择其他途径可以忽略下文)</p> <h2>我选择博客工具链的目标</h2> <p>现在网络上有各式各样的博客,有基于第三方的平台(如博客园、csdn 等),自带用户和流量,但是要受平台约束和限制;</p> <p>也有可供个人搭建的工具(如 Hexo、Ghost、wordpress、jekyll 等),自由度高,但是需要从0开始搭建和积累流量;</p> <p>选择一个最适合自己的最重要。</p> <p>作为一个博客,我最重视的有两个方面:</p> <ol> <li>自由,可自定义,可个性化。</li> </ol> <p>因为每个人追求的博客风格不同,想要展示的内容和格式也有所不同。</p> <p>我希望能自由地表达自己想说的话。</p> <ol> <li>高效转化。</li> </ol> <p>我指的转化,是你的输出原文档 到 博客文本的转化,这一转化的过程对于想要存档原文,或不习惯于博客编辑器,不习惯于博客网页格式的人之分重要。</p> <p>我推崇用 markdown 来写笔记,因为 markdown 足够简约优雅,兼容性也十分强,</p> <blockquote> <p>Markdown 是一种轻量级的「标记语言」,通常为程序员群体所用,目前它已是全球最大的技术分享网站 GitHub 和技术问答网站 StackOverFlow 的御用书写格式。</p> <p>非技术类笔记用户,千万不要被「标记」、「语言」吓到,Markdown 的语法十分简单,常用的标记符号不超过十个,用于日常写作记录绰绰有余,不到半小时就能完全掌握。</p> <p>就是这十个不到的标记符号,却能让人优雅地沉浸式记录,专注内容而不是纠结排版,达到「心中无尘,码字入神」的境界。</p> </blockquote> <p>总结来说,我目标的工具链是这样的:</p> <ol> <li>在趁手的工具写笔记(Notion PC端、移动端)</li> <li>工具将笔记转化为md文档</li> <li>自动推送md文档到我的博客git仓库</li> <li>git仓库更新,触发部署工具(netlify、vercel、jenkins)自动部署</li> <li>更新博客</li> </ol> <p>目前已经实现了1,2,4,5,目前正在研究第3步,成功后我就不会再对工具链投入时间,而是把注意力放到内容上。</p> <h2>写在最后</h2> <p>以技术为目标的人,切忌浮躁。</p> <p>莫逞他人嘴上快,莫争浮世虚功名,心无旁骛,沉下心来钻研技术就好。</p> 个人成长https://www.scarsu.com/why_blog_and_how_to_choose/#post-comment/原则:Principles for Life and Workhttps://www.scarsu.com/principles_life_and_work/https://www.scarsu.com/principles_life_and_work/以看待机器的方式看待生活和工作,找到事情反复发生的周期,总结经验,转化为原则;客观地承认自己的缺点和思维盲点,保持开放的态度,与他人协作。Tue, 27 Jun 2023 00:00:00 GMT<h2>简介</h2> <ul> <li>书名:《原则》</li> <li>原名:Principles:Life and Work</li> <li>作者:瑞·达利欧</li> <li>出版时间:2018-1</li> <li>ISBN:9787508684031</li> <li>豆瓣链接:https://book.douban.com/subject/2760823</li> <li>豆瓣评分:8.3⭐</li> <li><a>官方动画讲解(全8集)- 哔哩哔哩</a></li> </ul> <p><img src="/images/picgo/IMG_0168.jpeg" alt="封面" /></p> <h2>必须做一个独立的思考者</h2> <ul> <li>必须自己思考真相是什么,必须基于自己的价值观总结自己的原则</li> <li>自己决定怎么做</li> <li>有勇气去做</li> <li>决策质量决定生活质量</li> <li>反思错误,形成原则。</li> </ul> <h2>拥抱现实,应对现实</h2> <ul> <li>真相是取得良好结果的根本基础</li> <li>梦想+现实+决心=成功的生活</li> <li>每个人都必须根据自身价值观选定目标、并选定实现目标的途径</li> <li>痛苦+反思=进步(一旦感受到痛苦,就是提示你反思进步的信号</li> <li>经历痛苦,反思,解决问题取得成功,总结经验原则应对未来</li> </ul> <h2>五步流程</h2> <ul> <li>知晓自己的目标</li> <li>应对阻碍你实现自己目标的问题,找出问题,不容忍问题</li> <li>诊断问题,找到问题根源,区分“症状和疾病根源”</li> <li>规划一个方案来彻底解决问题</li> <li>践行,推动自己做需要做的事</li> </ul> <h2>一切都是机器:事物运行原则</h2> <ul> <li>以看待机器的方式看待每个人、地球宇宙、生活、投资</li> <li>大多数事情都在以大同小异的方式反复发生,有些在易于识别的短期循环中发生(例如日出日落),有些可能在人的一生中也不会发生一次、或者在很长的周期才发生一次(例如百年一遇的地震 台风 养育孩子的周期)</li> <li>与其将每件事情当作一次性事件看待,不如将其视为类似情境的重现</li> <li>找到事情反复发生的周期和方式,看到其背后的因果关系,总结原则,以语言、算法的形式表达,以助于未来做更好的决策。</li> </ul> <h2>两个最大障碍</h2> <ul> <li>自我意识 <ul> <li>大脑里阻止你客观的承认自己缺点的区域,我们不喜欢直视自己错误和缺点,我们会不经过妥当的测试就相信自己的观点,我们本能地把对自己的弱点和错误的探讨 视作对自己的攻击 从而发怒。这导致我们接受不到客观反馈、做出差的决策</li> </ul> </li> <li>思维盲点 <ul> <li>人自以为能查知一切,但实际上任何人都无法完整的看到现实,人无法理解自己看不到的东西。</li> <li>每个人的音域、视力、辨色能力、味觉都不同,我们查知和理解事物的能力也不同,有的人习惯线性思维、有的人习惯发散思维;有些人可靠但没有创造力、有些人有创造力但却不可靠。 <ul> <li>只顺着自己的天性做事,就会忽略自己的弱点,就会失败。</li> </ul> </li> </ul> </li> </ul> <h2>如何解决上述两个问题:做到极度头脑开放</h2> <ul> <li>不为了「证明自己对而沾沾自喜」,而是为了「获得真相」而高兴</li> <li>与视角不同的思想者一起努力:找出与自己意见不同的最有想法的人,不在乎他们的结论,从他们的视角看问题,并让他们从我的视角看问题,这样就能一起把问题梳理明白,发现真相。</li> <li>把「惧怕错误结论的恐惧」转化为「追求真相的动力」。</li> </ul> <h2>奋力拼搏</h2> <ul> <li>直面现实、承认自己错误和缺陷、与在不同方面比自己更强的人走到一起,这些做法 是做出良好决策最有效的方式。</li> <li>目标只是诱饵,一次次奋力争取诱饵 迫使我们进化。与他人协作的个人进化才是拼搏的回报。</li> </ul> 个人成长https://www.scarsu.com/principles_life_and_work/#post-comment/Vite笔记https://www.scarsu.com/vite/https://www.scarsu.com/vite/Vite组成、原理、配置、插件、性能优化Sat, 17 Jun 2023 00:00:00 GMT<h2>Vite 读 /vit/</h2> <h2>资源</h2> <ul> <li>[官方文档](https ://Vitejs.dev/)</li> <li><a>Vite源码</a></li> <li><a>Awesome Vite</a></li> </ul> <h2>Vite发展&amp;现状</h2> <ul> <li><a>2021.2 v2版本</a></li> <li><a>2022.7 v3版本</a></li> <li><a>2022.12-至今 v4版本</a></li> <li>vue-cli官方推荐使用 <a><code>create-vue</code></a> 来创建基于 <a>Vite</a> 的新项目</li> </ul> <h2>Vite基本概念</h2> <p>Vite和webpack一样都是构建工具。</p> <p>使用webpack打包大型的前端应用,启动开发服务器时webpack必须优先抓取并分析 <strong>整个应用的依赖</strong> ,由于大型项目包含大量模块,可能需要很长时间(甚至是几分钟)才能启动dev server,文件修改后的HMR也可能长达几时秒到一分钟,极大影响开发者的开发效率。</p> <p>Vite就是为了解决这个问题而诞生。</p> <p><strong>目前Vite主要由两部分组成:</strong></p> <ul> <li><strong>一个开发服务器</strong>,服务于开发环境,它基于 <a>原生 ES 模块</a> 和ESBuild,提供了 <a>丰富的内建功能</a>:如速度很快的 <a>模块热更新(HMR)</a>。其原理是利用浏览器去解析 imports,在服务器端按需编译返回,完全跳过了打包这个概念,服务器随起随用。</li> <li><strong>一套构建指令</strong>,用于生产环境打包,使用 <a>Rollup</a> 打包代码,并且它是预配置的,可输出用于生产环境的高度优化过的静态资源。 &lt;!-- <img src="image/Vite/1685668545904.png" alt="1685668545904" /> --&gt;</li> </ul> <h2>上手</h2> <p>使用<code>npm create vite@latest</code>命令初始化一个Vite项目</p> <p>有六种框架可选:<img src="/images/picgo/20230702235218.png" alt="" /></p> <p>选择vue框架,初始化后的目录结构是这样: <img src="/images/picgo/20230702235353.png" alt="" /></p> <p>相较于过去基于webpack的vue项目,有2个不同之处。</p> <p>1是index.html从/public移出到了根目录,这是因为对于Vite项目而言,index.html就是一切依赖的入口。</p> <p>2是Vite.config.ts 替代了 vue.config.js。</p> <p>Vite其他命令如下:</p> <ul> <li><code>Vite</code>启动开发服务器</li> <li><code>Vite build</code> 打包</li> <li><code>Vite optimize</code> 预构建依赖</li> <li><code>Vite preview</code> 本地预览打包产物</li> </ul> <p>本地启动项目后,可以看到index.html中以原生ES模块的方式,引入了main.js和其他依赖:</p> <p><img src="/images/picgo/20230702235634.png" alt="" /></p> <p>对于浏览器对.vue文件的HTTP请求,通过设置<code>Content-Type: application/javascript</code>,被处理成了浏览器可识别的js逻辑,并且js中用的也是原生ES模块的导入导出语法: <img src="/images/picgo/20230703000005.png" alt="" /></p> <p>本地打包后,启动preview服务器查看效果: <img src="/images/picgo/20230703000124.png" alt="" /></p> <h2>学Vite的几个前置条件</h2> <h3>1 了解ES Module</h3> <p>Vite基于<a>原生ESM</a>实现。</p> <p>现在js程序越来越复杂,因此近年来Nodejs都支持<strong>将 JavaScript 程序拆分为可按需导入的单独模块</strong>的机制,例如,<a>CommonJS</a> 和基于 <a>AMD</a> 的其他模块系统 如 <a>RequireJS</a>、 <a>Webpack</a> 、 <a>Babel</a>。</p> <p>但是这类模块系统服务器启动缓慢,经历一条很长的编译打包链条,从入口开始需要逐步经历语法解析、依赖收集、代码转译、打包合并、代码优化,最终将高版本的、离散的源码编译打包成低版本、高兼容性的产物代码,流程如下图:</p> <p><img src="/images/picgo/20230703000211.png" alt="" /></p> <p>最新的<strong>浏览器开始原生支持模块功能</strong>、浏览器支持es语法中的import和export语法</p> <p>可以通过 <code>&lt;script type="module" src="xx"&gt; 引入模块</code>。</p> <p>浏览器通过HTTP请求的方式,按需加载每一个被引入的模块,在启动开发服务器时,可以达到免打包、随开随用的效果,流程如下:</p> <p><img src="/images/picgo/20230703000248.png" alt="" /></p> <h3>2 了解ESBuild</h3> <p>那么Vite为什么不直接使用浏览器原生esm,还要用ESBuild呢?</p> <p>因为浏览器原生ESM功能有限,例如:只支持用<strong>完整的相对路径/绝对路径</strong>引入模块,不支持引入裸模块(以模块名的方式从node_modules下引入模块),会报错,举个例子引入lodash的报错:</p> <p><img src="/images/picgo/20230703000821.png" alt="" /></p> <p><img src="/images/picgo/20230703000715.png" alt="" /></p> <p>为什么浏览器不支持自动从node_modules下寻找并引入模块?如果某个模块依赖项很多,而每个模块又会产生一次HTTP请求,会导致严重的HTTP请求并发问题。</p> <p>而 <a>ESBuild</a> 会对依赖进行 <a>预构建</a>,对原生的ESM功能进行了扩展。</p> <p>另外,ESBuild 使用 Go 编写,比以 JavaScript 编写的打包器预构建依赖快 10-100 倍。(<a>文章 - ESBuild 为什么那么快</a>)</p> <h3>3 了解Rollup</h3> <p>对于生产环境,Vite会使用rollup进行生产环境的构建和打包。</p> <p>ESBuild 也支持打包,为何不用 ESBuild 打包?</p> <p>目前Vite团队认为 Rollup 提供了更好的<strong>性能与灵活性</strong>方面的权衡:Vite 目前的插件 API 与使用 <code>ESBuild</code> 作为打包器并不兼容。尽管 <code>ESBuild</code> 速度更快,但 Vite 采用了 Rollup 灵活的插件 API 和基础建设,这对 Vite 在生态中的成功起到了重要作用。</p> <p>(即便如此,<code>ESBuild</code> 在过去几年有了很大进展,Vite不排除在未来使用 <code>ESBuild</code> 进行生产构建的可能性。)</p> <p>近年来对于构建工具的选择,主流的经验是:</p> <p><img src="/images/picgo/20230703000942.png" alt="" /></p> <p>关于Webpack和Rollup的区别,推荐阅读一篇2017年的Medium文章:<a>Webpack and Rollup: the same but different</a>。</p> <p>相较于Rollup,Webpack有着丰富庞大的生态系统、大量的contributors和sponsors,rollup的生态并没有webpack工具强大。</p> <p>但Rollup是React, Vue, Ember, Preact, D3, Three.js, Moment等众多知名开源库选择的构建工具,rollup相对webpack更轻量,其构建的代码并不会像webpack一样被注入大量的webpack内部结构,而是尽量的精简保持代码原有的状态。它同样支持tree-shaking、依赖解析等能力。</p> <h2>Dev Server 功能 &amp; 原理</h2> <p>我在本地进行了实际对比:</p> <p>使用vue cli创建一个webpack+vue的空项目,启动devserver时间在10s左右;</p> <p>使用Vite创建一个Vite+vue的空项目,启动dev server的时间在1s-2s左右。</p> <p>Vite本地启动比webpack快很多,那么Vite启动本地服务器的原理是什么?</p> <p><code>Vite</code> 会将应用代码分为 <strong>依赖</strong> 和 <strong>源码</strong> 两类,对不同的模块进行<strong>按需编译。</strong></p> <h3>1 依赖预构建</h3> <ul> <li>对于依赖:当首次启动 <code>dev server</code> 时,Vite 会在本地加载站点之前<strong>预构建</strong>依赖。</li> <li>默认情况下,预构建是自动且透明地完成的,可以在Vite.config.js配置中禁用。</li> <li>Vite 底层使用 <code>ESBuild</code> 预构建依赖( <code>Esbuild</code> 使用 Go 编写,比以 JavaScript 编写的打包器预构建依赖快 10-100 倍)。</li> </ul> <h4>兼容导出格式</h4> <p>为了兼容不同的第三方依赖包的不同的导出格式(例如浏览器不支持的commonjs),ESBuild会将所有依赖包转换为浏览器支持的esm格式,然后放到当前目录 <code>node_modules/.Vite/deps</code>下。</p> <h4>多包传输优化</h4> <p>为了解决浏览器网络多包传输的性能问题,ESBuild会分析依赖链,将多模块的import集成到一个模块中去,减少 http 请求数。例如引入lodash-es包的合并前后对比:</p> <p><img src="/images/picgo/20230703002715.png" alt="" /></p> <h4>补齐import路径</h4> <p>浏览器只支持完整相对路径/绝对路径形式引入模块,对于裸模块、省略了文件后缀名的模块,预构建阶段会对路径进行补齐和重写。例如引入lodash包:</p> <pre><code>import _ from "lodash"; </code></pre> <p><img src="/images/picgo/20230703002852.png" alt="" /></p> <h4>强缓存</h4> <p>依赖包的HTTP请求会被Vite设置为 <code>Cache-Control: max-age=31536000,immutable</code> 进行<strong>强缓存。</strong></p> <p><img src="/images/picgo/20230703002952.png" alt="" /></p> <h3>2 源码转换</h3> <p>对于源码:JSX、CSS 或者 Vue SFC等,Vite会对其进行转换,以 <a>原生 ESM</a> 方式提供源码。</p> <h4>Vite对vue文件的处理</h4> <p>对于.vue文件:Vite会使用vue-compiler将其转为js,通过设置Content-Type:text/javascript,让浏览器将.vue文件识别为js文件并解析。<img src="/images/picgo/20230703000005.png" alt="" /></p> <h4>Vite对css的处理</h4> <p>对于css文件:Vite会将浏览器.css文件的HTTP请求设置Content-Type:text/javascript,然后把css文件的内容替换为一段js代码,这段js代码的逻辑就是将对应的css代码作为 <code>&lt;style&gt;</code>标签插入到html文件中,并且支持css的热更新功能。<img src="/images/picgo/20230703003133.png" alt="" /></p> <p>CSS代码分割:Vite 会自动地将一个异步 chunk 模块中使用到的 CSS 代码抽取出来并为其生成一个单独的文件(而不是将所有的 CSS 抽取到一个文件中),这个 CSS 文件将在该异步 chunk 加载完成时自动通过一个 <code>&lt;link&gt;</code> 标签载入,该异步 chunk 会保证只在 CSS 加载完毕后再执行,避免发生 <a>FOUC</a> 。</p> <h4>Vite对css模块化的处理</h4> <p>将所有.module.css后缀的文件视为模块化css,例子:</p> <pre><code>Foo.module.css文件: .footer{ width: 100px; height: 100px; background-color: rosybrown; } Bar.module.css文件: .footer{ width: 100px; height: 100px; background-color: rosybrown; } </code></pre> <p>对其css代码中的所有类名进行 <strong>哈希转换</strong>,创建<strong>映射对象</strong>:</p> <pre><code>&lt;script setup&gt; import css from "@/styles/modules/Bar.module.css"; console.log('Bar.module.css映射对象', css); &lt;/script&gt; </code></pre> <p>&lt;!-- <img src="image/Vite/1686193428140.png" alt="1686193428140" /> --&gt;</p> <p>然后将原始css文件中的代码抹除,替换成一段JS脚本,这段脚本会将上述的映射对象 默认导出:</p> <p>&lt;!-- <img src="image/Vite/1686193624774.png" alt="1686193624774" /> --&gt;</p> <p>这段脚本的逻辑是将哈希转换后的css代码,作为 <code>&lt;style&gt;</code>标签插入html中:</p> <p>&lt;!-- <img src="image/Vite/1686193719848.png" alt="1686193719848" /> --&gt;</p> <h4>Vite对less和scss的处理</h4> <p>Vite 也同时提供了对 <code>.scss</code>, <code>.sass</code>, <code>.less</code>, <code>.styl</code> 和 <code>.stylus</code> 文件的内置支持。没有必要为它们安装特定的 Vite 插件,但必须安装相应的预处理器依赖:</p> <pre><code># .scss and .sass npm add -D sass # .less npm add -D less # .styl and .stylus npm add -D stylus </code></pre> <p>Vite调用各个css预处理器将.scss .less转换为css代码后,对css代码的处理同上述【Vite对css的处理】</p> <h4>协商缓存</h4> <ul> <li>源码的HTTP请求会被Vite设置为 <code>304 Not Modified</code> 进行<strong>协商缓存</strong>。</li> </ul> <h3>3 静态资源处理</h3> <h4>尽量遵循 ESM 方式提供静态资源</h4> <p>Vite 尽量避免直接处理静态资源,而是选择遵循 ESM 方式提供服务,例如引入静态资源图片 <code>import img from 'xxx.png'</code> ,执行后会返回解析后的 URL,供浏览器直接请求:</p> <ul> <li>常见的图像、媒体和字体文件类型会被自动检测为资源,可以通过<a><code>assetsInclude</code> 选项</a>配置文件后缀名。</li> <li>代码中引入的静态资源,会返回解析后的公共路径:</li> </ul> <pre><code>import imgUrl from './img.png' document.getElementById('hero-img').src = imgUrl </code></pre> <ul> <li> <p>Vue SFC <code>&lt;template&gt;</code>中的资源引用,会被自动转换为import语句。</p> </li> <li> <p>资源体积小于 <a><code>assetsInlineLimit</code> 选项值</a> (默认4KB)会被转换为内联的 base64 data URL。</p> </li> <li> <p>在 CSS 中引用的 <code>url()</code>,也是同样的处理方式。</p> </li> <li> <p>如果需要显式引入一个资源的url,可以加 <code>?url</code>后缀:</p> <pre><code>import workletURL from 'extra-scalloped-border/worklet.js?url' CSS.paintWorklet.addModule(workletURL) </code></pre> </li> <li> <p>如果需要将资源引入为字符串,可以使用 <code>?raw</code> 后缀:</p> <pre><code>import shaderString from './shader.glsl?raw' </code></pre> </li> <li> <p>public目录:对于不会被源码引入、保持原文件名不加hash的文件,可以放在项目根目录下public目录中,开发时必须<strong>直接通过“/”根路径访问</strong>,打包时也会被完整复制到根目录下。</p> </li> <li> <p>支持JSON的具名导入(解构导入)</p> </li> </ul> <h4>使用 <code>new URL(url, import.meta.url)</code>:</h4> <p><a>import.meta.url</a> 是一个 现代浏览器支持的 ESM 的原生功能,会暴露当前模块的 URL。将它与原生的 <a>URL 构造器</a> 组合使用,在一个 JavaScript 模块中,通过相对路径我们就能得到一个被完整解析的静态资源 URL:</p> <pre><code>const imgUrl = new URL('./img.png', import.meta.url).href document.getElementById('hero-img').src = imgUrl </code></pre> <p>在dev server使用上述方法,可以借助浏览器的原生能力,而不需要Vite做处理。</p> <p>对于生产构建时,Vite 会进行必要的转换保证 URL 在打包和资源哈希后仍指向正确的地址。</p> <h2>Vite打包功能</h2> <h3>打包入口</h3> <p>默认情况下,以 <code>&lt;root&gt;/index.html</code> 作为打包入口,并生成能够静态部署的应用程序包。</p> <p>MPA多页应用:在 <code>build.rollupOptions.input</code>数组中,定义多个html入口即可。</p> <h3>hash</h3> <p>打包后的资源文件名有hash,与文件内容一一对应(文件内容更新才会更新hash值,便于控制浏览器缓存)。</p> <h3>浏览器兼容性</h3> <p>Vite不支持低版本浏览器:</p> <ul> <li>默认情况下 Vite 只处理语法转译,且 <strong>默认不包含任何 polyfill</strong> 。</li> <li>默认情况下,Vite 的目标是 <a>支持原生 ESM</a>、<a>支持原生 ESM 动态导入</a> 和 <a>import.meta</a> 的浏览器:Chrome &gt;=87,Firefox &gt;=78,Safari &gt;=14,Edge &gt;=88</li> <li>可以通过 build.target 配置项指定构建目标,最低支持 es2015。</li> <li>可以通过插件 <a>@Vitejs/plugin-legacy</a> 支持传统浏览器,最低支持到IE 11</li> </ul> <h3>rollup配置</h3> <p>Vite基于Rollup工具打包,可以通过 <code>build.rollupOptions</code> 直接调整底层的 <a>Rollup 选项</a>。</p> <h3>base路径</h3> <p>如果需要 在嵌套的服务器路径下部署项目,可以指定 <a><code>base</code> 配置项</a>。</p> <h3>build watch</h3> <p>可以使用 <code>Vite build --watch</code> 来启用 rollup 的监听器,文件变化时重新构建。</p> <h3>预加载优化</h3> <p>Vite 会为入口 chunk 和它们在打包出的 HTML 中的直接引入自动生成 <code>&lt;link rel="modulepreload"&gt;</code> 指令,实现预加载优化。</p> <h2>Vite配置文件</h2> <h3>配置文件的语法提示</h3> <p>Vite的配置文件是 <code>Vite.config.js</code>,可以直接写成:</p> <pre><code>export default {} </code></pre> <p>但是,可以利用 <code>defineConfig</code>获得语法提示和类型约束:</p> <pre><code>import { defineConfig } from "Vite"; export default defineConfig({}) </code></pre> <p>也可以利用IDE和jsdoc支持,来获得语法提示</p> <pre><code>/** @type {import('vite').UserConfig} */ export default { // ... } </code></pre> <h3>不同环境配置</h3> <p>类似于webpack.dev.config、webpack.prod.config</p> <p>Vite在配置文件提供环境区分:</p> <pre><code>export default defineConfig(({ command, mode, ssrBuild }) =&gt; { if (command === 'serve') { return { // dev 独有配置 } } else { // command === 'build' return { // build 独有配置 } } }) </code></pre> <p>可以采用更具有扩展性的方式:</p> <pre><code>import { defineConfig } from "Vite"; import ViteBaseConfig from "./Vite.base.config"; import ViteDevConfig from "./Vite.dev.config"; import ViteProdConfig from "./Vite.prod.config"; // 策略模式 const envResolver = { serve: ()=&gt;Object.assign({}, ViteBaseConfig, ViteDevConfig), build: ()=&gt;Object.assign({}, ViteBaseConfig, ViteProdConfig) } export default defineConfig(({ command, mode, ssrBuild }) =&gt; { return envResolver[command](); }); </code></pre> <h3>环境变量</h3> <p>Vite内置了<a>dotenv</a>库:支持读取 <code>.env</code>文件。</p> <pre><code>.env # 所有情况下都会加载 .env.local # 所有情况下都会加载,但会被 git 忽略 .env.[mode] # 只在指定模式下加载 .env.[mode].local # 只在指定模式下加载,但会被 git 忽略 </code></pre> <p>Vite会解析<code>.env</code>文件中的所有环境变量注入到node端 <code>process.env</code>对象中; 解析其中<code>Vite_</code> 前缀的环境变量,注入到客户端的 <code>import.meta.env</code>对象中。</p> <p>但是 Vite.config.js执行时,默认是不加载 <code>.env</code> 文件的,因为这些文件需要在执行完 Vite 配置后才能确定加载哪一个,举个例子:Vite.config.js中的 <code>envDir</code> 选项会影响到.env的加载。</p> <p>如果需要提前在Vite.config.js中获取环境变量,可以使用 Vite 的 <a>loadEnv</a> 函数来加载指定的 <code>.env</code> 文件:</p> <pre><code>export default defineConfig(({ command, mode, ssrBuild }) =&gt; { // 根据mode加载.env文件,默认是.env.development和.env.production,可以在Vite命令后通过--mode配置 // process.cwd()指定env文件目录是当前执行node脚本所在的目录 // 第三个参数是变量前缀,设置为''会加载所有环境变量,而不管是否有 `Vite_` 前缀。 const env = loadEnv(mode, process.cwd(), '') console.log(env); }); </code></pre> <h3>路径别名</h3> <pre><code>resolve:{ alias: { '@': path.resolve(__dirname,'../', 'src') } } </code></pre> <p>当使用文件系统路径的别名时,要始终使用绝对路径。相对路径的别名值会原封不动地被使用,因此无法被正常解析。</p> <h3>css配置</h3> <p><a>配置项 css.modules </a>定义了CSS modules 的行为,会被传递给 <a>postcss-modules</a>。</p> <ul> <li><code>css.modules.localsConvention</code>:配置了对css模块类名转换后,映射对象中key的写法,camelCase驼峰,dashes中划线</li> </ul> <p><a>配置项目 css.preprocessorOptions </a>指定了传递给 CSS 预处理器的选项。文件扩展名用作选项的键。每个预处理器支持的选项可以在它们各自的文档中找到:</p> <ul> <li><code>sass</code>/<code>scss</code> - <a>选项</a>。</li> <li><code>less</code> - <a>选项</a>。</li> <li><code>styl</code>/<code>stylus</code> - 仅支持 <a><code>define</code></a>,可以作为对象传递。</li> </ul> <p><a>配置项 css.postcss </a>与postcss.config.js文件的起同等作用。</p> <h3>proxy代理配置</h3> <p>通过<code>server.proxy</code>为开发服务器配置自定义代理规则。</p> <p>相关配置内容继承自 <a>http-proxy</a>。</p> <h2>Vite插件</h2> <h3>Vite插件作用是什么</h3> <p>Vite在不同的生命周期中取调用不同的插件,以达到不同的目的。</p> <h3>使用插件</h3> <p>可选的插件:<a>官方插件</a>、<a>社区插件</a>、<a>部分兼容Vite的rollup插件</a></p> <p>例子:引入并使用插件 <a>Vite-aliases</a> (自动根据项目目录生成 路径别名配置)</p> <p><code>npm i Vite-aliases -D</code></p> <pre><code>// Vite.config.js import { ViteAliases } from 'Vite-aliases' export default { plugins: [ ViteAliases() ] }; </code></pre> <p>假如项目目录是:</p> <pre><code>src assets components pages store utils </code></pre> <p>会自动生成如下配置:</p> <pre><code>[ { find: '@', replacement: '${your_project_path}/src' }, { find: '@assets', replacement: '${your_project_path}/src/assets' }, { find: '@components', replacement: '${your_project_path}/src/components' }, { find: '@pages', replacement: '${your_project_path}/src/pages' }, { find: '@store', replacement: '${your_project_path}/src/store' }, { find: '@utils', replacement: '${your_project_path}/src/utils' }, ] </code></pre> <h3>插件原理 &amp; 插件开发</h3> <p>插件开发文档: https://cn.Vitejs.dev/guide/api-plugin.html</p> <h4>1 插件代码结构</h4> <p>Vite插件应该是一个“返回实际插件对象的工厂函数”:</p> <pre><code>export default function myPlugin(config) { return { name: 'xx', transform(src, id) { // 此处transform是一个rollup和Vite通用的钩子 }, } } </code></pre> <h4>2 插件钩子</h4> <p>开发插件最核心的逻辑就是搞清楚:我的插件应该在哪些Vite生命周期做哪些事情。</p> <p>因此要先了解Vite提供了哪些生命周期钩子:</p> <ul> <li> <p>通用钩子:在开发中,Vite 开发服务器会创建一个插件容器来调用 <a>Rollup 构建钩子</a>,与 Rollup 如出一辙:</p> <ul> <li>在dev server启动时被调用的钩子: <ul> <li><a><code>options</code></a> :<code>(options: InputOptions) =&gt;InputOptions | null</code>。构建阶段第一个钩子,替换或操作传递给 <code>rollup</code> 的选项对象,在 Rollup 配置完成之前运行。</li> <li><a><code>buildStart</code></a> :<code>(options: InputOptions) =&gt;void</code>。在options后被调用,可以读取到最终options值,被 rollup.rollup 方法调用,如果仅需要读取options推荐使用这个钩子。</li> </ul> </li> <li>在每个模块请求时被调用的钩子: <ul> <li><a><code>resolveId</code></a> :定义自定义解析器,可以用于定位第三方依赖项等。</li> <li><a><code>load</code></a>:定义自定义加载器。</li> <li><a><code>transform</code></a>:用于转换单个模块。类似于webpack中的loader,在Vite源码有使用这个钩子转译vue文件以及template模板。</li> </ul> </li> </ul> </li> <li> <p>Vite 独有钩子:服务于特定的 Vite 目标。这些钩子会被 Rollup 忽略。</p> <ul> <li>config:在解析 Vite 配置前调用。接收原始用户配置,可以返回一个将被deepMerge到现有配置中的部分配置对象。</li> <li>configResolved:在解析 Vite 配置后调用。使用这个钩子读取和存储最终解析的配置。</li> <li>configureServer:用于配置dev server的钩子,最常见的用例是给dev server添加自定义中间件,会在内部中间件被安装前调用。中间件API <code>server.middleware.use((req,res,next)=&gt;{})</code>。</li> <li>configurePreviewServer:用于预览服务器。用上一个用法类似。</li> <li>transformIndexHtml:转换 <code>index.html</code> 的专用钩子。钩子接收当前的 HTML 字符串和转换上下文 <code>ctx</code>。<code>ctx</code>在开发期间暴露<a><code>ViteDevServer</code></a>实例,在构建期间暴露 Rollup 输出的包。</li> <li>handleHotUpdate:自定义 HMR 行为。</li> </ul> </li> </ul> <h4>3 插件执行顺序</h4> <p>可以指定插件的enforce属性,来调整插件的执行顺序,enforce=pre/post。</p> <p>所有插件的执行顺序如下:</p> <ul> <li>Alias</li> <li>带有 <code>enforce: 'pre'</code> 的用户插件</li> <li>Vite 核心插件</li> <li>没有 enforce 值的用户插件</li> <li>Vite 构建用的插件</li> <li>带有 <code>enforce: 'post'</code> 的用户插件</li> <li>Vite 后置构建插件(最小化,manifest,报告)</li> </ul> <h4>4 区分mode执行插件</h4> <p>默认情况下插件在开发(serve)和构建(build)模式中都会调用。</p> <p>如果插件只需要在预览或构建期间有条件地应用,使用 <code>apply</code> 属性指明它们仅在 <code>'build'</code> 或 <code>'serve'</code> 模式时调用</p> <pre><code>function myPlugin() { return { name: 'build-only', apply: 'build' // 或 'serve' } } </code></pre> <h2>Vite 对 TS的支持</h2> <ul> <li>Vite 天然支持引入 <code>.ts</code> 文件。</li> <li>Vite 使用 <a>ESBuild</a> 将 TypeScript 转译到 JavaScript,约是 <code>tsc</code> 速度的 20~30 倍。</li> <li>Vite只负责转译ts代码,不负责类型检查。(Vite默认类型检查已经被你的 IDE 或构建过程处理了。)(原因是类型检查会影响Vite的速度:转译在每个文件的基础上进行,与 Vite 的按需编译模式完全吻合。相比之下,类型检查需要了解整个模块图。把类型检查塞进 Vite 的转换管道,将不可避免地损害 Vite 的速度优势。)</li> </ul> <p>Vite不负责类型检查,怎么获得更多类型检查提示?</p> <ul> <li>开发时,在项目中使用ts,并添加tsconfig.json配置,就可以依赖IDE自带的ts检查。</li> <li>开发时,可以在一个单独的进程中运行 <code>tsc --noEmit --watch</code>,可以获得更多IDE提示。</li> <li>打包时,可以这样运行 Vite 构建命令: <code>tsc --noEmit &amp;&amp; Vite build</code>,如果检查到类型错误,会报错并停止打包。</li> <li>也可以使用<a>Vite-plugin-checker</a>插件,会将ts类型错误抛到浏览器中。</li> </ul> <h2>Vite性能优化</h2> <h3>分包策略</h3> <p>把一些不会经常更新的依赖,单独打包:通过配置 <code>build.rollupOptions.output.manualChunks</code> 来自定义 chunk 分割策略:</p> <pre><code>({ manualChunks: (id) =&gt; { if (id.includes("node_modules")) { return "vendor"; } }, }); </code></pre> <p>或者直接使用Vite4中内置的 <code>splitVendorChunkPlugin</code> 插件,会自动拆分vender chunk:</p> <pre><code>// Vite.config.js import { splitVendorChunkPlugin } from "vite"; export default defineConfig({ plugins: [splitVendorChunkPlugin()], }); </code></pre> <h3>gzip压缩</h3> <p>使用 <a>Vite-plugin-compression</a> 插件,打包后会生成静态资源的压缩文件,后缀是.gz,直接提供给浏览器去解压缩。由于消耗浏览器资源,只针对大的文件进行压缩;</p> <p>这种方式与nginx的gzip压缩区别在哪?nginx上的资源是以原始文件形式存在的,当返回给浏览器的时候再进行压缩,浏览器收到压缩文件再解压缩。是动态压缩,会消耗服务器资源。如果提前压缩好.gz文件,可以节省服务器压力。</p> <h3>动态导入</h3> <p>动态导入也是es原生支持的特性。</p> <p>例如使用动态导入引入一个异步组件4:</p> <pre><code>import { defineAsyncComponent } from "vue"; const Bar = defineAsyncComponent(() =&gt; import("@cmp/Bar/index.vue")); </code></pre> <p>打包后,Bar组件的代码会被单独打包为一个chunk,在使用到Bar组件时浏览器会按需加载这个chunk。</p> <h3>Glob导入</h3> <p>Vite 支持使用特殊的 <code>import.meta.glob</code> 函数从文件系统导入多个模块:<code>const modules =import.meta.glob('./dir/*.js')</code>。</p> <p>匹配到的文件默认是懒加载的,通过动态导入实现,并会在构建时分离为独立的 chunk。</p> <h3>避免单屏拥有过度数目的依赖</h3> <p>举个例子:lodash-es是lodash为了支持构建工具tree-shaking而诞生的包,包中导出了600多个模块,如果我们在vite项目中不小心写了以下代码:</p> <p><code>import * as lodash from 'lodash-es';</code></p> <p>这将会导致dev server模式下,页面出现严重卡顿,因为浏览器会将这600多个子模块全部作为HTTP请求,进而导致了严重的HTTP请求并发问题。</p> <p><img src="/images/picgo/vite.gif" alt="" /></p> <p>如上动态演示,这些请求都会阻塞DOM的渲染,降低开发效率。</p> 前端https://www.scarsu.com/vite/#post-comment/长安的荔枝:古装版社畜求生记https://www.scarsu.com/chang_an/https://www.scarsu.com/chang_an/见微知著,从小人物的视角体味历史与政治Mon, 12 Jun 2023 00:00:00 GMT<blockquote> <p>一骑红尘妃子笑,有人知是荔枝来。</p> </blockquote> <p><img src="/images/picgo/lizhi.jpg" alt="封面" /></p> <p>《长安的荔枝》是马伯庸写的小说,他以大唐天宝14年为历史背景,以一位长安九品小吏李善德为主角,叙述了他完成从岭南运送新鲜荔枝到长安这一任务的故事。</p> <p>故事的开端,李善德 受领导设计,接手了这个“无法完成的”差事:要在六月一日杨贵妃生日之前,从岭南运送新鲜荔枝到长安。而荔枝保鲜期只有三天、从岭南到长安五千里路程。</p> <p>他恐惧、绝望到想与妻子和离 交代后事,遂又接受了两位好友的安慰和出谋划策,决心奔赴岭南,放手一搏。</p> <p>经过种种努力、多次试验和数据分析,他终于找到了保鲜的最佳方法、最优的运送路径,在自己的一次亲身试验中,成功将新鲜荔枝从岭南送到长安,就在他沉浸于喜悦之中、准备安排最终运送细节时,他又被不同部门来回踢皮球、差点被人抢功,经人引导下,投靠上了卫国公杨国忠,才得到各部门的配合。在最终的运送过程中,他又遭遇了几次意想不到的危机、感受到了身不由己的无奈、失去朋友信任的悲痛、对皇权贵势下百姓苦难的愤懑。</p> <p>整个故事读下来,有几处令我印象深刻的点。</p> <ol> <li>不要随意接手自己不清楚的任务、不要签署未确认过的文件、不要在不清醒状态做决策。荔枝使的任务已经被多个部门踢来踢去踢到了李善德的部门,由于有一天他请假不在,于是领导和同事统一意见踢给他,在酒局上珍肴美酒下肚、几句奉承话入耳,李善德便接下了这个任务。</li> <li>学会“和光同尘”。李善德在岭南研究出运送方法后,险些被岭南官员杀害,原因就是这个任务以往都没有人完成,一旦李善德完成,其他人就有了“办事不力”的罪名。如果能让出部分功劳,“归功于xx通力配合”,情况就能转变。</li> <li>学会“借势”,规矩是约束弱者的。李善德照规矩办事,却处处碰壁,而靠着卫国公杨国忠的银牌,却畅通无阻。强者制造规则、智者利用规则、弱者遵守规则。</li> <li>不要随便许诺。胡商苏谅在李善德多次试验中提供了大量资金帮助,李善德答应了让苏的商队接下运送荔枝的差事,不曾想这根本不由李善德说了算,于是只能毁诺于苏谅,丢失了朋友、丢失了信任。</li> <li>有时候小人物只是大人物博弈的棋子。李善德以为,是皇帝为取悦杨贵妃才要岭南的荔枝,而自己这个荔枝使是任务完成与否的核心人物,直到最后才发现,整个事件不过是高力士为了打压鱼朝恩,设下的局。</li> <li>不要小看政治背后的复杂和黑暗。李善德以为,皇帝和朝廷会承担这几斤荔枝带来的巨额费用,没想到,最终的人力、物力竟然来源于对百姓提高税赋、增加徭役,甚至其中还有差价不知进了谁的口袋;为了荔枝保鲜,需要砍下荔枝树干运送,荒废一颗荔枝树,最初要的十斤荔枝只需要砍一棵树,但是为了保证层层运送不出差错、无人担责,最终要砍下10棵树,这其中10倍的损耗令人唏嘘。</li> </ol> 个人成长https://www.scarsu.com/chang_an/#post-comment/极简学习法:精准输入-深度消化-多元输出https://www.scarsu.com/minimal_learning_method/https://www.scarsu.com/minimal_learning_method/学习一切知识,都可以遵循【精准输入-深度消化-多元输出】这三个步骤Sun, 11 Jun 2023 00:00:00 GMT<h2>简介</h2> <ul> <li>书名:《极简学习法》</li> <li>作者:廖恒</li> <li>出版时间:2022-4-10</li> <li>ISBN:9787559659385</li> <li>豆瓣链接:https://book.douban.com/subject/35856498/</li> <li>豆瓣评分:7.3⭐</li> </ul> <p><img src="/images/picgo/minimal_learning_method.png" alt="" /></p> <h2>优势</h2> <ul> <li>极简闭环:学习一切知识,都可以遵循【精准输入-深度消化-多元输出】这三个步骤</li> <li>追求精准:从目标倒推输入内容</li> <li>直击本质:选择最本质的东西去学习。</li> <li>举一反三,知识迁移</li> <li>麦肯锡的“MECE”原则,英文全称是 Mutually Exclusive Collectively Exhaustive,中文意思是“相互独立,完全穷尽”。也就是说,对于一个重大的议题,要做到不重叠、不遗漏的分类。这是一种非常重要的方法论</li> </ul> <h2>1 精准输入</h2> <ul> <li><strong>倒推</strong>思维,学习“决定结果的知识”。确定自己的目标是什么,推演实现目标的过程,制定可实现的计划 <ul> <li>eg TED 演讲者分享了一个方法:在年初写"年终总结":今年我完成了 xx 目标,我完成这个目标做的具体步骤,如果写不出来步骤,说明这是无法实现的计划。</li> <li>SMART 法则: <ul> <li>Specific 具体的</li> <li>Measurable 可量化的</li> <li>Attainable 可达到的</li> <li>Relevant 有相关性的(目标之间)</li> <li>Time-bound 有时限的</li> </ul> </li> </ul> </li> <li>紧盯目标,拒绝借口 <ul> <li>选适合自己的学习材料</li> <li>考试学习:把握考纲、教材,将其所有知识点串起来形成知识体系,最好自己可以画出思维导图</li> <li>从一而终,长期、系统性、持续性学习</li> </ul> </li> <li>追求本质:学<strong>基石</strong>之作 <ul> <li>财经作家欧盛在一篇文章中谈道:“任何复杂事物的背后,都有简洁的可以用一句话或者几句话说明的规律。这些规律,便是<strong>本质</strong>。”</li> <li>古希腊哲学家亚里士多德曾说:“在每个系统探索中存在<strong>第一性原理</strong>。第一性原理是基本的命题和假设,不能被省略和删除,也不能被违反。”</li> <li>牛顿只用了三大定律,就解释了日月星辰的旋转、潮汐涨落现象以及各类力学现象;欧几里得只用了几条定理,就解释了万千形状的组合。</li> <li>学基石之作:比如, <ul> <li>你要学经济学,就可以直接看曼昆的《经济学原理》;</li> <li>你要学营销,就可以看“营销教父”菲利普·科特勒的《营销管理》;</li> <li>你要学习管理,最好先看管理学泰斗彼得·德鲁克的《卓有成效的管理者》。</li> </ul> </li> <li>还有一些基石之作,是某一篇<strong>开创这一领域的论文</strong>,例如,“信息论之父”香农在 1948 年 10 月发表于《贝尔系统技术杂志》上的论文:“A Mathematical Theory of Communication”(《通信的数学理论》),就是现代信息论的开端,自此开创了信息论这门伟大的学科。即使几十年过去了,信息论这一领域的研究,核心还是基于他在这篇论文中提出的理论进行展开的。</li> </ul> </li> <li>新知输入,做好"夹心饼":当你学完后,要记得及时复习,这样效果才会更佳,一方面是消灭“假明白”,另一方面是防止遗忘,加深理解。</li> </ul> <h2>2 深度消化,彻底搞懂知识</h2> <ul> <li>培养钝感力:正确处理学习的<strong>挫败感</strong> <ul> <li>日本作家渡边淳一有一本书叫《钝感力》,在这本书中,他提出了“钝感力”这个词。按照渡边淳一自己的解释,“钝感力”可直译为“迟钝的力量”,即<strong>从容面对生活中的挫折和伤痛,坚定地朝着自己的方向前进</strong>,它是“赢得美好生活的手段和智慧”。</li> <li>其实,成功的人几乎都有一个共同的特质,那就是拥有很强的“钝感力”。他们一方面很自信,相信自己可以;但更重要的另一面,他们不在意追求自己目标的路上遇到的困难和打击,哪怕头破血流也要死磕到底。这也印证了中国的一句俗话:“明知山有虎,偏向虎山行。"</li> <li>和“<strong>逃避式学习</strong>”恰恰相反,这是“<strong>不达目的不罢休式的学习</strong>”</li> </ul> </li> <li>无条件自信:破除“畏难情绪”,你就能学懂一切 <ul> <li>我接触的每一个顶级学霸原本都有自己的偏科,有些弱在语文,有些弱在数学,有的弱在其他科目。而且特别有意思的是,很多学霸对自己擅长的科目,并没有什么学习方法,可以说就是有天赋,不用怎么学就能拿高分。这就是他们的优势科目。所以,他们在学习的时候,会把大部分时间放在自己的弱势科目上,最终通过自己的各种办法,把弱势科目的成绩提上来。因此,顶级学霸通常是对自己的弱势科目有学习方法,因为这是他们花了心思,想了办法,最终把成绩提上来的科目。对这些科目的学习,他们是非常有心得的。所以,如果你想求得好的语文、英语的学习方法,你可以去向一个考上清华的理科生请教,他的方法,可能对你来说更有帮助。</li> <li><strong>学霸是哪科不行学哪科,学渣是哪科不行就哪科不学</strong>;学霸是瞄着偏科上,学渣是躲着偏科走。学习成绩差的人之所以不愿学偏科,是因为心中对偏科存有恐惧,从骨子里面接受了自己就是学不好某一科的现实,认定自己这辈子都不可能学好了。或者是想学好,但是觉得自己实在是差得太多,觉得完全无从下手,不可能赶上来了。人一旦被“畏难情绪”左右,就会干脆选择放弃。</li> </ul> </li> <li>精准自查,找出自己的知识漏洞 <ul> <li><strong>承认自己的错误</strong>,可谓是人最难做到的事之一。很多学习能力差的人,并不是真的学习能力差,而是他们不能正视自己学习过程中的问题,选择了掩耳盗铃,从而失去了真正学好的机会。</li> <li>方法 1.源头自查:用清单自测,列出要学的东西,看自己都学会了吗?</li> <li>方法 2.结果自查:按输出物自查,分析考卷、错题、作品</li> <li>方法 3.他人帮测:找高手帮助诊断,找学员尝试教授自己的知识</li> </ul> </li> <li>真正拿下,彻底学懂一切 <ul> <li>72 小时之内开始做 <ul> <li>理财畅销书《小狗钱钱》一书中,讲到了做事的“<strong>72 小时法则</strong>”。书中说:“<strong>当你决定做一件事情的时候,你必须在 72 小时之内真正开始行动,否则你很可能永远不会再做了。</strong>”</li> <li>把已知应用到未知,找知识连接:任何事物的学习都是相通的,当你自查出没有学明白的部分时,你就可以问自己,这部分知识和自己已经掌握的哪些知识有关,是否可以用到这部分知识的学习上。太阳底下没有新鲜事,万事万物都是有联系的,而且很多事物的底层逻辑是相通的,当你用已知的知识去理解新知识时,你就能很快找到突破口,后面的事情,就变得简单了。</li> <li>从哪里开始不重要,开始本身才重要</li> </ul> </li> </ul> </li> <li>深度专注,一次攻克一个难点 <ul> <li>1.要主动探索,而不是被动接受,明确自己的学习目的</li> <li>2.沉下心来,排除一切干扰:每个人在学习时的干扰源是不一样的。你要学会主动屏蔽这些干扰源。具体而言,我认为有“物理隔绝和琐事隔绝”这两种方法。 <ul> <li>物理隔绝:就是在<strong>时间和空间上与干扰源隔开</strong>。比如上文提到的那个喜欢在酒店的房间里工作的朋友,采用的就是空间隔绝;作家郝景芳早起写作采用的就是时间隔绝。</li> <li>琐事隔绝:这是被很多人忽略的,这里我专门提出来。当你要深度专注学习时,那些影响你精力的但又必须要做的琐事,要么让别人帮你做,要么你就干脆不管,比如你担心手机干扰你,干脆把手机放得离你远远的。</li> </ul> </li> <li>3.集中发力,一次解决一个问题:你专注去攻克一个问题时,你能学得深,想得多,学得透</li> </ul> </li> </ul> <h2>3 多元输出,学以致用</h2> <ul> <li>表达型输出,<strong>费曼学习法</strong>的三种应用 <ul> <li>讲给不懂得人听,试图教会他</li> <li>讲给自己听,先讲 录下来 自己再听</li> <li>写给自己看,比语言表述更缜密</li> </ul> </li> <li>解题型输出,高效<strong>刷题</strong>: <ul> <li>刷超出自己舒适区一些范围的题目,不要太难也不要太简单,</li> <li>专题刷题:复习知识-一刷-总结规律-二刷</li> </ul> </li> <li>考试输出,科学抢分 <ul> <li>尝试了解出题人思维:越是大型的考试 出题标准越严格 出题人必须严格按照这些标准来出题,看到一道题要知道这道题想考你什么知识点</li> <li>仔细分析参考答案的结构思路、得分点、学科术语,找出规律,总结答题模板</li> </ul> </li> <li>现实应用,<strong>33 原则</strong> <ul> <li>学会知识后,至少用 3 次</li> <li>抓住本质,举一反三:将知识迁移到其他的 3 个知识点</li> </ul> </li> <li><strong>刻意练习</strong> <ul> <li>刻意练习的三个关键要点:<strong>目标、突破、反馈</strong>:首先确定你想要通过练习达到的目标,在练习的过程中不断突破自己的能力边界,并有导师或教练对你的表现给予反馈,一步步精进,最终达成目标</li> <li>一、有目标的练习:首先要有明确的练习目标,就是你在练习时最终要达到什么样的结果。树立明确的目标,能有效地指导你的练习,也能帮你一步步拆解自己的练习步骤,让你的练习可以落地并最终实现。</li> <li>二、一点点突破能力边界:如果你想让自己在数学考试中考满分,就需要做一些高难度的试题,而不是一直待在舒适区,仅仅去做那些简单的数学题,那样你的数学水平永远都不会提高。</li> <li>三、练习过程中要有反馈。</li> <li>进入“突破 → 练习 → 反馈 → 改进 → 练习”这样的循环中,不断精进自己,最终做到对一件事情的精通。</li> </ul> </li> </ul> <h2>改变学习状态</h2> <ul> <li><strong>找到源动力</strong>,爱上学习:用自己的梦想倒推定计划、梦想可视化 随时提醒自己目标、自我奖励</li> <li>不要迷恋自律,<strong>养成习惯</strong>更重要:任何人的自律都有有限性,养成习惯 利用身体本能 让习惯变成生活的一部分 才更长久可靠。</li> <li><strong>拒绝拖延</strong>:谁都会拖延,不要加大心理压力;用一个小仪式开启任务;《少有人走的路》例子,先难后易</li> </ul> 个人成长https://www.scarsu.com/minimal_learning_method/#post-comment/高效能人士的七个习惯:以原则为核心https://www.scarsu.com/7_habbits/https://www.scarsu.com/7_habbits/树立原则、改变思维、养成习惯;产出与产能的平衡;Sun, 28 May 2023 00:00:00 GMT<h2>来源</h2> <ul> <li>书名:《高效能人士的七个习惯》 (The 7 Habits of Highly Effective People)</li> <li>作者:[美] 史蒂芬·柯维 (Stephen R. Covey)</li> <li>出版时间:2018-5-1</li> <li>ISBN:9787500695356</li> <li>豆瓣链接:https://book.douban.com/subject/5325618/</li> <li>豆瓣评分:8.6⭐</li> </ul> <p><img src="/images/picgo/20230528151746.png" alt="" /></p> <h2>本书的中心思想:以原则为中心从内而外造就自己</h2> <h3>先改变思维方式</h3> <p>我们的思维方式,无论正确与否,是我们的态度与行为的根本。</p> <p>要改变现状,首先要改变自己;要改变自己,先要改变我们对问题的看法。</p> <p>如果一个人无法改变自己的思想构造,就永远无法改变现实,也永远不可能取得进步。</p> <p>比起为改变态度和行为所做出的努力,正确的思维方式对于个人和人际关系效能的影响要大得多。</p> <p>**“思维转换(Paradigm Shift)”**一词由托马斯·库恩(Thomas Kuhn)在他的经典之作《科学革命的结构》(The Structure of Scientific Revolutions)一书中最先提出。库恩在书中阐释:</p> <blockquote> <p>科学研究的每一项重大突破,几乎都是首先打破传统,打破旧思维、旧模式才得以成功。</p> </blockquote> <h3>以原则为中心的思维方式</h3> <p>原则如灯塔,是不容动摇的自然法则。</p> <p>正如塞西尔·B.德米尔(Cecil B.deMille)在他执导的电影《十诫》(The Ten Commandments)中所揭示的:</p> <blockquote> <p>“我们不可能打破法则,只能在违背法则的时候让自己头破血流。”</p> </blockquote> <p>一个人的思维方式越符合原则或自然法则,越能正确而高效的生活。</p> <p>短期的方法与技巧只能治标不治本,应该只关注带来长期效应的自然法则和原则。</p> <h3>循序渐进是成长的自然法则</h3> <p>人的一生包含了许多成长和进步阶段,必须循序渐进。</p> <ul> <li>依赖期</li> <li>独立期</li> <li>互赖期</li> </ul> <p>自然的成长过程不容违背、忽略或缩短,那只会让你平添失望和挫败感。</p> <p>如果学生不肯发问,不肯暴露自己的无知,不肯让老师知道他的真正水平,那么绝对学不到东西,也就不能有长进。而且伪装实非长久之计,总有被拆穿的一天。</p> <p>承认自己的无知往往是求知的第一步。梭罗曾说:“如果我们时时忙着展现自己的知识,将何从忆起成长所需的无知?”</p> <h3>书名中的效能是指什么?</h3> <p>效能在于<strong>产出与产能的平衡</strong>。</p> <p>对于人来说,产能是人的健康、精神状态、思想水平,不能以损害健康为代价去一味的追求"产出",而是要寻求产出与产能的平衡。</p> <p>人的三类资产都要追求产出与产能平衡:</p> <ul> <li>物质资产,急功近利常常会毁掉宝贵的物质资产。保持产出与产能的平衡会帮助你更有效地利用物质资产。</li> <li>金融资产,我们最宝贵的金融资本就是赚钱的能力。如果不能持续投资以增进自己的产能,眼光就会受到局限,只能在现有的职位上踏步。</li> <li>人力资产,一味重视产出会导致糟糕的健康状况、耗损的机器设备、透支的银行存款或破裂的人际关系。</li> </ul> <h3>思想决定行动,行动决定习惯</h3> <p>如上所述,要先养成以原则为中心的思维方式,才能影响到日常的每一个决策和行为,长期一致性的行为最终才能成为习惯。</p> <p>习惯有三个要素,缺一不可:</p> <ul> <li>知识:要知道做什么、为什么做</li> <li>技巧:要知道如何做</li> <li>意愿:想要做</li> </ul> <h2>本书的7个习惯</h2> <p>书中的7个习惯,符合成长规律的三个阶段:依赖期-独立期-互赖期,若下[成熟模式图]所示:</p> <p><img src="/images/picgo/20230528154320.png" alt="成熟模式图" /></p> <h3>“个人领域”的三个习惯:</h3> <ol> <li>积极主动</li> <li>以始为终</li> <li>要事第一</li> </ol> <p>养成这个三个习惯,可以大幅提高你的自信心,你将更能认清自己的本质、内心深处的价值观以及个人独特的才干与能耐。</p> <p>秉持自己的信念而活,就能产生自尊自重与自制力,并且内心平和。</p> <p>你会以内在的价值标准,而不是旁人的好恶或与别人比较的结果,来衡量自己。这时候,事情对错与别人是否发现无关。</p> <h3>“公众领域”的三个习惯:</h3> <ol> <li>双赢思维</li> <li>知己解彼</li> <li>统合综效</li> </ol> <p>当你接受“公众成功”中的三个习惯时,修复和重建破裂的人际关系的意愿和能量将被激发。</p> <p>关系会更上一层楼,变得更加深厚、坚固,历久弥新且经得起考验。</p> <h3>1积极主动</h3> <p>依据原则及价值观行事,而非情绪或外在环境来下决定。</p> <p>为自己过去、现在及未来的行为负责、对自己的人生负责。</p> <p>个人行为取决于自身的抉择,而不是外在的环境。</p> <p>人类应该有营造有利的外在环境的积极性和责任感,养成主动改变环境的观念:对于可控的事情要勇敢改变自己,对于间接可控的事情要共情、施加自己的影响,对于不可控的事情要泰然处之、不被其左右。</p> <p>只有消极的人才会一直紧盯别人的缺点、环境问题、超出自己能力范围的事情不放,作为自己消极行为的挡箭牌,任由"感觉"去左右自己的行为,怨天尤人、装受害者。</p> <h3>2以始为终</h3> <p>要以原则为中心:</p> <ul> <li>养成原则第一的思维方式,即在做决策时要知道什么最重要。</li> <li>只要心中秉持着恒久不变的真理,就能屹立于动荡的环境中。</li> <li>因为一个人的应变能力取决于他对自己的本性、人生目标以及价值观的不变信念。</li> </ul> <p>要自我领导:</p> <ul> <li>明确自己的原则、目标、价值观。</li> <li>以他人为中心的人没有内在的安全感,自我价值变化无常,受制于他人的情绪和行为;人生方向也取决于他人的回应,时时揣摩如何反击;他们的智慧受限于以敌人为中心的偏执心理;毫无力量可言,总是被别人牵着鼻子走。</li> </ul> <p>行动之前先定结果。</p> <p>可以具象的撰写出个人/团队的**【使命宣言】**:自己要成为怎样的人、成就怎样的事、为此奠基需要哪些价值观和原则。</p> <blockquote> <p>休太长的假,看太多的电影或电视,打太多的电子游戏,长期无所事事,都等于浪费生命,无益于增长智慧,激发潜能,增进安全感或指引人生,只不过制造更多的空虚而已。</p> </blockquote> <h3>3要事第一</h3> <p>制定计划,安排优先级。</p> <p>专注于重要的事情:</p> <ul> <li>以目标为导向</li> <li>以原则为中心培养独立意识,服从自我价值观的约束。</li> <li>重要性与目标有关,凡有价值、有利于实现个人目标的就是要事</li> <li>花在第二象限(重要紧急)的时间,回报指数非常高,花在第一象限的时间只能收支平衡</li> </ul> <p>拒绝不重要事情的烦扰:</p> <ul> <li>控制感情、情绪,不被“不重要”的事情干扰</li> <li>如果内心不够坚定,很难拒绝第三、第四象限事务的诱惑</li> <li>花在第三和第四象限(不重要)的时间则是血本无归</li> </ul> <p><img src="/images/picgo/20230528155525.png" alt="" /></p> <p>学会授权</p> <ul> <li>授权是提高效率或效能的秘诀之一,可惜一般人多吝于授权,总觉得不如靠自己更省时省事。</li> <li>授权基本上可以划分成两种类型:指令型授权和责任型授权。</li> <li>责任型授权的关注重点是最终的结果。它给人们自由,允许自行选择做事的具体方法,并为最终的结果负责。</li> </ul> <h3>4双赢思维</h3> <p>与人交往 要基于互敬、寻求互惠的原则。</p> <p>人际关系的本质:</p> <ul> <li>人际关系情感账户中存储的是信任、安全感、礼貌</li> <li>投资情感账户方式:理解倾听、注意小节、信守承诺、明确期望、正值诚信、勇于致歉、无条件的爱心(鼓励个人肯定自我 追求成长)</li> </ul> <blockquote> <p>生活是合作的舞台,而不是一个角斗场</p> </blockquote> <ul> <li>分享更多的机会、财富及资源,避免敌对式竞争。</li> <li>正值诚恳的对待每个人,损人利己、损己利人皆不可取,遇到冲突时要尽量寻求对双方都有利的解决方案,利人也是利己。</li> </ul> <p>与人合作前签订双赢协议:</p> <ol> <li>确认预期目标</li> <li>确立指导方针:实现目标要坚持的原则、方法</li> <li>可用资源:人力、物力</li> <li>建立任何考核标准和时间</li> <li>根据考核制度确认奖惩</li> </ol> <p>举个例子🌰:这个协议看起来很书面化,但是可以应用在生活的方方面面,与任何人合作一件事,都可以按照这个套路来进行事前沟通:</p> <blockquote> <p>咱俩今天在一起做这个事情,目标就是把xx完成,希望我们双方遵循xx原则(尽好职责)做好这件事,可以提供的人力物力资源有xx,需要更多资源可以提出来沟通;如果事情做得好、达到xx标准,有xx奖励,如果谁做的不好、不达标,也有xx惩罚。</p> </blockquote> <h3>5知己解彼</h3> <blockquote> <p>除了物质,人类最大的生存需求源自心理,即被人理解、肯定、认可和欣赏。</p> </blockquote> <p>首先寻求诚心去了解、聆听别人,承认人与人的差异,主动倾听和理解别人的想法,而不是好为人师。</p> <p>学会移情、理解别人:人际沟通有10%靠语言,30%靠语调和声音,60%靠表情和肢体语言。</p> <p>无效沟通的典型例子:</p> <ul> <li>对别人的想法进行价值判断</li> <li>以自己的价值观对别人的隐私追根究底</li> <li>好为人师——以自己的经验提供忠告。</li> <li>自以为是——根据自己的行为与动机衡量别人的行为与动机。</li> </ul> <h3>6统合综效</h3> <p>感知、尊重、利用<strong>差异</strong></p> <ul> <li>判断和尊重人与人之间的差异,取长补短</li> <li>重视不同个体的不同心理、情绪与智能,以及个人眼中所见到的不同世界。</li> <li>缺乏安全感的人总觉得别人要按照他的想法来,殊不知人际交往最可贵的地方就在于有差异、有差异才能互补。</li> </ul> <p>统合综效的基本心态是:如果一位具有相当聪明才智的人跟我意见不同,那么对方的主张必定有我尚未体会的奥妙,值得加以了解。</p> <p>非按照我的方式,亦非遵循你的方式,而是创造第三种更好的办法。</p> <p>最优的沟通方式是大家都对事不对人、坦诚表达观点,为同一个目标集思广益。</p> <h3>7不断更新</h3> <p>不断做重复的工作并不能带来经济上的安全感,拥有财富并不代表经济独立,拥有创造财富的能力才真正可靠。</p> <p>歌德(Goethe)说:</p> <blockquote> <p>“以一个人的现有表现期许之,他不会有所长进。以他的潜能和应有成就期许之,他定能不负所望。”</p> </blockquote> <p>把玩内心兽性的人,早晚会变成真正的野兽;整天弄虚作假的人,终将失去获得真理的权利;暴虐成性的人,头脑的判断力会日益减退。</p> <p>要从四个层面自我提升:</p> <ul> <li>身体(运动 营养 压力调节)</li> <li>精神(价值观 冥想)</li> <li>智力(学习 阅读写作 想象力 规划)</li> <li>社会/情感(理解他人 影响他人 统合综效)。</li> </ul> 个人成长https://www.scarsu.com/7_habbits/#post-comment/月刊#12 | 2022.06-09https://www.scarsu.com/monthly_12_2022_06-09/https://www.scarsu.com/monthly_12_2022_06-09/这篇文章收集了2022年6月-9月之间,我获取到的对我有用的信息,包括:新闻 读书 写作、个人成长 低消费 健康、FIRE生活 财富 技术 前端等等分类。Fri, 23 Sep 2022 00:00:00 GMT<p>💡 <a>点击此链接前往notion查看</a></p> 信息源https://www.scarsu.com/monthly_12_2022_06-09/#post-comment/软技能2:软件开发入门世界观https://www.scarsu.com/software_developer_career_guide/https://www.scarsu.com/software_developer_career_guide/软件开发是什么?软件开发者需要拥有哪些技能?软件开发有哪些方向?软件开发如何求职?Wed, 01 Jun 2022 00:00:00 GMT<h2>来源</h2> <ul> <li>书名:《软技能2:软件开发者职业生涯指南》</li> <li>作者:[美] 约翰·森梅兹</li> <li>出版时间:2020-5-1</li> <li>ISBN:9787115534538</li> <li>豆瓣链接:https://book.douban.com/subject/35043940/</li> <li>豆瓣评分:8.3⭐</li> </ul> <h2>如何学习?</h2> <ul> <li>定目标;</li> <li>搜资源;</li> <li>学-做-复盘;</li> </ul> <h2>软件开发的流程?</h2> <ul> <li>理解问题、收集整理需求</li> <li>设计解决问题的方案、搭建代码架构</li> <li>写代码</li> <li>测试部署</li> </ul> <h2>软件需要哪些技能?</h2> <ul> <li>一门编程语言、数据结构与算法、框架/库/设计模式、数据库基础、源代码控制、调试与测试、构建与部署</li> </ul> <h2>学哪门编程语言?</h2> <ul> <li>考虑当前与未来的就业前景选一门主流语言,一旦你学会了一门编程语言,学习第二门语言就容易多了。</li> </ul> <h2>怎样写简历?</h2> <ul> <li>写清楚专业与技能、做过什么、如何做的、有什么成果</li> <li>针对不同岗位和需求,写不同版本简历</li> </ul> <h2>如何准备面试?</h2> <ul> <li>准备常见面试问题</li> <li>练习编程和问答类型的面试题</li> <li>理清楚自己简历上写的经历</li> </ul> <h2>如何投简历?</h2> <ul> <li>找人脉内推、找猎头推荐、网投</li> </ul> <h2>如何谈薪?</h2> <ul> <li>了解薪资范围、行情,获得一个平均薪资</li> <li>不要直接透露目前薪资,一般公司都要求保密,可以给出整包的范围</li> <li>不要直接透露期望薪资,先了解整体待遇情况,以真实期望薪资+一定比例报价,留出谈判余地</li> <li>至少有一轮还价,要毫不犹豫的还价;最多3轮还价;</li> <li>多谈几份offer</li> </ul> <h2>主流编程语言世界观</h2> <ul> <li>C语言:使用最广,古老强大,可以访问计算机内存和底层部件,面向操作系统、底层硬件、嵌入式</li> <li>C++:C的超集,常与C混用,用于扩展C的对象、类、虚拟函数等特性,广泛用于游戏开发,复杂度高</li> <li>java:年代久远,运行在虚拟机上 虚拟机可以运行在任何平台上,面向对象 语法简洁,不允许直接操作内存和计算机底层</li> <li>python:优雅简洁,用更少的代码来表示更多的语义,适合初学者,正在流行,面向对象、过程式、函数式都可以,解释型语言 无需编译</li> <li>ruby:有趣简单,面向对象的脚本语言</li> <li>javascript:1995起,web领域主流语言,解释型语言无需编译,可以嵌入浏览器执行;10天内创造出的语言 历史遗留问题多,最新的ecmascript已经修改了许多遗留问题;</li> <li>swift:用于新一代ios、osx上的语言,支持许多objective-c的许多特性、比其简洁、易用、灵活</li> <li>go:2007起,google创造的语言,和C一样面向系统,也正在被扩展到web;并发编程,无需考虑内存管理,性能强大;</li> <li>haskell:在学术界受欢迎,纯函数式编程语言+强静态类型系统,可以编写高度可预测的代码,无任何副作用;学习难度大</li> </ul> <h2>主流开发方向世界观</h2> <ul> <li>web开发: <ul> <li>是什么?开发在浏览器中显示与运行的网页</li> <li>特点?跨平台,运行环境、系统、软件类型、版本不可控</li> <li>技术?HTML代码编写网页显式内容、css代码控制内容的样式、javascript代码编写脚本逻辑;</li> <li>原理?浏览器将web代码渲染成网页;网页通过HTTP向服务器发送网络请求 获取数据;</li> </ul> </li> <li>移动端开发: <ul> <li>是什么?开发在移动设备上运行的程序(手机 平板 手表 穿戴设备 车机)</li> <li>特点?规模小,用途聚焦,容易构建,适合自由职业者,最有创业机会</li> <li>技术?ios原生开发用xcode、objective-c、swift;android原生开发用java和android sudio;跨平台开发用Cordova等;移动web开发 以web的形式制作移动程序;</li> </ul> </li> <li>后端开发: <ul> <li>是什么?所有不涉及用户交互界面的开发工作</li> <li>工作内容有哪些?检索、存储、处理数据,遵循&amp;实现业务逻辑,参与构建系统架构、基础设施</li> <li>技术?java php  ruby  .net  等后端语言,SQL语言与数据库</li> </ul> </li> <li>游戏开发: <ul> <li>特点?难度大,竞争激烈,时间金钱投入大,盈利难</li> <li>技术?游戏引擎:unity3d(最主流)、unreal;接近底层硬件的编程语言,以便获取硬件平台的最高性能:C++(最主流);数学知识:矩阵转换、向量运算等图形计算</li> <li>学习方法?复刻大量游戏,由简入难</li> </ul> </li> <li>DBA: <ul> <li>是什么?数据库管理员</li> <li>工作内容有哪些?建立 维护 监控数据库,维护数据库硬件,扩容 资源回收,定期备份与恢复数据库,建立数据库模式(数据库的空白副本),编写存储过程</li> </ul> </li> <li>DevOps: <ul> <li>是什么?开发与运维人员</li> <li>工作内容?创建构建环境 让代码在服务器中部署 运行 测试</li> </ul> </li> </ul> <h2>作为软件开发者,应该掌握的测试知识?</h2> <ul> <li>作为软件开发者,应该有软件测试的知识背景,自测发现问题修复  远比测试人员发现问题提bug修复 节省时间和精力</li> <li>有哪些测试类型? <ul> <li>黑盒测试:把软件本身看作黑匣子,只关心输入输出</li> <li>白盒测试:要了解软件内部的实现,根据代码实现来设计测试用例</li> <li>功能测试:测试系统实际功能</li> <li>验收测试/系统测试:执行一组测试以检验客户的实际需求和期望,针对系统整体运行效果的测试</li> <li>自动化测试:自动执行测试并且验证结果</li> <li>回归测试:验证系统是否按照以前的方式运行,避免新功能破坏现有的功能</li> <li>其他测试:负载、性能、恢复、安全、压力、可用性accessibility</li> </ul> </li> <li>TDD 测试驱动开发是什么?在编写任何代码前,先编写测试用例,将它作为软件应该做什么的规格说明</li> <li>单元测试是什么?编写测试程序,检查代码中"最小内聚单元"</li> </ul> <h2>源代码控制</h2> <ul> <li>是什么?跟踪软件项目里不同版本文件和源代码的方法</li> <li>作用?减少丢失代码的可能性;支持定期备份;多人协同开发;多版本管理;</li> <li>应该掌握的基础知识有哪些?代码库、checkout签出代码、历史版本、分支管理、合并版本merge、版本冲突conflict</li> <li>流行的代码控制工具?git最主流</li> </ul> <h2>CICD</h2> <ul> <li>是什么?自动化构建与持续集成</li> <li>作用?自动化提升效率、缩短反馈周期、改善质量</li> <li>典型工作流?开发者更新代码-CI软件检测到代码更新,触发自动构建,获取最新代码,编译代码 执行静态分析与单元测试-打包程序-部署</li> <li>流行的CI软件:jenkins、hudson、TravisCI、Teamcity、TFS</li> </ul> <h2>调试</h2> <ul> <li>调试是什么?在代码中寻找问题的根源、检验假设</li> <li>如何调试?重现错误,定位问题(查看日志 报错信息,思考可能的原因,验证假设,检查前置条件,分治思想,二分法排查代码,逐步缩小范围)</li> </ul> <h2>代码维护</h2> <ul> <li>在软件生涯中 维护旧代码比编写新代码要花的时间多,因此要学会维护代码</li> <li>目的?避免代码越来越糟;改善现有代码、编写可维护的代码、降低代码熵值</li> <li>如何维护?增强代码可读性,使其简洁、组织清晰,重构代码,在不改变现有功能的前提下,使现有的代码更具有可读性,写好清晰、简洁注释</li> <li>推荐资源?《代码整洁之道》、《代码大全》、《修改代码的艺术》、《重构:改善既有代码》</li> </ul> 个人成长https://www.scarsu.com/software_developer_career_guide/#post-comment/谈判是什么https://www.scarsu.com/negotiation/https://www.scarsu.com/negotiation/谈判,看起来离我们很远,实际上处处存在,是人际交往、谈薪、撕逼、砍价、贸易… 的必备能力。Fri, 27 May 2022 00:00:00 GMT<p><img src="/images/picgo/trade.png" alt="《谈判是什么》" /></p> <h2>简介</h2> <ul> <li>书名:谈判是什么 Everything Is Negotiable</li> <li>作者:(英)盖温.肯尼迪</li> <li>出版时间:2004-10-1</li> <li>ISBN:9787801441881</li> <li>封面:/images/picgo/trade.png</li> <li>豆瓣链接:https://book.douban.com/subject/1038977/</li> <li>豆瓣评分:8.6⭐</li> <li>思维导图:/images/picgo/negotiation.png</li> <li>我的笔记:https://www.scarsu.com/negotiation/</li> </ul> <p>谈判,看起来离我们很远,实际上处处存在,是人际交往、谈薪、撕逼、砍价、贸易… 的必备能力。</p> <h2>处处是谈判</h2> <ul> <li>人在社会生活的本质是价值交换,不论是金钱、物资、劳动力、时间、情感,都属于人与人交换价值的范畴</li> <li>交换的过程,必然会有谈判的存在</li> <li>在人际交往、求职面试、职场工作、生意买卖、国际贸易中,谈判更为重要</li> <li>因此,谈判是生活、工作、人际交往的必备技能</li> </ul> <h2>四种谈判风格</h2> <ul> <li>作者划分了四种谈判风格: <ol> <li>羊(懦弱)</li> <li>驴(蠢)</li> <li>狐(奸猾)</li> <li>枭(冷静正直)</li> </ol> </li> <li>作者主张,应该做枭一样的谈判者:<strong>既不欺压旁人又能取得自己想得到的结果</strong></li> </ul> <h2>谈判的本质是利益交换</h2> <ul> <li>谈判的本质,就是己方与对方的利益交换。</li> <li>谈判的艺术,就在于善于<strong>在“妥协和利益”两者之间取得平衡</strong>。</li> </ul> <h2>谈判前</h2> <ol> <li>强化决心、确定双方的谈判目标、双方的利益、双方的筹码,尤其谨记自己谈判的真正目标、不要被对方带偏</li> <li>做好谈判前准备、<strong>提前收集所有利于谈判的信息</strong>,利用这些信息去讨价还价,做筹码交换</li> </ol> <h2>谈判技巧</h2> <ol> <li>不要接受对方的第一次开价、商品标价:特价不是真的特价、特价只能证明标价的坑人程度</li> <li>己方的第一次开价可以夸张一点,留下足够的<strong>讨价还价的余地</strong>;</li> <li><strong>记牢价格公式</strong>:卖家开价&gt;卖家心理价&gt;卖家底价、买家开价&lt;买家心理价&lt;买家最高价;</li> <li>对方不愿开价:在提出己方开价后,一定要设法<strong>了解到对方的方案</strong>再做进一步的行动。</li> <li>对方否定你的提议:在对方明确提出其解决方案之前,不要另提新建议也不要修改原建议</li> <li>对方要求你让步:礼尚往来、而不是一味退让,记牢<strong>如果句式</strong><code>“如果我方可以获得xx利益,那么我方就能做出xx让步”</code>;善意让步只会让对方得寸进尺。</li> <li>对方问你是否可以砍价:不能直接回答可以,这会直接削弱谈判地位;可以略作思考后回答,我的东西因为xx肯定值这个开价,再反问对方,是否对我提供的东西不满意,让他提出建议</li> <li>对方态度强硬:应该<strong>处变不惊、乐于耐心听取对方的意见并加以充分考虑 但微笑着说不</strong></li> <li>对方威胁、恫吓、胡搅蛮缠、不尊重你:要坚定表现出:无论他怎样胡搅蛮缠,我都绝对不受影响、他绝对达不到目的,除非愿意礼尚往来、各让一步。</li> <li>掌握**谈判的杠杆、谈判的力量:**不要轻易相信对方释放的信息:卖方要避免暴露着急成交的心态和库存货源等信息;买方不要赞扬卖方的产品、可以假装有多方竞争</li> <li>受托策略:我受人所托做这个交易、我无法做出决定、我要去和xx商量、xx说低于这个价格不卖</li> <li>买方<strong>还价策略</strong>千千万:可以用一切于己方不重要 于对方重要的条件,去做利益交换;例如要买3件某款玩具,有标价,应该:先问有没有特价、再问买两件多少钱、再问买三件多少钱;例如在商店东西,售货员说无权打折,可以要求找经理谈;搭上附件,我才买;按这个价得白送一个赠品;如果总从你这里订货,可打多少折扣? 我是新(老)客户,作为见面礼(为了老交情)你总得打点折扣才是。;要是付现金打多少折扣?如果我答应向别人推荐你的产品,卖给我的能不能打点折扣? 你要是有权给我优惠,我马上就下订单。</li> <li>卖方<strong>提价策略</strong>也有千千万:不要轻易在价格上让步,而是考虑价格之外的<strong>其他因素:<strong>不要把注意力集中于</strong>价格的数目</strong>上而要放在**其提出的“形式”**上,“<strong>这种包装是这个价,那种包装是另一个价</strong>。”</li> <li>适时变通,遇到互不让步的问题,可以换其他更细节/更抽象的问题讨论</li> </ol> <h2>谈判后</h2> <p>合同一定要具体、要考虑到一切不可控的情况、及其处理方案。</p> <p>墨菲定律告诉我们:“越是坏事越易出现”。</p> <p>因此<strong>不要存有侥幸心理</strong></p> 个人成长https://www.scarsu.com/negotiation/#post-comment/月刊#11 | 2022.05https://www.scarsu.com/monthly_11_2022_05/https://www.scarsu.com/monthly_11_2022_05/这篇文章收集了2022年5月,我获取到的对我有用的信息,包括:新闻 读书 写作、个人成长 低消费 健康、FIRE生活 财富 技术 前端等等分类。Mon, 23 May 2022 00:00:00 GMT<p>&lt;aside&gt;</p> <p>💡 <a>信息源分类整理 | 往期合集 | 持续更新</a></p> <p>带⭐标的是我精选出来、推荐你阅读的信息</p> <p>&lt;/aside&gt;</p> <h3>提升认知:信息输入、知识管理🧠</h3> <ul> <li>⭐认知 | <a>如何从底层杀出 / 人生翻盘指南 - 知乎</a>、<a>思维导图</a></li> <li>新闻 - <a>宇宙可能停止膨胀开始收缩</a></li> <li>新闻 - <a>科学家警告称海洋开始失去记忆</a>:稳定的海洋环境正变得更加不可预测和不稳定</li> <li>新闻 - <a>全球陷粮荒危机</a> | solidot</li> <li>新闻 - <a>美的内部电话会曝光,董事长方洪波:未来三年是前所未有的行业寒冬</a></li> <li>写作 | <a>写作最大的理由应该是,我们通过写作认识自己</a></li> <li>写作 | <a>作家和评论家YanYi给的写作建议</a></li> <li>读书 | <a>如何消化超出你“水平”的书籍并提高你的智力</a> - Medium</li> <li>读书 | <a>《原子习惯》</a>:习惯是“自我完善的复利”</li> <li>⭐读书 | <a>《内在动机》</a>:内在动机由三个要素组成: 自主(听听自己内心的声音)、 胜任(在自己舒适区边缘探索)、 联结(认识我与这个世界的关系)</li> <li>读书 | <a>什么时候是读哲学的好时候?</a> | 澎湃:赵林在《西方哲学史演讲录》中提出,当人们普遍处于亢奋的发展和拼搏状态时,哲学完全是一种累赘的文化奢侈品,而正是在人们开始转向“内卷”或者“躺平”状态时,哲学才成为一种排遣无奈和无聊、给人以精神慰藉的刚需。</li> <li>纪录片 | <a>《秃然发生》</a>:全国首档关注男性脱发的纪录片, 至今已有超过2700万观众收看</li> </ul> <h3>提升体验:身心舒适、自律极简😃</h3> <ul> <li>⭐成长 | <a>是什么让人们看上去很无聊,以及这如何影响到我们对于无聊的人的认识 - 36Kr</a></li> <li>低消费 | ****<a>年轻人如何远离消费主义陷阱?</a>****资本最擅长的三件事:一、凭空制造需求。二、用消费品划分社会层级结构。三、设法加快你的消耗速度。</li> <li>⭐健康 | <a>蔬菜水果的营养量在下降 - 奇客Solidot</a></li> <li>健康 | <a>身体健康百病不侵,ICU 医生助你抢鲜了解《中国居民膳食指南(2022)》 - 少数派</a></li> <li>饮食 | 为什么炸食物要炸两遍:低温炸熟炸透食物、高温脱水酥脆</li> <li>教育 | <a>教育部要求9月起中小学生要学煮饭</a></li> <li>生活 | <a>量化家务分工的模式</a></li> <li>人际关系 | <a>和父母最好的相处模式什么样的? - one</a></li> </ul> <h3>提升物质:专业技能、工作投资💹</h3> <ul> <li> <p>⭐财富 | <a>FIRE生活</a>:“低配版”财富自由 = 攒年支出*25的启动资金 + 每年4%的理财收益 + 辞职、恢复自由身、低物欲低消费生活;FIRE生活只是不工作了,把自己的时间完全交给爱好和其他更有价值的事情;“FIRE有两个好处,一个是如果把它作为一个奋斗目标,那就有盼头了。还有就是FIRE的重点不在于财富,而是在于自由。”</p> </li> <li> <p>财富 | <a>个人财富的六个层级 - 36Kr</a> ( <a>英文原文</a> 、<a>信息源Personal Finance Principles网站</a></p> </li> <li> <p>财富 | 拥有多少钱才能实现财富自由?100w年收益4%,月均利息收入3333¥</p> </li> <li> <p>市场 | *<strong>*<a>用「乐高」思维做成的产品是什么样的?Notion 和他的 GTM 策略</a>**</strong></p> </li> <li> <p>行业 | 这个“五一“假期,有草地的地方就有帐篷,<a>露营之后火什么?</a>:家庭园艺消费市场、舞台剧 话剧 脱口秀等演艺市场(中产阶级所追求的精致是一种生活的美好,但并不是奢侈的享受。)</p> </li> <li> <p>行业 | <a>谈谈我对 web 3.0 的看法 - 掘金</a>:web 1.0 与 web 2.0 数据中心话,存储在平台的服务器、web 3.0 数据去中心化,不受平台拥有,存储在某些去中心化的应用里面</p> </li> <li> <p>职业 | <a>真实的公务员世界</a></p> </li> <li> <p>职业 | <a>陪诊师、跑腿业务</a></p> </li> <li> <p>网络 | <a>计算机网络常用知识总结 - 掘金</a></p> </li> <li> <p>低代码 | <a>电商系统 低代码 开源项目</a></p> </li> <li> <p>低代码 | 阿里开源<a>LowCodeEngine、</a><a>demo地址</a></p> </li> <li> <p>技术 | <a>线上突然出 bug 怎么找? - V2EX</a></p> </li> <li> <p>前端 | <a>开源wx小程序</a></p> </li> <li> <p>前端 | <a>JavaScript 框架的四个时代 - pzuraq | blog</a></p> </li> <li> <p>前端 | <a>Building a JavaScript Bundler - Christoph Nakazawa</a></p> </li> <li> <p>前端 | <a>掘金 5.11 月影 贺师俊 最新JS标准&amp;ES2022直播回放</a></p> </li> <li> <p>前端 | <a>纯CSS实现 3D slinky效果</a> <img src="https://i0.wp.com/css-tricks.com/wp-content/uploads/2022/05/giphy.gif?resize=500%2C375&amp;ssl=1" alt="https://i0.wp.com/css-tricks.com/wp-content/uploads/2022/05/giphy.gif?resize=500%2C375&amp;ssl=1" /></p> </li> <li> <p>前端 | <a>使用CSS text-shadow实现复杂的hover效果</a></p> </li> <li> <p>前端 | <a>微前端架构</a> - Medium</p> </li> <li> <p>前端 | <a>我是高级前端开发人员吗?</a> - Medium</p> </li> <li> <p>前端 | <a>专业人士如何处理 JavaScript Promise</a> - Medium</p> </li> <li> <p>前端 | <a>前端埋点方案</a></p> </li> </ul> 信息源https://www.scarsu.com/monthly_11_2022_05/#post-comment/月刊#10 | 2022.04https://www.scarsu.com/monthly_10_2022_04/https://www.scarsu.com/monthly_10_2022_04/这篇文章收集了我2022年4月获取到的对我有用的信息,包括:信息源 书籍 播客、工具、健康 疫情 时间管理、职场 技术 前端等等分类。Thu, 28 Apr 2022 00:00:00 GMT<p>💡 <a>信息源分类整理 | 往期合集 | 持续更新</a></p> <hr /> <h3>提升认知:信息输入、知识管理🧠</h3> <ul> <li>新闻 | <a>中国网络媒体抖音、头条、小红书先后宣布拟展示帐号IP属地</a>:更真实有序的网络言论氛围</li> <li>信息源 | 反复推荐过多次的happy xiao的博客改了域名:<a>coke.do - 简短实用的效率方法,健康习惯,思维模式</a>,每周都会分享一些好的想法、信息</li> <li>信息源 | <a>博客TA :Total Annarchy</a> - 华尔街日报畅销书作者ANN HANDLEY的无政府主义博客,关于写作、营销</li> <li>信息源 | <a>国家智慧教育平台</a>:中小学、职业教育、高等教育 免费高质量资源</li> <li>书籍 | <a>《乌合之众》</a>+<a>《娱乐至死》</a>+<a>《美丽新世界》</a>+<a>《1984》</a>四本结合看:“媒体是现代社会的独裁者”、”人一到群体中,智商就严重降低”</li> <li>书籍 | <a>《纳瓦尔宝典:财富和幸福指南》</a></li> <li>书籍 | <a>《大国空巢:反思中国计划生育政策》</a>:了解中国社会人口、老龄化现状</li> <li>播客 | 知晓有我:从女性视角出发探讨社会现象(小宇宙App可听</li> <li>播客 | 霞光里FM:《三联生活周刊》出品(小宇宙App可听</li> <li>播客 | 螺丝在拧紧:单向空间出品(小宇宙App可听</li> <li>播客 | 随机波动:三位女性媒体人的一档泛文化播客(小宇宙App可听</li> <li>播客 | 放学以后:探寻日常生活之外的可能性(小宇宙App可听</li> <li>播客 | 故事FM:真实的女性故事自有万钧之力(小宇宙App可听</li> <li>话题 | <a>人生唯一确定的就是不确定的人生 - 罗翔</a></li> <li>话题 | <a>道法术器</a>:学校就是打造社会工具的地方、“有时候有些观念知识不是你真正需要的,而是这个世界少数掌握话语权的人想要你知道的,但这不一定是真相”</li> <li>话题 | 言论自由:<a>李敖2005年北京大学演讲</a></li> <li>话题 | <a>怎样让别人觉得自己很靠谱?</a>:明确能力边界、帮助对方明确任务的规划和想法、不要完美主义,先把事情做出去、学会邀功</li> <li>想法 | 新闻自由是灾难最大的救助者</li> <li>想法 | 尊重他人命运,放下助人情节、你的建议如果唤不起别人的改变,那不如说句好话结个善缘、禁止🈲好为人师</li> <li>想法 | <a>弱者如何以小博大</a>:1.快,先起步。2.差异化</li> <li>想法 | <a>谈判前要包装自己</a>:要懂得给自己造势</li> <li>想法 | <a>表达、抓逻辑漏洞、不要被挑起情绪、不要陷于对攻击自己的无关的问题的辩解之中</a></li> </ul> <h3>提升效率:用 好工具、用好 工具🔨</h3> <ul> <li>工具 | <a>Auto.js</a>:Android平台上支持Node.js的JavaScript自动化工具</li> <li>工具 | <a>Parsec</a>:轻量级、即开即用的远程连接工具</li> <li>工具 | <a>Thud</a>:一款用ionic+angular开发的、开源、无广告的Android 新闻 App</li> <li>工具 | <a>叮咚抢菜-派送时段监听及推送工具</a></li> </ul> <h3>提升体验:身心舒适、自律极简😃</h3> <ul> <li>健康 | 据<a>《柳叶刀》医学期刊</a>称,步行几乎对身体内所有的细胞都有好处;能够带来益处的步数大约是 7000步(老年人) - 9000 步(年轻人),超过推荐的次数后,死亡风险就不再降低。</li> <li>健康 | <a>在线问诊平台横评</a>:当下的在线问诊平台是资本的大饼</li> <li>健康 | <a>程序员延寿指南</a>:稳健的活得更久、降低66.67%全因死亡率</li> <li>疫情 | <a>“躺平”抗疫</a>维护的是既得利益者的财产,牺牲的是大众以及弱势群体的健康、甚至生命,而我们这些普通人,早晚一天都是弱势群体的一员。</li> <li>疫情 | <a>首批新冠感染幸存者</a>:每一天看似平淡的生活,其实都是最大的幸福。</li> <li>心理学 | <a>自卑的本质 - one</a>:接受自己的不好、承认问题的难度、想办法解决问题</li> <li>心理学 | <a>如何提高情绪阈值</a>:避免悲观 即刻努力、放大心胸 面向未来、持续学习 保持健康</li> <li>生活 | 在线小工具:<a>选择食材 ⇒ 推荐食谱</a></li> <li>游戏 | <a>汉兜</a> 、<a>词影</a>:国内版Wordle(在国外大火的游戏),玩家有十次机会猜一个四字词语(一般是常见成语)。每次猜测后,通过拼音、音调和汉字的颜色标识与答案的区别。</li> <li>环保 | <a>科学家在活人血液以及肺部发现塑料微粒</a>,/样本取自 13 名接受手术的患者的组织,其中 11 例发现了微塑料。最常见的是用于塑料包装和吸管的聚丙烯,以及用于瓶子的 PET。这些颗粒可以在人体内传播,并且可能滞留在器官中。</li> <li>时间管理 | <a>如何高效利用下班后的时间?- 少数派</a>:**可用时间 = 24 小时 - 工作时间 - 通勤时间 - 休息时间 - 花在必要事项上的时间:**从 996 的工作换到 965;搬到离公司更近的地方;从社交网络抽离;提升睡眠效率减少睡眠时间;</li> </ul> <h3>提升物质:专业技能、工作投资💹</h3> <ul> <li>自媒体 | 写作技巧:尽可能写的更具体 - 文案大师 <a>Ann Handley 的邮件</a></li> <li>商业 | 美剧<a>《亿万》</a>金融、财富、信息差:财富的本质就是洞察力的变现</li> <li>商业 | <a>微软是如何做到市值$10T的</a>:2000 年代的 Windows 公司,2010 年代成为 Office 公司,并正在成为 2020 年代的云公司</li> <li>商业 | <a>金融战历史</a>:”不创造财富,也不以土地占领为目标,而是依仗资本实力建立各色武装实力去偷猎、围猎他国财富,其实都属广义金融战范畴,与当今更加隐秘、更加高超的金融战异曲同工,不过是时代不同、表象不同而已。“</li> <li>行业 | IC Insights 的数据显示,2021 年中国占了全球半导体市场份额的 <a>4%</a>,美国占据了一半以上的份额。</li> <li>职业 | **<a>Topworker跨境客</a>:**全国最大的、优质的跨境自由职业者社群</li> <li>职业 | <a>Toptal</a>: 全球精英自由职业者平台(需要英语好</li> <li>职业 | <a>TalentOrg</a>:互联网行业的远程工作社区(不需要有好的英文能力也可以胜任,招聘多语言产品经理</li> <li>职业 | <a>前端私活</a></li> <li>求职 | <a>Show Me Bug</a>:技术面试的云端IDE,提供实时共享的编程环境</li> <li>求职 | <a>如何判断一个求职者的职业水平</a>:反向思考自己如何提升求职成功率</li> <li>技术 | Nginx替代方案:<a>Caddy2</a> 开源 自动化https 比nginx配置简单</li> <li>技术 | <a>22种设计模式目录</a></li> <li>前端 | 前端架构:<a>前端架构设计模式</a></li> <li>前端 | 前端架构:<a>前端代码的三种设计模式</a>:组件模式、compose组合模式、<strong>Membrane模式</strong></li> <li>前端 | 项目管理:<a>从零到一建立前端规范</a></li> <li>前端 | 性能优化:<a>webpack优化</a></li> <li>前端 | 性能优化:<a>虚拟列表</a></li> <li>前端 | 性能优化:<a>得物团队H5秒开优化</a></li> <li>前端 | 补齐知识体系:React知识点<a>脑图</a></li> <li>前端 | 补齐知识体系:<a>ajax fetch axios区别</a></li> <li>前端 | 补齐知识体系:<a>分析HTTP TCP区别</a></li> <li>前端 | 补齐知识体系:CSS <a>calc()函数</a>,可以计算 长度值、角度、时间、百分比、数值</li> <li>前端 | 补齐知识体系:css3 animation暂停/恢复:<code>animation-play-state: paused/running;</code></li> <li>前端 | 补齐知识体系:<a>CSS Functions脑图</a></li> <li>前端 | 补齐知识体系:5个好用的现代JS特性 <ul> <li>用<code>Object.hasOwn()</code>代替<code>key in obj</code>(包含原型链)和<code>obj.hasOwnProperty</code>(对于非obj容易报错)</li> <li>用<code>#</code>声明私有属性</li> <li>数字分隔符<code>6000_000_000</code></li> <li>用<code>?.</code>简化&amp;&amp;和三元运算符 <ol> <li><code>obj?.prop</code> 对象属性</li> <li><code>obj?.[expr]</code> 对象/数组属性</li> <li><code>func?.(...args)</code> 执行函数</li> </ol> </li> </ul> </li> <li>前端 | 学习借鉴:<a>年包70w+的前端技术专家offer是如何拿到的</a></li> <li>前端 | 开发工具:<a>Javascript运算符搜索引擎</a></li> <li>前端 | ECMAScript新提案:通过复制更改数组,提案了四个新的数组方法<code>.toReversed()</code>、<code>.toSorted()</code>、<code>.toSpliced()</code>、<code>.with()</code>,前三种方法相对应的原始方法.reverse() .sort() .splice() 均会更改原数组,<code>.with(index, value)</code>方法替换了原始的修改数组元素的方式<code>arr[index]=value</code></li> <li>前端 | ECMAScript新提案:<a>类型注解(TypeScript 在未来可能被纳入 ECMAScript 中)</a></li> <li>前端 | 函数式编程:<a>函数组合compose、管道符、pipe函数</a></li> <li>前端 | 实际场景与方案:<a>Vue API 统一管理</a></li> <li>前端 | 实际场景与方案:用<a>责任链模式</a>解决一系列校验问题、避免大量<code>if、else</code></li> <li>前端 | 实际场景与方案:<a>前端常见实际问题&amp;解决方案</a></li> <li>前端 | 项目实例:<a>koa2+vite+ts+vue3+pinia前端SSR项目</a></li> <li>前端 | 项目实例:<a>Angular 13 Example App + Angular CLI + i18n + GraphQL + TypeScript</a></li> </ul> 信息源https://www.scarsu.com/monthly_10_2022_04/#post-comment/纯CSS实现无限循环轮播https://www.scarsu.com/infinite_scroll_by_css/https://www.scarsu.com/infinite_scroll_by_css/无JS代码实现无限循环轮播、鼠标悬浮时暂停动画、鼠标移出时继续动画Fri, 22 Apr 2022 00:00:00 GMT<h2>原理</h2> <p><img src="/images/picgo/infinite-scroll.png" alt="原理" /></p> <h2>demo代码</h2> <p>html</p> <pre><code>&lt;div class="wrap"&gt; &lt;div class="slide-dom"&gt; &lt;div class="itemA"&gt;A&lt;/div&gt; &lt;div class="itemB"&gt;B&lt;/div&gt; &lt;div class="itemA"&gt;A&lt;/div&gt; &lt;div class="itemB"&gt;B&lt;/div&gt; &lt;/div&gt; &lt;/div&gt; </code></pre> <p>css</p> <pre><code>@keyframes infinite-slide { 0% { transform: translateX(0); } 100% { transform: translateX(-50%); } } .wrap { overflow-x: visible; background: #eee; width: 200px; height: 300px; margin: 0 auto; padding: 100px 0; } .slide-dom { width: max-content; animation: infinite-slide 10s linear infinite; } /* 鼠标悬浮时暂停动画 */ .slide-dom:hover { animation-play-state: paused; } .itemA { display: inline-block; width: 200px; height: 100px; background: pink; } .itemB { display: inline-block; width: 200px; height: 100px; background: yellow; } </code></pre> <h2>效果</h2> <p><a>demo在线地址</a></p> <p><img src="/images/picgo/demo.gif" alt="preview" /></p> 前端https://www.scarsu.com/infinite_scroll_by_css/#post-comment/前端字体性能优化https://www.scarsu.com/web_font_optimize/https://www.scarsu.com/web_font_optimize/字体文件过大、FIOT(flash of invisible text)字体闪现问题Mon, 11 Apr 2022 00:00:00 GMT<h2>问题1:字体文件过大,解决方案:<code>Fontmin - 字体子集化</code></h2> <h3>介绍</h3> <p>Fontmin是一个纯JS字体子集化方案,用于压缩字体文件。</p> <p>依赖node环境。</p> <p>其原理是扫描项目中的文字,将用到的字从字体文件中单独拿出来组成一个子集字体文件。</p> <p>可以达到大幅度减小字体文件尺寸的效果。</p> <h3>相关资源</h3> <ul> <li><a>Fontmin官网</a></li> <li><a>开源仓库</a></li> <li><a>文档</a></li> </ul> <h3>安装</h3> <pre><code>npm install --save-dev fontmin </code></pre> <h3>使用</h3> <pre><code>const fs = require("fs"); const Fontmin = require("fontmin"); //扫描文件目录 const scanFolder = (dir, done) =&gt; { let results = []; fs.readdir(dir, (err, list) =&gt; { if (err) { return done(err); } let i = 0; (function iter() { let file = list[i++]; if (!file) { return done(null, results); } file = dir + "/" + file; fs.stat(file, (err, stat) =&gt; { if (stat &amp;&amp; stat.isDirectory()) { scanFolder(file, (err, res) =&gt; { results = results.concat(res); iter(); }); } else { results.push(file); iter(); } }); })(); }); }; //Fontmin根据文字内容生成压缩后的字体子集 const generateFinalHTML = (finalString) =&gt; { const fontmin = new Fontmin() .src('static/fonts/*.ttf') // 需要压缩的所有字体文件 .dest('static/fonts/') // 压缩后文件存储路径 .use( Fontmin.glyph({ text: finalString, hinting: false, }) ) .use( Fontmin.ttf2woff({ deflate: true, }) ); fontmin.run((err) =&gt; { if (err) { throw err; } }); }; //获取目录下所有文件的文字内容 scanFolder("dist", (n, results) =&gt; { let set = new Set(); results.forEach((file) =&gt; { const result = fs.readFileSync(file, "utf8"); const currentSet = new Set(result); set = new Set([...set, ...currentSet]); }); generateFinalHTML(Array.from(set).join("")); }); </code></pre> <h2>问题2:FOIT(Flash of Invisible Text )字体闪现问题</h2> <h3>问题描述</h3> <p>浏览器在加载字体时,默认不展示文本内容,在现代浏览器中,FOIT会导致这种现象出现至多3秒。</p> <p>如果有文字混搭(有的字体需要加载,有的字体不需要)那么用户可能就会发现“网页只显示部分字体”的情况,用户体验很差。</p> <h3>解决步骤1:<code>font-display:swap</code> :未加载到字体时,优先显示替代字体,而不是空白(<a>MDN文档</a>)。</h3> <p><code>font-display</code>属性决定了一个@font-face在不同的下载时间和可用时间下是如何展示的。</p> <pre><code>@ font-face { font-family: ExampleFont; src: url(/path/to/fonts/examplefont.woff)format('woff'), url(/path/to/fonts/examplefont.eot)format('eot'); font-weight: 400; font-style: normal; font-display: fallback; } </code></pre> <h3>解决步骤2:<code>preload</code>:预加载字体文件,提前加载字体。</h3> <pre><code>&lt;link rel="preload" type="font/woff" href="/fonturl" as="font" crossorigin="true"&gt; </code></pre> <h3>解决步骤3:<code>document.fonts.ready</code> <a>接口</a>:浏览器处理完成字体加载后的回调(加载成功或者失败都会触发回调)</h3> <pre><code>document.fonts.ready.then(() =&gt; { // 字体加载完成后的逻辑 this.fontLoaded = true; }); </code></pre> 前端https://www.scarsu.com/web_font_optimize/#post-comment/月刊#9 | 2022.03https://www.scarsu.com/monthly_9_2022_03/https://www.scarsu.com/monthly_9_2022_03/提升格局的纪录片、工具、前端、女性觉醒Thu, 31 Mar 2022 00:00:00 GMT<p>💡 <a>信息源分类整理 | 往期合集 | 持续更新</a></p> <hr /> <h3>提升认知:信息输入、知识管理🧠</h3> <ul> <li>话题 | <a>迄今为止看到的 对女性最诚挚的祝福</a></li> <li>书籍推荐 | <a>女性主义入门书《成为波伏瓦》</a>:“有伦理的爱情必须是对等而互惠的,爱人与被爱的人都必须有意识,是自由的,努力拥抱彼此生活中的价值所在。而且,当他们的爱涉及性时,他们都必须是性的主体,而不是客体。”</li> <li>纪录片 | <a>天地玄黄 (豆瓣)</a>:从远古到现在,从猿猴到人类,从荒无人烟的沙漠到震撼人心的宗教活动现场,从广袤天地带来的感动到婴孩单纯的笑脸给予的幸福,<strong>祝福与我们共同存在在这颗蔚蓝地球上的一切</strong></li> <li>纪录片 | <a>积极心理学 (豆瓣)</a>:哈佛幸福课,幸福感是衡量人生的唯一标准,是所有目标的最终目标</li> <li>纪录片 | <a>地球脉动 - 电影 - 豆瓣搜索</a>:BBC纪录片,从南极到北极,从赤道到寒带,从非洲草原到热带雨林,再从荒凉峰顶到深邃大海,难以数计的生物以极其绝美的身姿呈现在世人面前。</li> <li>纪录片 | <a>但是还有书籍 (豆瓣)、</a><a>但是还有书籍 第二季 (豆瓣)</a>:在阅读多样化、碎片化的当下,记录这个时代形形色色的爱书之人,捕捉和书有关的那些精彩故事</li> <li>纪录片 | <a>人生第一次 (豆瓣)</a>:央视网系列人文纪录片《人生第一次》旨在通过蹲守拍摄,观察不同人群在人生重要节点的“第一次”:第一次上学、第一次上班、第一次走进军营,许多“第一次”串联起我们人生的重要节点,“初来乍到,请多关照”。</li> <li>纪录片 | <a>人生七年 - 电影 - 豆瓣搜索</a>:采访来自英国不同阶层的十四个七岁的小孩子,他们有的来自孤儿院有的是上层社会的小孩。此后每隔七年,艾普特都会重新采访当年的这些孩子,倾听他们的梦想,畅谈他们的生活。人生的轮回从这十四个七岁的孩子真实生活开始,他们天真无邪的脸上写满对生活的憧憬和渴望。<strong>“七岁看老”</strong>,在这童言无忌的问与答中,人生七年又七年,震撼上演。(截至2022年,从7UP,到63UP,已经拍摄了9部)</li> <li>纪录片 | <a>女人 Woman(豆瓣)</a>:走访50个国家,纪录2000名女性对自己的评价,构成了一幅巨大且撼动心灵的女性“自画像”。</li> </ul> <h3>提升效率:用 好工具、用好 工具🔨</h3> <ul> <li>工具 | <a>WIS微思博客</a>:多款在线智能工具、自定义地图空间可视化工具</li> <li>工具 | <a>超级简历</a>:免费 快速创建简历、海量模板</li> <li>工具 | <a>Tunefind</a>:电影和电视音乐查询网</li> <li>工具 | <a>zlibrary</a>:免费 电子书 搜索 下载</li> <li>工具 | <a>slidesgo</a>:海量 免费 PPT资源 下载</li> <li>工具 | <a>古诗文网</a>:古诗文经典传承</li> <li>工具 | <a>all to all</a>:在线 文档音视频图片 格式转换</li> </ul> <h3>提升物质:专业技能、工作投资💹</h3> <ul> <li>前端 | 一个Canvas3D动效<a>网页</a>案例</li> <li>前端 | <a>docx to html在线转换网站</a>(常用于网站隐私政策、用户协议等页面)</li> <li>行业 | <a>2022年的互联网行业</a></li> </ul> 信息源https://www.scarsu.com/monthly_9_2022_03/#post-comment/黄金投资新时代:黄金是永恒的硬通货https://www.scarsu.com/gold/https://www.scarsu.com/gold/本书作者的两个重点:1.国际货币市场不久会崩溃;2.作者建议投资者趁早配置10%的流动资产投资实物黄金或者实物黄金基金。Wed, 30 Mar 2022 00:00:00 GMT<h2>简介</h2> <p><img src="/images/picgo/20230709103730.png" alt="《黄金投资新时代》" /></p> <ul> <li>书名:黄金投资新时代</li> <li>原作名: The New Case for Gold</li> <li>作者:[美]詹姆斯·里卡兹 James Rickards</li> <li>译者:许余洁 吴海军</li> <li>出版时间:2016年4月</li> <li>ISBN:9787508693743</li> <li>封面:/images/picgo/20220331171131.png</li> <li>豆瓣链接:https://book.douban.com/subject/30353151/</li> <li>Amazon链接:https://www.amazon.com/New-Case-Gold-James-Rickards/dp/1101980761/</li> <li>思维导图:/images/picgo/20220331171755.png</li> </ul> <p>《黄金投资新时代》一书深入浅出地论述了黄金即货币的观点:当货币秩序紊乱时,黄金将起到重要的作用,即使并非单纯的定锚作用,也是重建货币体系中各国谈判的重要筹码。</p> <p>作者梳理历史,发现在面临国际货币体系失序和复杂的金融市场时,黄金的表现仍然非常稳健,拥有黄金是抵御当前经济环境和不稳定货币体系的保险和保障。</p> <h2>黄金即货币</h2> <h3>黄金是人类共识的财富资本</h3> <p>黄金是唯一具有作为货币所需的全部必要特性(稀缺性、延展性、惰性、耐用性和均匀性)的元素,可以作为可靠并且实用的价值贮藏物。</p> <p>黄金的历史1:18世纪经典的金币<strong>金本位</strong>在英国诞生以来,英镑、美元等信用货币先后依靠黄金的天然信用成为世界货币,黄金成为社会财富价值标准。</p> <p><img src="/images/picgo/20220401142123.png" alt="金本位" /></p> <p>黄金的历史2:二战即将结束时,多国遭受重创,金融和货币体系皆处于崩溃边缘。然而,美国却成为这次战争的最大受益者。大量黄金流入,令美国当时拥有世界黄金总储备量的大约75%。</p> <p>为了加强各国经贸合作,重建国际货币秩序,1944年7月,美国邀请44国政府代表共同确立了<strong>布雷顿森林体系</strong>:规定美元与黄金挂钩,<strong>每35美元兑换1盎司黄金</strong>,其他国家的货币与美元挂钩,只能通过美元同黄金发生联系。美元因此成为了国际货币体系的中心。</p> <p><img src="/images/picgo/20220401142259.png" alt="布雷顿森林体系" /></p> <p>黄金的历史3:19世纪末,美国关闭黄金与美元挂钩的窗口,把“黄金无用论”推上了巅峰。</p> <p>黄金的历史4:2008年国际金融危机以来,关注黄金又成为世界资本市场上的潮流。俄罗斯等多国央行增储黄金。</p> <p><img src="/images/picgo/20220401104259.png" alt="全球黄金储备分布" /></p> <p>图片来自<a>WGC-世界黄金协会</a>,在图中可以看到,全球黄金总储存量约19万吨,其中:</p> <ul> <li>黄金首饰约9万吨</li> <li>私人投资金约4万吨</li> <li>各国央行官方储备金约3.5万吨</li> <li>其余黄金约2.6万吨</li> </ul> <p>由金本位制度、到美元-黄金的布雷顿森林体系,到“非货币化”,再到当下社会对黄金的重视,足以说明:<strong>30多年来的黄金非货币化其实是人类的一次试错过程。</strong></p> <p>如今,包括美元在内的世界范围内的<strong>信用货币的信任危机</strong>在不断加深。黄金已经进入一个新的价值(价格)重估阶段。</p> <h3>黄金是“M小于0”(M-Subzero)货币</h3> <p>货币由3部分组成:交易的媒介、价值的储存和记账的单位。</p> <p>从技术层面讨论关于广义或者狭义的货币供应,如M3、M2、M1、M0等范畴。</p> <ul> <li>M0(货币)= 流通中的现金,M0也被称为“基础货币”,即流通于银行体系之外的现金(消费、终端市场</li> <li>M1(狭义货币)= M0 + 企业活期存款(现实购买力</li> <li>M2(广义货币) = M1 + 准货币(居民储蓄款 + 定期存款 + 其他存款)(投资和中间市场</li> <li>M3 = M2 + 金融债券 + 商业票据 + 大额可转让定期存单等</li> </ul> <p>作者把黄金称为“M小于0”(M-Subzero),因为<strong>即使经济学家们不予认可,黄金也是纸币背后真正的基础货币</strong>。</p> <h3>美联储不愿承认的事实:美元依赖黄金</h3> <p>“美联储”一般是指联邦储备银行体系,由12个独立的地区性联邦储备银行组成,每个银行都由该地区的私人银行所拥有。</p> <p>如果只考虑美联储的证券投资组合,美联储在2013年已濒临破产:</p> <ul> <li>表面上看,美联储并没有破产和资不抵债。在撰写本书时,美联储的资产负债表显示总资产约为4.49万亿美元,总负债约为4.45万亿美元,总资本(资产减负债)约为400亿美元。</li> <li>但是,美联储杠杆率很高(约合114∶1),杠杆放大了资本账户收益及损失的影响。美联储资产的损失只需要达到1%就可以彻底抵销其资本。</li> </ul> <p>然而,考虑到美联储隐藏的黄金资产,它从来没有资不抵债:</p> <ul> <li>美国财政部持有的黄金数量约为8000吨,大致相当于美联储在其资产负债表中所称的黄金数量——也是8000吨左右。</li> <li>隐形资产(黄金券)为美联储资本账户增加了3000亿美元,使得美联储的杠杆比率从114∶1降至一个更加合理的比例——13∶1,与大多数资本雄厚的银行的资本比率类似。</li> </ul> <p>美元决定了人们对全球金融体系的整体信心,对美元的信心依赖于美联储资产负债表的偿付能力,而这种偿付能力最终却依赖于黄金。</p> <p>这就是为什么虽然各国央行和政府都公开贬低黄金的重要性,但仍然将黄金储存在它们的保险库中。</p> <p><img src="/images/picgo/20220401142723.png" alt="" /></p> <h2>黄金是复杂经济局势下的保险</h2> <h3>作者为何判断国际货币市场不久会崩溃</h3> <p>作者在分析世界经济状况和经济崩溃的可能性时,使用了复杂性模型。然而,美联储却使用随机均衡模型。</p> <p>然而,经济并非一个均衡的体系,而是一个复杂的体系:</p> <ul> <li>由于网络自身的特性,网络之中存在着相互连接、相互作用和溢出效应的现象,这些现象导致了网络的复杂性。</li> <li>在一个复杂的系统中,如果你试图使用均衡模型实施策略,那么必定会错误百出。</li> <li>例如,2007年美国房地产崩溃,但是尽管平时美国房地产市场与日本股票市场本身没有关联,但美国住房贷款市场的困境导致日本股票市场同时大幅下滑。</li> <li>总而言之,全球经济状况 就如同复杂的网络系统,盘根错节,十分复杂</li> </ul> <h3>过去30年来,经济出现了极度的金融化</h3> <p>传统上,金融被用来促进贸易、生产制造业和商业的发展,它支持其他业务活动的开展,但<strong>金融业本身并不是目的所在</strong>。</p> <p>在2008年经济危机时期,美国经济中金融业约占股票市值的17%,占GDP的17%。对于一个促进性的行业来说,它的比例是巨大的,合理的比例应该是5%。</p> <p>这表示我们更倾向于从金融交易,而非从制造业、建筑业、农业和其他实体形式的生产中获得财富。</p> <p><strong>银行家用来提取财富的手段增加了复杂性,却没有增加价值</strong></p> <p>金融业本身并不能创造财富,它利用内部信息和政府补贴从其他行业中获取财富,这是一种寄生或所谓的“食利者”活动。</p> <p>在金融引发下一次经济危机之前,应该控制它的无序发展,控制措施包括分拆大银行、禁止大部分金融衍生品、限制货币供应等。</p> <p><img src="/images/picgo/20220401143508.png" alt="" /></p> <h3>美联储及其政策具有不可靠性</h3> <p>美联储是私人银行所有权与政府监管的不寻常混合体:</p> <ul> <li>在区域性的储备银行层面,联邦储备银行是私有的,美联储的下一层所属机构由位于全美主要经济中心的12家地区联邦储备银行组成。其中包括纽约联邦储备银行、波士顿联邦储备银行,以及费城,旧金山和达拉斯等联邦储备银行。这些区域储备银行并不属于美国政府所有。</li> <li>但整个系统的控制权仍掌握在由美国总统任命并经美国参议院确认的理事会中。</li> </ul> <p><img src="/images/picgo/20220401143955.png" alt="" /></p> <p>美联储执行政策普遍失败:</p> <ul> <li>美联储可以通过公开市场操作直接控制所谓的“政策利率”,也就是<strong>联邦基金利率</strong>,美联储通过调节这一利率来达到一个目的——保持美国最大限度的就业和物价稳定。</li> <li>如果<strong>加息</strong>,这一利率升高,银行在给企业或个人放贷时的利率也水涨船高,此举可以减少货币供给量,降低通胀,从而给经济降温。</li> <li>反之,如果<strong>降息</strong>,银行放贷的利率就会降低,借钱成本更低,将刺激企业和个人贷款,一般来讲,整体经济得到刺激,变得更加活跃。</li> <li>自2008年以来,美联储已有15个不同版本的政策去调控利率,按照作者的原话“这并不是一个训练有素而严谨的实验,美联储只是走一步算一步,随着时间的推移对此加以弥补。”</li> </ul> <h3>个人投资者的最保险的投资就是黄金</h3> <ul> <li>互联网金融战争</li> </ul> <p>2013年8月22日,纳斯达克停业了半天。4年后,媒体报道了原因:俄罗斯政府向纳斯达克操作系统植入了攻击病毒。</p> <p>因此互联网金融战争威胁的存在,是拥有黄金的另一个原因,因为黄金不是数字化的,不能被黑客攻击或抹除。</p> <ul> <li>现金之战</li> </ul> <p>除了货币战争和金融战争之外,美国还出现了针对现金的战争。这种对自由使用现金权利的攻击,是在经济不确定时期考虑投资实物黄金的另一个理由。</p> <p>一个完全数字化的系统正在为负利率的经济体系铺路;取消现金也使得强制保释、征收和冻结账户变得更加容易。</p> <p><strong>从金币到黄金担保支持的纸币,再到法定货币,之后到数字货币的整个过程,已经花费了大约100年的时间。在此过程中的每一个步骤,都让政府更容易征收你的财富。</strong></p> <p>因此黄金作为一种实物财富,有保值的效果,并且可以不受其他形式的货币数字化的影响。</p> <h3>无论是通货膨胀、还是通货紧缩,黄金都是保值的</h3> <p>通货膨胀的情况下,物价上涨,金价上涨,黄金的保值是显而易见的。</p> <p>通货紧缩的情况下,如果黄金的名义价格下跌,那么其他商品的名义价格下跌更多,如果以实际价格来衡量,黄金仍然是保值的。</p> <h3>美元霸权力量减弱</h3> <ul> <li>世界对美元的信心正在减弱:</li> </ul> <p>自2010年以来,美国政府实际上已经放弃了稳健的美元。当年1月,美国结束了自1980年以来盛行的稳健美元政策。一项旨在鼓励通货膨胀和名义增长的货币贬值政策开始实施。廉价的美元策略引发了一场货币战争。</p> <p>世界各地有许多活动旨在削弱美元作为全球储备货币的地位。我们有太多的贸易伙伴和金融投资伙伴已经对美元失去了信心,并对美国利用美元的地位来维持赤字和印钞补缺的方式感到不满。</p> <p>外资银行也正在尽快摆脱美元体系。</p> <ul> <li>多个国际力量都希望结束国际货币体系中的美元霸权:</li> </ul> <p>俄罗斯、伊朗、中国都先后遭到过美国的经济制裁;</p> <p>2014年 俄罗斯和中国、伊朗分别签署了石油贸易协议;</p> <p>俄罗斯本身是石油出产国,但是俄罗斯同意购买伊朗的石油;由于美国的制裁,伊朗还不能轻易地在公开市场上出售石油;因此俄罗斯可以进口伊朗的石油,担当伊朗向其他国家出售石油的中间人;</p> <p>而中国与瑞士进行了货币互换;因此中国向俄罗斯购买石油后,可以用瑞士法郎支付给俄罗斯;俄罗斯可以通过其他国家转换瑞士货币;</p> <p>这样的贸易链接,完全跳过了美元。</p> <h2>金价起伏,但是黄金的价值永恒不变</h2> <h3>黄金的“价格”</h3> <p><img src="/images/picgo/20220401144229.png" alt="1970年来的黄金价格" /></p> <p>黄金的美元价格的“上涨、下跌”,其实意味着美元货币价值的“下跌、上涨”。</p> <p>作者对黄金投资者的建议:应该关注的是黄金的重量,而不是黄金的价格。</p> <p>实物金价会遭到来自纸黄金市场的压制,但实际上,<strong>实物金比纸黄金价值更高</strong>:</p> <ul> <li>黄金的衍生品——期货、掉期、ETF、租赁、远期和未分配黄金构成纸黄金市场。</li> <li>纸黄金市场很可能有实物黄金市场的百倍之大,如果一直有双向市场、价格行为不混乱、人们愿意不断滚动契约、人们不坚持实物交割,杠杆化的纸黄金系统就可以有序运转。</li> <li>实物金价会遭到来自纸黄金市场的压制,但是如上所述,纸黄金市场存在过高的杠杆、意味着过高的风险,一旦黄金实物交割的任何意外中断都可能引发买盘恐慌、金价暴涨。</li> </ul> <h3>操纵金价的力量</h3> <p>金价操纵是千真万确存在的。在没有相关消息的情况下,当我们看到金价大幅下跌时,我们可以合理推断出黄金市场正在被人操纵着。</p> <p>操纵金价的途径有很多,例如抛售实物金、纸黄金操纵、对冲基金操纵、租赁未分配远期合约,或是以上途径的组合操纵。</p> <p>美联储希望美元走弱:</p> <ul> <li>美元贬值会导致进口成本上升,这有助于美联储实现其通胀目标</li> <li>美元疲软原则上意味着黄金价格上涨</li> <li>美联储希望金价有条不紊的上涨,但不希望金价无序增长,因此需要操纵金价走低。</li> </ul> <p>中国希望金价走低:</p> <ul> <li>中国拥有数万亿美元的美国国债</li> <li>如果美国达到它所希冀的通货膨胀率,美元走低,中国持有的美国国债就会贬值</li> <li>但是美元走低,黄金就会涨价,持有的黄金价值会更高。</li> <li>因此持有美国国债和黄金是保护中国财富的一种对冲方式。</li> </ul> <h3>对抗操纵?</h3> <p>如上所述,复杂莫测的原因导致实物黄金的“价格”起起伏伏,实物金投资者应该如何对抗操纵?</p> <p>作者的建议是:</p> <ul> <li>任何金价控制都需要实物黄金;实物黄金是有限的;对金价的操纵控制是有极限的。最终,价格控制者的实物黄金将消耗殆尽,或通货膨胀预期的变化将导致金价飙升,甚至连政府都无法控制。</li> <li>因此无需对抗操纵,即使金价起伏,实物金的价值也是永恒不变的。</li> <li><strong>投资者应该忽略金价的起伏,长期购买和持有黄金,以在突如其来的金融震荡和恐慌情况下达到财富保值的效果。因为我们的目标不是通过交易头寸来快速获利,而是财富长期保值。</strong></li> </ul> <h2>如何投资黄金</h2> <p>作者的建议是:<strong>现在就投资黄金,将流动资产的10%配置为黄金,并将其妥善存放在安全的地方</strong>。</p> <p>除此之外,我总结了国内投资者购买实物金的几种途径:</p> <ul> <li>上海金交所,但此渠道已经对个人买家关闭(2022年,金交所已经取消了个人用户注册,各大银行的代理交易通道也被关闭了)</li> <li>各大金店实物金,溢价较高(例如2022年4月1日金交所大盘价394,四大珠宝品牌中谢瑞麟、周生生、周大福金条价是502,首饰金价是512,还要另外收几十~上百每克的工费)</li> <li>银行实物金,大多数基础投资金条价格是大盘价+10~30元/g工费</li> <li>各大电商平台黄金卖家,出售大盘价格+5元/g工费的实物金、金条、板料</li> </ul> <h2>关于黄金的有趣知识</h2> <ul> <li>自人类文明以来,开采了约<strong>18.72万</strong>吨黄金</li> <li>世界海洋中的含金量被预估为<strong>1.5万吨</strong></li> <li>世界上**90%**的黄金已经被开采</li> <li>被开采的黄金中,有**49%**被用于首饰</li> <li>已被开采的所有黄金,可以装进一个<strong>21立方米</strong>的箱子中。</li> <li>黄金的熔点是<strong>1064摄氏度</strong></li> <li>国外通常使用盎司Oz作为单位衡量黄金的重量,<strong>1Oz=31.103g</strong></li> <li>伦敦金交所的标准交易金条重量是<strong>400盎司</strong></li> <li>中国上海金交所的标准交割金条重量是<strong>1kg</strong></li> </ul> <p><a>以上数据来源: www.gold.org</a></p> 个人成长https://www.scarsu.com/gold/#post-comment/月刊#8 | 2022.02https://www.scarsu.com/monthly_8_2022_02/https://www.scarsu.com/monthly_8_2022_02/书单、自我管理、心理、健康、工具、经济、投资、前端开发Mon, 28 Feb 2022 00:00:00 GMT<p>💡 <a>信息源分类整理 | 往期合集 | 持续更新</a></p> <hr /> <h3>提升认知:信息输入、知识管理🧠</h3> <ul> <li>书单 | <a>2021年读了162本书,向你推荐这些 - 36Kr</a></li> </ul> <h3>提升体验:身心舒适、自律极简😃</h3> <ul> <li>自我管理 | <a>个人生活的数字化与可视化表达</a></li> <li>健康 | <a>适当的咖啡因可以降低身体内的“坏”胆固醇</a></li> <li>心理 | <a>如何提升内心的充实感</a></li> <li>厨艺 | <a>程序员在家做饭指南</a></li> </ul> <h3>提升效率:用 好工具、用好 工具🔨</h3> <ul> <li>工具推荐 | <a>生产力开发工具</a></li> <li>浏览器插件 | <a>omni:书签、历史、tab页管理</a></li> <li>文章 | <a>快速打字是一项高杠杆技能</a></li> <li>打字 | <a>在线打字训练TIPP10 Online Typing Tutor</a></li> <li>打字 | <a>打字速度测试Typing Test · Improve your WPM speed</a></li> <li>打字 | <a>打字训练 Typing Practice</a></li> <li>打字 | <a>在线打字竞速游戏 TypeRacer</a></li> <li>打字 | <a>在线打字训练 Monkeytype</a></li> </ul> <h3>提升物质:专业技能、工作投资💹</h3> <ul> <li>投资 | <a>黄金市场分析 &amp; 投资黄金的几种方式</a></li> <li>经济 | <a>为什么美联储一提加息,市场就慌了? - 知乎</a></li> <li>经济 | <a>出国劳务在日本打工到底有多累? - 知乎</a>:现代奴隶制度</li> <li>经济 | <a>1993 年左右发生的人民币大贬值是怎么回事? - 知乎</a></li> <li>经济 | <a>《爱情公寓》中唐悠悠用 18 张信用卡相互还债保持平衡的方式科学吗? - 知乎</a></li> <li>职场 | <a>十年内远程工作会普及吗?</a></li> <li>开发 | <a>开发者路线图</a></li> <li>前端 | <a>State of avaScript 2021</a></li> <li>前端 | <a>如何阅读ECMAScript标准</a></li> <li>前端 | <a>vue-naive-admin</a>:Vite+Vue3+NaiveUI+Pinia后台管理模板</li> <li>前端 | <a>baidu/amis: 前端低代码框架,通过 JSON 配置就能生成各种页面。</a></li> <li>前端 | <a>tencentyun/TUIChorus: 腾讯云TRTC针对直播、语聊、视频通话等推出的低代码解决方案~</a></li> <li>前端 | <a>技术周报·为什么说 WebAssembly 是 Web 的未来 - 掘金</a></li> <li>前端 | <a>字节的一个小问题:npm 和 yarn不一样吗? - 掘金</a></li> <li>前端 | <a>我的前端性能优化知识体系 - 掘金</a></li> <li>前端 | <a>解释Twitter的前十行代码 - CSS Tricks</a></li> <li>前端 | <a>7篇Web性能的新文章 - CSS Tricks</a></li> <li>前端 | <a>DOM中,Node和Element的区别</a>:Object&gt;EventTarget&gt;Node&gt;Element&gt;HTMLElement&gt;HTMLDivElement</li> <li>前端 | <a>用Vercel一键部署静态网站</a></li> <li>前端 | <a>微前端落地</a></li> </ul> 信息源https://www.scarsu.com/monthly_8_2022_02/#post-comment/高敏感是种天赋:HSP自救指南https://www.scarsu.com/hsp/https://www.scarsu.com/hsp/敏感是与生俱来的特质,肯定自己的独特、感受更多、想象更多、创造更多Fri, 25 Feb 2022 00:00:00 GMT<p><img src="/images/picgo/20220215104940.png" alt="《高敏感是种天赋》" /></p> <h2>简介</h2> <ul> <li>书名:《高敏感是种天赋》</li> <li>原名:《Highly Sensitive People in an Insensitive World》</li> <li>作者:[丹麦]伊尔斯·桑德</li> <li>ISBN:9787559608710</li> <li>豆瓣链接:https://book.douban.com/subject/27125070/</li> <li>思维导图:/images/picgo/2022HSP.png</li> </ul> <p><code>HSP</code>是<code>Highly Sensitive People</code>,高敏感人群。</p> <ul> <li>如果你无法长时间待在热闹的环境</li> <li>如果你被人指责过于敏感</li> <li>如果你因为对信息过于敏感,以致于大脑“硬盘”很快就被填满、意识失去秩序</li> <li>如果你因为高度共情,而常常被别人的情绪影响</li> <li>如果你拥有过度的责任感、总是努力避免给他人带来不便或痛苦、甚至常常自责</li> <li>如果你即使独处也能拥有丰富的内心世界</li> <li>如果你行事谨慎、提前考虑好每个细节,想象所有可能的风险,并准备好对应的解决方案</li> </ul> <p>如果以上的特征之一与你相符,那么我推荐你看看这本书。</p> <p>我从前常常产生自我怀疑:是否自己过于敏感?</p> <p>看完了作者在本书中介绍的<code>HSP</code>的特质,才认知到自己是高敏感人群的一员。</p> <p>本书的作者是心理治疗师,丹麦奥胡斯大学神学硕士,硕士论文以卡尔•荣格与索伦•克尔凯郭尔为主要研究方向。</p> <p>书中的<code>HSP</code><strong>如何自处、如何自我疗愈、如何应对人际交往</strong>等方法,让我受益良多。</p> <h2>如何判断自己是否高敏感</h2> <h3>发达的神经系统</h3> <p>高敏感人群拥有发达的神经系统,听觉、视觉、触觉、嗅觉等感官可能较敏感,能感知更多的信息。</p> <p>因此,高敏感人群可以感知到事物细微的差别,并对信息进行更深入的加工。</p> <p>我们拥有活跃的想象力和丰富的内心世界,这意味着我们从外部世界接收和感知到的信息,会触发大脑里各种概念、想法并建立联结。</p> <p>这也会导致我们的大脑“硬盘”很快就被填满,不堪重负。</p> <h3>高度共情,容易受别人的情绪影响</h3> <p>能给予别人共情式的倾听;</p> <p>在帮助和照顾他人方面十分尽心;</p> <p>对别人的情绪也非常敏感;</p> <p>但是,并不擅长将自己从他人的痛苦中抽离出来</p> <h3>拥有强烈的责任感</h3> <p>许多高度敏感型人都有着强烈的责任感,认为自己需要承担整个世界的责任。</p> <p>研究显示,与一般4岁左右的儿童相比,抑制性(敏感性)的儿童更少欺骗他人、破坏规则或者做出自私的行为。</p> <p>高度敏感型人总是努力避免给他人带来不便或痛苦。他们也花更多精力去维持与他人的关系。</p> <p>但是,有时学着后退一步,让他人负责,使之从错误中汲取教训或许会更好。</p> <h3>拥有更加丰盛的内在世界</h3> <p><code>HSP</code>享受宁静的生活,独自一人时,很少感到孤独无聊,甚至享受其中。</p> <p>敏感者们的意识和无意识之间的间隔太过无力,无意识的意念和想法很容易在他们进行创作或者编织梦想时闯入大脑,变得清晰可见。</p> <p>有时候能思如泉涌,并不需要特别激励。这股天生的动力可谓是价值连城的财富,当然,前提是你懂得如何利用它。</p> <h3>谨慎</h3> <p><code>HSP</code>倾向于提前考虑好每个细节,想象所有可能的风险,并准备好对应的解决方案。</p> <p>这虽然会降低你出错的概率,但是,它也会降低你对事物的接受速度。</p> <p>可能使你长期处于担心焦虑的状态</p> <h3>附录2:敏感度指数测试</h3> <p><a>https://weread.qq.com/web/reader/95e323805dfeb195e2928b1k1c3321802231c383cd30bb3</a></p> <h2>高敏感是与生俱来的</h2> <p>有些人生而敏感,其敏感性是与生俱来的,遗传因素比环境和教养的影响更大。</p> <p>研究表明,这些高敏感人群的比例是20%。</p> <ul> <li>敏感不是缺陷,相反,它可以丰富你的人格。</li> </ul> <p>高度敏感型是不同特质的复杂结合体:<strong>尽责、创造、积极向上、易受影响、共情,敏感的感觉</strong>和<strong>脆弱的神经系统</strong>等等。</p> <p>这些特质会给敏感型人的生活带来些许麻烦,但也会是创造性、专注力和同理心之源。</p> <blockquote> <p>高度敏感可以极大地丰富我们的人格特点……只有在糟糕或者异常的情况出现时,它的优势才会转变成明显的劣势,因为那些不合时宜的影响因素让我们无法进行冷静的思考。 没有比把高度敏感归为一种病理特征更离谱的事。如果真是这样,那世界上25%的人都是病态的了。</p> <p>——荣格(C.G. Jung)</p> </blockquote> <p>因此,作为<code>HSP</code>,我们应该客观看待自己,可以将<strong>敏感</strong>一词,视为中性词,不贬不褒。</p> <ul> <li>我们天生比别人拥有更敏感的感官、神经,如果妥善利用,<strong>敏感</strong>就是我们天生的优势。</li> <li>在糟糕的环境中,我们比别人更容易感到疲惫,如果我们知道这一点,并合理安排自己的生活,也可以最大程度的避免糟糕的体验。</li> </ul> <h2>HSP应该如何自处</h2> <h3>了解自己、接纳自己、爱自己</h3> <p>正如前文所说,高敏感是与生俱来的。</p> <p>我们应该客观地看待自己和周围的世界。</p> <p>和过去和解、和自己和解。意识到并理解自己的敏感性,选择让自己最舒服的方法。</p> <blockquote> <p>你越是接受自己是一个什么样的人,你越不需要花太多精力去让自己适应</p> </blockquote> <p>关切自己,同情自己,给予自己支持和鼓励。</p> <p>学着接受自己,肯定自己的独特、感受更多、想象更多、创造更多。</p> <h3>停止内耗、跳出恶性循环</h3> <p>典型的高度敏感型的人都存在低自尊问题,并且尝试通过设定高标准来弥补自己的缺点。</p> <p>也因此容易陷入恶性循环:</p> <p><img src="/images/picgo/20220216162847.png" alt="恶性循环" /></p> <p>跳出恶性循环的方法,就是做真实的自己,接纳自我、正视自我,<strong>设定与自身能力相匹配的目标</strong>。</p> <p>为自己设定一些可实现的目标:</p> <ul> <li>比如早早起床、做顿早饭。</li> <li>简单的事就可以为自己带来积极的体验。</li> <li>列出一份心愿清单,当感觉心情低落时,找点清单上的事情做,完成它们会带来极大的快乐。</li> </ul> <h3>合理处理冲突、愤怒、内疚、羞耻</h3> <ul> <li> <p>愤怒有害无利,冷静下来</p> <p>当愤怒值达到顶峰时将其发泄出来并不是件好事;</p> <p>如果你的愤怒给别人带来伤害,你也会感到痛苦,无法忽视内心强烈的自责感。这会刺痛你的神经,使你受困于内疚和自责的牢笼。</p> <p>清楚地说出“不”“我不想做”或者“我不能接受”常常比直接表达愤怒更有效。</p> <p>在冲突中,叫停、休战,确定重新沟通的时间,各自冷静</p> </li> <li> <p>共情,发现愤怒背后的需求</p> <p>愤怒常常只是人们保护自己的盔甲。愤怒之下,往往隐藏着许多其他脆弱的情感。</p> <p>发现隐藏在愤怒背后的情绪、根源。</p> </li> <li> <p>明确边界</p> <p>认真观察,勇于表达,最后不带偏颇地讲出自己感知到的信息。</p> <p>为自己设置界限,明确要求对方停止对你做出的行为。</p> </li> <li> <p>转愤怒为悲伤</p> <p>愤怒往往出现在期望未被实现或者需求未被满足之时。</p> <p>与愤怒不同的是,悲痛的优势在于它可以唤起别人的同情,得到别人的支持。</p> <p>可能的话,放下未得到满足的期望,启动悲伤程序,引导对方与你共情。</p> <p>从“应该”到“希望”,从愤怒到悲伤。</p> </li> <li> <p>合理内疚</p> <p>内疚其实是一种<strong>面向自己的愤怒</strong>,可以视为一种对自己的无能为力和悲伤情绪的防御方式。</p> <p>如果你的内疚感和你的行为所带来的影响之间是成比例的,那么你的内疚就是合理的。</p> <p>如果你对那些你并没有产生任何实质性的影响或者根本无法人为控制的事感到内疚,那么这种内疚感就是多余的。</p> <p>如果是合理的内疚,对承受方 表达歉意、做出补偿,及时消除内疚感。</p> <p>如果是不合理的内疚,那就勇敢直面生活的不确定性和自己的无能为力,打破“非黑即白”的世界观;详尽列举出糟糕状态的所有原因,找出只属于自己责任的那部分。</p> </li> <li> <p>及时止损,远离不健康的人际关系</p> <p>有时候,人际关系不顺利,并不是自己的问题。</p> <p>如果尝试过上述方法后,仍然不起作用。</p> <p>那么应该重新思考一下,你们的关系给你们双方带来了什么?是否要继续维持你们的关系?</p> </li> </ul> <h3>精神断舍离</h3> <ul> <li>清晰地设定边界、表达不满</li> <li>留出独处时间</li> <li>减少信息刺激的输入</li> <li>做一些疗愈的事情</li> <li>给自己适当的独处时间</li> <li>向伴侣表达明确需求:希望ta尊重你的敏感型人格</li> </ul> <h2>人际交往的技巧</h2> <h3>高质量互动</h3> <p>在高质量的互动下,情感的交流就会代替信息刺激,给高敏感人群更好的体验。</p> <p>如果自己是倾听者,要给予对方反馈,适当表达自己。</p> <p>如果自己是表达者,要寻找方法获得对方回应,例如提问对方如何看待你、分享想法和感受、进一步追问等。</p> <h3>掌控对话:设定对话界限</h3> <p>设置好对话的界限,当人际交流中感到疲惫、不适时,将注意力返回到自己身上,避免在对话中被信息吞噬。</p> <h3>掌控对话:控制聊天深度</h3> <p>不同的聊天深度适合不同的场景。</p> <p>深入的聊天,引人入胜,可以带来情感的体验。</p> <p>想要很深度的聊天,有两个技巧:</p> <ol> <li>沉默,可以在无形之中增加对话的深度。</li> <li>从泛泛而谈转变到具有针对性的交流。</li> <li>追问。</li> </ol> <p>浅聊,适合初识、短时间的交际场景,有时候,需要及时避免对话变得更深,在必要的时候能成功地将深入的对话带回到表面,轻松地结束对话;</p> <p>浅聊的技巧:使用一些概括性或者解释性的语言(俗称糊弄、敷衍😂</p> <h3>掌控对话:灵活切换于对话的四个层次</h3> <ul> <li>层次1:短对话。</li> </ul> <p>短对话的优点是,你很容易开始一个话题,结束一个话题也非常轻松。如果你对你们的对话并不满意,你也可以很快从对话中脱身</p> <p>适合不熟悉的人,作为互相认识的敲门砖。</p> <p>结识一个新的人方法,就是建立你和ta之间的纽带</p> <p>可以直接直接讲讲自己当前的感觉,包括味觉、嗅觉、听觉、视觉</p> <p>重要的不是你说了什么,而是你说话的语气,让对方感受到你们还有进一步交流的空间</p> <ul> <li>层次2:角色层次,寻找共同兴趣。</li> </ul> <p>根据某个特定角色来展现自己,例如介绍自己的职业、家庭</p> <p>寻找共同的兴趣,交换信息、想法、意见,讨论政治、家庭以及其他有意思的东西</p> <p>从第1层次到第2层次,可以延长每个话题的停留时间。例如:对食物的一点意见就可能将话题切换到对食谱的探究;对天气的简单点评也可能发展到对气候的讨论。当然,你也可以提出一个新的话题。</p> <p>达成一致,定下约定。</p> <ul> <li>层次3:情感层次,让对方踏入你的秘密空间。</li> </ul> <p>分享一些个人经历,将对方带入到你的秘密空间</p> <p>聊一些自己关于人和事的经历和感受</p> <p>分享你的童年、婚姻、同事关系和家庭关系、流言蜚语、八卦新闻</p> <p>分享自己的内心世界</p> <ul> <li>层次4:坦诚相待。</li> </ul> <p>先确认对方是否真的想跟你进行如此深入的对话</p> <p>讨论两者之间的关系:我和你,此时此刻,是如何看待对方的。</p> <p>例如:我想跟你聊一聊我们之间的感觉。可以吗?我很想跟你聊一聊此刻我对你的感觉。你愿意听吗?我想知道你对我的感觉。你愿意告诉我吗?</p> 个人成长https://www.scarsu.com/hsp/#post-comment/月刊#7 | 2022.01https://www.scarsu.com/monthly_7_2022_01/https://www.scarsu.com/monthly_7_2022_01/2021年度书单、纪录片推荐、播客、职场、行业、前端、家居、种草、工具Mon, 31 Jan 2022 00:00:00 GMT<p>💡 <a>信息源分类整理 | 往期合集 | 持续更新</a></p> <hr /> <h3>认知提升 | 读书 | 信息源 | 知识管理 🧠</h3> <ul> <li>【话题】每个人的缺点,都会在与最亲近的人相处时放大显现。</li> <li>【话题】<a>我们一生中不同阶段需要放弃的东西</a> - 《少有人走的路》</li> <li>【话题】<a>为什么有些垂直技术领域看不到好文章</a> - <a>余杭子曰</a></li> <li>【TED演讲】读书是为了什么 <a>思维导图</a> - <a>余杭子曰</a></li> <li>【文章推荐】<a>happy xiao:2021改变我人生的那些文章</a></li> <li>【知识管理】<a>一个信息流管理方案</a>:RSS、Inoreader、简悦、Obsidian、Notion</li> <li>【播客】<a>有趣的中文播客推荐?</a></li> <li>【播客】<a>全种类播客推荐</a></li> </ul> <h3>纪录片 | 电视节目 📺</h3> <ul> <li>央视纪录片<a>《基金》</a>,基金投资必看</li> <li>我们究竟有多轻,上下五千年 - 央视纪录片<a>《国家宝藏》</a></li> <li>电视节目<a>《锵锵行天下》</a>,窦文涛深度聊天</li> <li>电视节目<a>《很高兴认识你》</a>,在疗愈时光里与生活对话</li> <li><a>《但是还有书籍》</a>纪录片,快时代里的阅读指南</li> <li>为情所困<a>《梁永安爱情问答》</a></li> <li>拓展知识边界、开阔心胸和格局,访谈节目<a>《十三邀》</a></li> <li>拖延、焦虑<a>《某某与我》呼兰篇</a></li> <li>内耗严重、身心俱疲、找不到人生目标与意义<a>《梁永安从“小镇做题家“到”窄人“》</a></li> <li>【财富】电视节目<a>《隐姓亿万富翁》</a>,亿万富翁再现如何从贫穷汉到价值百万公司的总裁</li> <li>【财富】电影<a>《金钱与我》</a>,消费节流的方法</li> <li>【财富】纪录片<a>《富哥哥穷弟弟》</a>,相同背景走出的不同人生</li> <li>【财富】纪录片<a>《金钱通解》</a>,经济骗局</li> <li>【财富】纪录片<a>《成为沃伦巴菲特》</a></li> <li>【财富】纪录片<a>《无节制消费的元凶》</a>,资本主义的三大毒药:性开放、成功学、消费主义。</li> </ul> <h3>2021年度书籍榜单 📔</h3> <ul> <li><a>kindle电子书2021年度榜单(中国)</a>: <ul> <li>蛤蟆先生看心理医生</li> <li>被讨厌的勇气</li> <li>三体</li> <li>消失的13级台阶</li> <li>百年孤独</li> <li>别想太多啦</li> <li>绝叫</li> <li>活着、无人生还</li> <li>毛泽东选集</li> </ul> </li> <li><a>2021微信阅读年度书单</a>: <ul> <li>《疫苗竞赛》</li> <li>《狂人日记》(2月觉醒年代热播)</li> <li>《棉花帝国》(3月H&amp;M发布声明抵制新疆棉)</li> <li>《切尔诺贝利的午夜》(4月日本决议投放核废水)</li> <li>《袁隆平的世界》(5月袁隆平逝世)</li> <li>《人口大逆转》(6月“三孩政策”)</li> <li>《漫画百年党史·开天辟地1921-1949》(7月中共建党100周年)</li> <li>《无规则游戏:阿富汗屡被中断的历史》(8月塔利班在时隔20年后重新掌控阿富汗)</li> <li>《论中国》(9月孟晚舟在加拿大被拘1028天后回归祖国)</li> <li>《血战长津湖》(10月电影《长津湖》拿下年度票房冠军)</li> <li>《罪与罚》(11月陀思妥耶夫斯基诞辰200周年)</li> <li>《煤气灯效应》(12月王力宏婚变事件让“gaslighting”这个词进入公众视野)</li> </ul> </li> </ul> <h3>自我管理 | 心智提升 | 意识秩序 | 极简低消 | 健康生活 😃</h3> <ul> <li>【时间管理】<a>人与人的差距,是由第3个8️⃣小时创造的</a></li> <li>【健康】<a>2021跑步总结 - 来自一位365天全勤跑步的大佬</a></li> <li>【种草&amp;排雷】<a>2021 你买的最值和最不值的东西是? - V2EX</a></li> <li>【2022年初Flag大赏】<a>大家 2022 年的第一个挑战是什么? - V2EX</a></li> <li>【维权】<a>一次12315维权经历</a></li> <li>【家居】<a>强弱电箱遮丑案例</a></li> </ul> <h3>用 好工具 | 用好 工具 🔨</h3> <ul> <li>【App - 你我当年】:修复模糊照片</li> </ul> <h3>技术 | 职场 | 财富 💹</h3> <ul> <li>【职场】<a>年终总结怎么写?</a></li> <li>【行业】<a>成功转型的初创公司列表</a></li> <li>【行业】<a>下一个 10 年,将会发生的 12 个趋势</a></li> <li>【行业】<a>2022年,互联网10大关键词</a></li> <li>【行业】<a>2021全球最受欢迎域名榜单,Tiktok取代Google成为第一</a></li> <li>【前端】<a>ES2016-ES2021知识点</a></li> <li>【前端】<a>前端监控系统设计 - 掘金</a></li> <li>【前端】<a>2022 年需要关注的几个前端技术 - 掘金</a></li> <li>【前端】<a>CSS-Based Fingerprinting | CSS-Tricks - CSS-Tricks</a></li> <li>【前端】<a>Defensive CSS | CSS-Tricks - CSS-Tricks</a></li> <li>【前端】<a>浅析我们为什么要上Vue3? - 掘金</a></li> <li>【前端】<a>下一代CSS:@container</a></li> <li>【前端】<a>web components组件库</a></li> <li>【前端】<a>css + svg 实现极光特效</a></li> <li>【前端】<a>低代码行业现状简析-凹凸实验室 京东</a></li> <li>【前端】<a>对2D图片实现3D效果</a></li> <li>【前端】<a>腾讯UI套件: TDesign</a>(支持vue2、3、react、angular;并内置于设计工具<a>pixso</a>中</li> <li>【前端电子书】:<a>给不耐烦的JS程序员看的ES2022</a> - The ECMAScript 2022 edition of “JavaScript for impatient programmers”</li> <li>【前端】<a>如何在产环境debug</a>:global search、添加本地sourceMap、local overrides</li> </ul> 信息源https://www.scarsu.com/monthly_7_2022_01/#post-comment/少有人走的路:心智成熟的旅程https://www.scarsu.com/the_road_less_traveled/https://www.scarsu.com/the_road_less_traveled/自律就是解决人生问题最主要的工具,也是消除人生痛苦最重要的方法。爱是自律的原动力。Tue, 25 Jan 2022 00:00:00 GMT<h2>简介</h2> <p><img src="/images/picgo/less-road.png" alt="《少有人走的路:心智成熟的旅程》" /></p> <ul> <li>原名:The Road Less Traveled</li> <li>作者:[美]M.斯科特·派克</li> <li>ISBN:978-7-5158-1979-2</li> <li>豆瓣链接:https://book.douban.com/subject/35442753/</li> <li>思维导图:/images/picgo/less-road-note.png</li> </ul> <p>在这本书中,作者结合“自律、爱”等话题,阐明了如何在人生这一场艰辛之旅中,经历一系列艰难乃至痛苦的转变,促进心智成熟,最终达到自我认知的更高境界。</p> <h2>人生苦难重重</h2> <p>人生苦难重重————这是作者写在正文中的第一句话。</p> <p>前段时间看了<a>《逆商》</a>、<a>《心流》</a>这两本书,作者都有着类似的观点。</p> <p>《心流》中说:宇宙初创之时,就没有以人类的安逸舒适为念;自然选择出的基因和生理机制只是服务于人类生存繁衍,没有增加幸福快乐的考虑。</p> <p>《逆商》中说:人生就是要面对一个又一个逆境。</p> <p>本书作者说:<strong>人生就是一个不断面对问题解决问题的过程</strong>。</p> <blockquote> <p>人生苦难重重。这是个伟大的真理,是世界上最伟大的真理之一。</p> <p>它的伟大之处在于,一旦我们领悟了这句话的真谛,就能从苦难中解脱出来,实现人生的超越。</p> <p>只要我们真正理解并接受了人生苦难重重的事实,那么我们就会释然,再也不会对人生的苦难耿耿于怀了。</p> </blockquote> <p>回避问题和逃避痛苦的倾向,是人类心理疾病的根源。</p> <h2>自律</h2> <p>自律就是解决人生问题最主要的工具,也是消除人生痛苦最重要的方法。</p> <blockquote> <p>所谓自律,就是主动要求自己以积极的态度去承受痛苦,解决问题。</p> </blockquote> <p>心灵在承受痛苦和解决问题的过程中,会不断地成长和成熟。</p> <p>所以,自律是人们心灵进化最重要的手段和工具。</p> <h3>自律原则1:推迟满足感</h3> <p>不贪图暂时的安逸,先苦后甜,重新设置人生快乐与痛苦的次序。</p> <p>不逃避问题,不拖延:</p> <ul> <li>问题拖得越久,就越是积重难返。</li> <li>问题带来痛苦,尽早的直面问题,把满足感向后推迟,放弃暂时的安逸或是程度较轻的痛苦,去体验程度较大的痛苦,这才是对待问题和痛苦最明智的办法。</li> </ul> <p>对自我价值的认可也是自律的基础:</p> <ul> <li>当一个人觉得自己很有价值时,就会采取一切必要的措施来照顾自己。</li> <li>自律是自我照顾,自我珍惜,而不是自暴自弃、贪图安逸。</li> </ul> <h3>自律原则2:承担责任</h3> <p>必须面对属于自己的问题,而不是推卸责任。</p> <p>过度承担责任、或者推卸责任,都是心理疾病:</p> <ul> <li>神经官能症患者为自己强加责任;</li> <li>人格失调症患者不愿承担原本属于自己的责任。</li> </ul> <p>自己承担责任,就可以掌控自己的自由:</p> <ul> <li>把自己的责任推给别人、让别人为自己负责,实则是逃避自由</li> <li>作为成年人,我们一生都充满选择和决定的机会。接受这一事实,就会变成自由的人;无法接受这种事实,就会永远觉得自己是个牺牲品。</li> </ul> <h3>自律原则3:忠于事实</h3> <p>认清事实,才能认清自己的位置:</p> <blockquote> <p>我们对现实的观念就像是一张地图,凭借这张地图,我们才能了解人生的地形、地貌和沟壑,指引自己的道路。</p> <p>如果地图准确无误,我们就能确定自己的位置,知道自己要到什么地方,怎样到达那里;</p> <p>如果地图信息失真,漏洞百出,我们就会迷失方向。</p> </blockquote> <p>要不停探索、接受新信息:</p> <blockquote> <p>大多数人过了中年,就自认为地图完美无缺,世界观没有任何瑕疵,甚至自以为神圣不可侵犯,而对新的信息和资讯缺乏兴趣。</p> <p>只有极少数幸运者能继续努力,他们不停地探索、扩大和更新自己对于世界的认识,直到生命终结。</p> </blockquote> <p>不要逃避现实,不要让过去的信息成为现在的“心结”:</p> <ul> <li>抱着残缺的人生地图不放,与现实世界处处脱节,这是不少人的通病,也是造成诸多心理疾病的根源。心理学家把这种情形称为“移情”。</li> <li>把产生和适用于童年时期的那些感知世界、对世界做出反应的方式,照搬到成年后的环境中,尽管这些方式已经不再适用于新的环境。</li> <li>逃避现实的痛苦是人类的天性,只有通过自律,我们才能逐渐克服现实的痛苦,及时修改自己的地图,逐步成长。</li> </ul> <p>要不断自我反省,并主动接受挑战:</p> <ul> <li>验证自己是否知行合一</li> <li>接受外界的质疑和挑战,以确定我们的地图是否与事实符合</li> </ul> <p>保持诚实,但有选择地表达意见和想法:</p> <ul> <li>要完全忠于事实,就需要一辈子保持诚实。我们必须确保我们的言语能够准确地表述出我们所认知的事实。</li> <li>敢于面对事实的人,能够心胸坦荡地生活,不必面临良心的折磨和恐惧的威胁。</li> </ul> <h3>自律原则4:保持平衡</h3> <p>确立富有弹性的约束机制:</p> <ul> <li>例如:不但要有生气的能力,还要具备克制脾气的能力。</li> </ul> <p>学会放弃:</p> <ul> <li>要让心智成熟,就得在彼此冲突的需要、目标和责任之间保持微妙的平衡,这就要求我们不断自我调整。保持平衡的最高原则就是“放弃”。</li> <li>失去平衡远比放弃更为痛苦</li> <li>我们一生中不同阶段需要放弃的东西: <blockquote> <p>无需对外界要求作出回应的婴儿状态</p> <p>无所不能的幻觉</p> <p>完全占有父亲或母亲(或二者)的欲望</p> <p>童年的依赖感</p> <p>自己心中被扭曲了的父母形象</p> <p>青春期的自以为拥有无穷潜力的感觉</p> <p>无拘无束的自由青年时期的灵巧与活力</p> <p>青春的性吸引力</p> <p>长生不老的空想</p> <p>对子女的权威</p> <p>各种各样暂时性的权力</p> <p>身体永远健康</p> <p>最后,自我以及生命本身</p> </blockquote> </li> </ul> <p>兼容并包:</p> <ul> <li> <p>既要肯定自我以保持稳定,又要放弃自我以腾出空间,接纳新的想法和观念,实现自我平衡。</p> </li> <li> <p>消除熟悉的过去,追求新鲜的未来</p> <blockquote> <p>面对陌生的人、事、物,我需要让昔日的经验、当前的需求和未来的期待一并出席,共同对我的需求和现实状况进行评估,做出恰当的判断和决定。</p> <p>为了体验新鲜事物的独特性,我必须以包容一切的姿态,说服既有的成见和观念暂时退位,让陌生、新奇的事物进入感官世界。</p> </blockquote> <blockquote> <p>不然的话,人生的每一分每一秒,都将是过去经验的一再重复。</p> </blockquote> </li> </ul> <h2>爱</h2> <p>爱是自律的原动力,把爱和自律结合起来,才能拥有幸福的人生。</p> <p>作者对爱的定义是:<strong>为了促进自己和他人心智成熟,而不断拓展自我界限,实现自我完善的一种意愿</strong>。</p> <p>爱的目的:</p> <ul> <li>实现自我完善</li> <li>拓展自我界限</li> <li>真正的爱是一种扩展自我界限的体验,对外界投入的精神越多,自我边界就会得到越多扩展</li> </ul> <p>真正的爱有以下特征:</p> <ul> <li> <p>爱是一个长期、渐进的过程。</p> </li> <li> <p>爱情不是是永恒的。</p> </li> <li> <p>依赖不是爱</p> <p>只想获取却不愿付出,心智就会永远停留在不成熟的状态,这只会对人生构成限制和束缚,给人际关系造成破坏,让别人跟着遭殃,而不是促进别人的心灵成长。</p> </li> <li> <p>爱在某种意义上是自私的,最终追求的是自我完善。</p> <blockquote> <p>我们真心去爱某个人,是因为我们自己需要去爱别人;</p> <p>我们生儿育女,是因我们自己想要孩子;</p> <p>我们爱自己的孩子,是因为我们渴望自己成为充满爱心的父母。</p> </blockquote> </li> </ul> <p>如何爱:</p> <ul> <li> <p>爱不是无原则的自我牺牲。</p> <p>真正意义上的爱,既是爱自己,也是爱他人。不爱自己的人,绝不可能去爱别人。</p> </li> <li> <p>爱不是感觉,是实际行动。</p> <p>爱是行为,爱意味着我们要不断付出努力,去跨越原来的界限。爱不能停留在口头上,而要付诸行动;爱不能坐享其成,而要真诚付出。</p> </li> <li> <p>爱的对象,也可以是事物、活动</p> <p>培养某种爱好,是自我滋养的有效手段。要学会自尊自爱,就需要自我滋养。</p> </li> <li> <p>爱需要充分投入、付出关注</p> <p>爱,最重要的体现形式,就是关注。我们爱某个人,一定会关注对方,细心照料对方,进而帮助对方成长。</p> <p>关注的主要途径是“倾听”,暂时放下个人的想法和欲望,把注意力放在别人身上</p> <p>充分投入是情感的基础;投入、做出承诺并遵守,可以给别人带来安全感</p> </li> <li> <p>爱需要勇气</p> <p>勇气,并不意味着永不恐惧,而是面对恐惧时能够坦然行动,克服畏缩心理,大步走向未知的未来</p> <p>人生是一场冒险。你投入的爱越多,经受的风险也就越大。</p> <p>敢于追求独立自主、摆脱依赖性。</p> <blockquote> <p>人生唯一的安全感,来自于充分体验人生的不安全感。</p> </blockquote> </li> <li> <p>保持诚实、谦虚、自省,尽力避免指责、冲突、傲慢</p> <p>我们常常以爱的名义去指责所爱的人。可是,大多数批评只是出于一时的冲动、不满和愤怒,不但没有启发和教育意义,反而会使局面更加混乱。</p> <p>保持诚实和谦虚,勤于自省,指责别人之前,先质疑自己是否“绝对正确”。</p> <p>该批评、指出错误时,也不能退缩。</p> </li> <li> <p>爱的前提是独立</p> <p>爱的重要特征之一在于,爱者与被爱者都不是对方的附属品。</p> <p>付出真爱的人,应该永远把爱的对象视为独立的个体,永远尊重对方的独立和成长。</p> <p>有的父母不尊重孩子独立的人格,只把子女当成自我的延伸。子女就像他们昂贵的衣服、漂亮的首饰、修剪齐整的草坪、擦拭一新的汽车一样,代表着他们的社会地位和生活水平。父母的这种自恋情结,看上去没什么大不了,但其实有着惊人的破坏力。</p> <p>婚姻是分工与合作并存的制度,夫妻双方需要奉献和关心,为彼此的成长付出努力。理想婚姻的基本目标,是让双方同时得到滋养,推动两颗心灵的共同成长。双方都有责任照顾后方营地,都要追求各自的进步,都要攀登实现个人价值的人生巅峰。</p> </li> </ul> 个人成长https://www.scarsu.com/the_road_less_traveled/#post-comment/月刊 | 信息源分类集合页https://www.scarsu.com/monthly_all/https://www.scarsu.com/monthly_all/分类整理 每月收集的信息源Sat, 01 Jan 2022 00:00:00 GMT<p><a>【月刊】分类集合页 https://scarsu.notion.site/b4ea0fb5a9ad4131b031205a8d2929f2 </a></p> 信息源https://www.scarsu.com/monthly_all/#post-comment/心流:最优体验心理学https://www.scarsu.com/psychology_flows/https://www.scarsu.com/psychology_flows/利用积极心理学,提升幸福感和效率。Sat, 25 Dec 2021 00:00:00 GMT<h2>前言</h2> <p><img src="/images/picgo/Snipaste_2022-01-18_18-01-41.png" alt="思维导图" /></p> <p><a>《心流:最优体验心理学》</a>的作者是心理学理论之父、积极心理学奠基人米哈里•契克森米哈赖。</p> <p>他在30年前,在大量案例研究基础上,开创性地提出了“心流”的概念。</p> <p>“心流”是指一个人完全沉浸在某种活动当中,那种全神贯注、投入忘我的状态。</p> <p>这种状态下,你甚至感觉不到时间的存在,在这件事情完成之后我们会有一种充满能量并且非常满足的感受。其实很多时候我们在做自己非常喜欢、有挑战并且擅长的事情的时候,就很容易体验到心流,比如爬山、游泳、打球、玩游戏、阅读、演奏乐器还有工作的时候。</p> <h2>人类不幸福的原因</h2> <p>作者之所以提出“心流”理论,离不开对“幸福”的研究。</p> <ul> <li>宇宙初创之时,就没有以人类的安逸舒适为念。</li> </ul> <p>大马哈鱼溯江而上,产卵后便死去。自然选择筛选出的这种机制为了繁衍连母体的生命都要牺牲,快乐在其中怎么能算得上重要的追求呢?</p> <p>人类性交快感为何这么短促?因为只要完成配种就够了。</p> <blockquote> <p>寻求快乐是基因为物种延续而设的一种即时反射,其目的非关个人利益。</p> </blockquote> <p>进食的快乐是为确保身体得到充足营养,性爱的快乐则是鼓励生殖的手段,它们实用的价值凌驾于一切之上。对异性的性趣只不过是肉眼看不见的基因的一招布局,完全在操纵之中。</p> <blockquote> <p>自然选择出的生理机制只是服务于人类生存繁衍,没有增加幸福快乐的考虑。</p> </blockquote> <ul> <li>空虚感、内在秩序的缺失(作者称之为<strong>精神熵</strong>)</li> </ul> <p>人类与动物的最大差别在于神经系统过于发达。</p> <p>感知和摄取更多的信息,无疑有利于人类生存。对外部情况不感知,当然更危险,但<strong>感知更多往往也更苦恼</strong>。</p> <p>动物中除了人以外,都不会自作自受,它们的进化程度还不足以感受沮丧和绝望,只要没有外来的冲突干扰,它们就能保持和谐,体验到人类称为心流的那种圆满。</p> <p>常言说:无知无畏。反之,多知多畏,多知多忧。于是焦虑增长。刚巧一切平安的时候呢?神经系统过于发达的人类偏偏又会感到枯燥无聊。</p> <p><strong>内在秩序的缺失</strong>,表现在某些人所谓的存在焦虑或存在恐惧等主观状况上。基本上,它是一种对生存的恐惧,一种生命没有意义、不值得继续的感觉。</p> <p>人类有一个超大的意识系统。意识系统需要秩序,其无序时人们会焦虑、烦躁。</p> <p>米哈里提出了<code>精神熵</code>:资讯对人们意识中的目标和结构的威胁,将导致内心失去秩序,处在混乱状态,内心一片混乱,熵值非常高。</p> <p>心流就是让内心的意识更有规律、更有秩序,是降熵的过程。</p> <ul> <li>永无止境的欲望</li> </ul> <p>世上大多数人的人生目标都很简单:平安地活着,养育一儿半女;如果可能的话,再加上那么一点儿舒适与尊严。</p> <p>只要基本的生存问题解决了,充足的食物和舒适的居所就立刻显得微不足道,新需求、新欲望会立即出现。</p> <p>生活越改善而越不满足的矛盾表明,<strong>提高生活品质是一件永远没有尽头的苦役。</strong></p> <p>设立新目标也没什么不好;但问题就在于一般人总把所有心力放在新目标上,不能享受现在,也因此与<code>知足</code>的快乐绝缘。</p> <p>外貌、金钱、权力、地位、财富,人类想追求的太多,却无人能达到完美。在无法同时满足太多要求的挫折之下,有些人干脆投降认输,躲进自己的小天地:培养一种高雅的嗜好、沉溺于酒精、消费、性欲、毒品。</p> <p>古代帝王的生活,比起现代人的生活品质,不值一提。</p> <p>但是尽管人类的物质力量增强了几千倍,在改善体验的内涵上却不见得有何长进。</p> <h2>如何应对不幸福:心流</h2> <p>上述总结了人类不幸福的原因,针对这几个原因,作者提出了“心流”理论。</p> <p>心流即一个人完全沉浸在某种活动当中,无视其他事物存在的状态。</p> <p>“心流”是改善体验,提升幸福感的关键。</p> <p>我们对自己的观感、从生活中得到的快乐,归根结底直接取决于心灵如何过滤与阐释日常体验。我们快乐与否,端视内心是否和谐,而与我们控制宇宙的能力毫无关系。</p> <p>只有学会掌控心灵的人,才能决定自己的生活品质;具备了这种能力,也就相当于接近幸福的境界了。</p> <p>最优体验有赖于时时刻刻用意识控制周遭事物,而要达到这种境界,唯有靠个人的努力与创意。</p> <p>心流是意识和谐有序的一种状态,在这种状态下,注意力集中,意识有了秩序,上述的“不幸福的原因”,自然就不存在了。</p> <h2>心流如何形成</h2> <h3>提高控制意识的能力</h3> <ul> <li>每个人都有控制意识的自由。</li> </ul> <p>我们通常将意识<em>化资讯为秩序</em>的那股力量称为“意图”。</p> <p>先天遗传或后天得来的意图,会按目标的高低排定重要性。政客可能认为政治改革比生命重要、普通人很根据身体的需要认为健康、长寿、美食、舒适生活更重要、英雄、圣人、疯子、罪犯也都会在其意识中排列出最重要的目标......这一切都证明了,<strong>意识可以遵循不同的目标与意图发展,每个人都拥有控制主观现实的自由。</strong></p> <ul> <li>意识是有限的</li> </ul> <p>神经系统在特定的时间内能处理的资讯极为有限。</p> <p>思绪必须井然有序,否则就会混乱。</p> <blockquote> <p>现阶段的科学知识已可以估计出中枢神经系统处理资讯的速限。大致而言,我们顶多能同时应付七组资讯,诸如分辨声音、影像、情绪或思想中可辨识的弦外之音等。由一组转换到另一组,至少需要1/18秒。从这些数字可以算出,大脑1秒钟顶多能处理126比特的资讯,1分钟是7560比特,1小时则大约50万比特。**一生若以70年计,每天有16小时的清醒时刻,一生中可处理的资讯便是1850亿比特。**这就是生活的全部——所有的思想、记忆、感觉与行动。这个数字听起来似乎很庞大,其实则不然。</p> <p>光是听懂他人说的话,就需要每秒钟处理40比特的资讯,意识的有限由此可见一斑。假设大脑的极限是每秒钟126比特,那么同时理解三个人的话,在理论上是可能的,但这样一来,我们就得把其他思想和感觉摒除在意识之外。比方说,我们就无法注意到说话者的表情,也不能考虑他们说话的动机,或注意他们的穿着打扮。</p> </blockquote> <ul> <li>意识使用率决定生活品质</li> </ul> <p>很多人没有充分发挥处理资讯的能力。大多数人在每天约占1/3的闲暇时间里,都尽可能避免用脑子,其中一半时间以上是消磨在电视机前。</p> <p>每个人一生中能处理的资讯有限,所以准许哪些资讯进入意识就显得格外重要。实际上,这就决定了生活的内涵与品质。</p> <ul> <li>注意力是“精神能量”</li> </ul> <p>控制意识最明显的指标就是能随心所欲地集中注意力,不因任何事情而分心。</p> <p>注意力负责从数以百万计位的资讯中挑出相关的资讯,以及从记忆中抽取相关的参考数据,然后评估事件,采取正确的对策。</p> <p>应用注意力的方式足以决定人生的外观与内涵。</p> <p>注意力除了决定某些事物能否进入意识外,还要带动其他心灵活动——回忆、思考、感觉、做决定,所以应该把注意力视为一种<strong>精神能量</strong>。</p> <p>它是完成工作不可或缺的能量,在工作中会耗损。我们通过这种能量的应用,创造自我;也通过应用的方式,塑造记忆、思想和感觉。</p> <p>注意力是一种受我们控制、随我们使用的能量变化而改变,也是改善体验品质的最重要的工具。</p> <ul> <li>生活的品质取决于控制意识的能力。</li> </ul> <p>痛苦与快乐都属于可意识的范围,而且只在意识中存在。</p> <p>一个人可以不管外界发生什么事,只靠改变意识的内涵,使自己快乐或悲伤</p> <p>“人害怕的其实是自己对事物的看法,而非事物本身。”</p> <p>生活的品质取决于控制意识的能力。</p> <h3>自寻目标与乐趣</h3> <p>集中注意力是造就心流的关键。而凝聚注意力需要一个目标。目标从何而来呢?</p> <p>在传统社会中,为百姓们提供人生目标的是社会权威:国王、主教、政府。他们提供的目标有:<strong>宗教、道德、阶级习俗、爱国主义</strong>。</p> <p>最后到来的一个目标提供者是商人,他们宣扬的是<strong>消费</strong>。</p> <p>这些目标渐渐失效,不再吸引众生。</p> <p>原因之一是,这些目标设置的动机是维护社会秩序、或者是鼓吹者自身的利益,更有利于宣讲者或统治阶层。</p> <p>社会将我们塑造成拼命工作与储蓄的公民、商人哄骗我们将辛苦赚来的钱消费、灰产与地下组织提供禁忌的快乐.....这些种种,都是为了剥削我们的精力,以满足其私欲或目标。</p> <p>因此,我们应该从<strong>社会制约</strong>与<strong>本能冲动</strong>下,解放意识,培养独立意识:</p> <ol> <li> <p>克服现代生活的焦虑与沮丧,从社会环境中独立出来,不再以社会的奖赏为念,试着以自己所能控制的奖赏取而代之。要在别人用以利诱我们的目标之外,另行建立一套自己的目标。</p> </li> <li> <p>不要屈服于出于人性和基因的本能反应,不要被肉体的欲望牵着鼻子走,控制本能的冲动。享受自然的乐趣并没有什么不好,但我们应该认清事实真相,在必要的时候,按照自己内心的优先顺序,做自己的主人。</p> </li> </ol> <h3>自寻乐趣</h3> <p>睡眠、休息、食物与性,都属于恢复“均衡”的体验,在肉体需求引起精神熵以后,重整意识的秩序。</p> <p>它们并不能带动心灵的成长,也不能增加自我的复杂性。换言之,享乐虽有助于维持意识的秩序,却无法在意识中创造新秩序。</p> <p>一味追求财富、地位、权力,未必能使人更快乐。唯有从每天的生活体验中创造乐趣,才能真正提升生活品质。</p> <p>改善生活品质的主要策略有两种:一是使外在条件符合我们的目标;二是改变我们体验外在条件的方式,使它与我们的目标相契合。</p> <p>如果要控制体验品质,就必须学习从每天的生活中创造乐趣。</p> <h3>有即时反馈,挑战要与能力匹配</h3> <p>所有心流活动,不论涉及竞争、投机还是其他形式的体验,都有一个共同点:它带来一种新发现、一种创造感,把当事人带入新的现实。</p> <p>简单地说,它把自我变得更复杂,自我因而成长,这就是心流活动的关键。</p> <p><img src="/images/picgo/picgo20211221151532.png" alt="意识复杂程度随心流体验渐增" /></p> <blockquote> <p>字母A代表艾利斯,一个正在学打网球的男孩,图形显示艾利斯学打网球的四个阶段。</p> <p>刚开始的时候,艾利斯不懂任何技巧,他唯一的挑战就是把球打过网去,这是A①。</p> <p>这种挑战没什么了不起,但艾利斯还是可能打得很愉快,因为难度正适合他粗浅的技巧。这时他很可能感受到心流,但为时不会太久。经过一段时间的练习,他的技巧进步了,他开始厌烦只是把球打过网去的动作(A②),</p> <p>或者他也可能碰到比他熟练的对手,使他发现球场上还有比高吊球更难应付的挑战——这时,他对自己拙劣的表现产生了焦虑(A③)。</p> </blockquote> <p>总而言之,可以造就心流的活动中必有挑战,且挑战应该是动态的。</p> <ul> <li>当挑战与你的技能匹配时,就有了心流。</li> <li>当挑战的目标大大高过你的技能时,将产生焦虑,那么就要提高技巧和能力,或者降低挑战目标。</li> <li>当你的技能高过设定的目标,继续持续这种活动将产生厌倦,那么就提高目标和挑战的难度,以求挑战和心流的持续。</li> </ul> <p>正是在技巧提高、目标上调的过程中,当事者感受到了成长的乐趣。</p> <h3>学会独处,屏蔽外界的干扰</h3> <p>一个人若能从独处中找到乐趣,必须有一套自己的心灵程序,不需要靠文明生活的支持——亦即不需要借助他人、工作、电视、剧场规划他的注意力,就能达到心流状态。</p> <p>一方面,独处是建立自己的内心系统的必要经历。</p> <p>另一方面,有了自己内心的系统,更能够适应因偶然原因陷入的孤独的处境中。</p> <h2>人生的意义:追寻人生的心流</h2> <p>如果一个人决心实现一个困难的目标,所有其他目标都是为这个大目标而存在,他就会投入所有精神能量,培养实现这一目标所需的技巧,那么所有的行动与感受就会形成蔚为和谐的整体,人生各个不同的部分也会契合无间。不论过去、现在,还是未来,每种活动都深具意义。在这种情形下,一个人的生命就有了意义。</p> <h3>培养方向感</h3> <p>每个人刚开始都只想到求生、保持身体及其基本目标的完整性,这时人生的意义很简单——就只是求生、求舒适、求享乐而已。</p> <p>当身体的安全得到充分保障后,一个人就可以扩张意义系统,包容家人、邻居、宗教或种族等团体的价值观。这一步骤虽然通常会要求个人认同传统的标准与规范,但仍能提升个人的复杂性。</p> <p>下一步发展又回到个人主义的反省。个人再次转向内心,从自我寻求权威与价值标准的新基础。他不再盲目认同,开始发展独立自主的善恶观念。这时人生的主要目标变为追求成长、进步和实现潜能。</p> <p>前面各步骤都已臻至圆熟,第四步才能展开,这是最后一次脱离自我,认同他人及宇宙共同的价值观。在这个阶段,极端个人化的人——就像修行功德圆满,听任河水控制船行方向的佛陀——终于心甘情愿让自己的利益融入大我的利益之中。</p> <h3>下定决心</h3> <p>在为一个目标投下大量精神能量之前,应该先提出几个基本问题:</p> <ul> <li>我真的想做这件事吗?</li> <li>做这件事会有乐趣吗?</li> <li>在可预见的将来,我仍然能从中得到乐趣吗?</li> <li>我和其他人,必须为它付出的代价值得吗?</li> <li>完成这件事以后,我还会喜欢自己吗?</li> </ul> 个人成长https://www.scarsu.com/psychology_flows/#post-comment/月刊#6 | 2021.08-12https://www.scarsu.com/monthly_6_2021_08-12/https://www.scarsu.com/monthly_6_2021_08-12/本文包含从2021年8月到12月,五个月之间,我收集到的信息和信息源,共16个类目:前端、开发与科技、话题、极简与低消费、Grow Up With You 指路人系列、读书、信息源、知识管理、Notion、有趣的网站、职场、投资理财与副业、种草、工具、设计与创作、生活与健康。Tue, 21 Dec 2021 00:00:00 GMT<h3>前端</h3> <ul> <li><a>政采云 | 如何写前端技术文档</a></li> <li><a>State Of CSS 2021</a></li> <li><a>V8编译浅谈</a></li> <li><a>前端面试八股文合集</a></li> <li><a>一个Three.js实例 | 3D看鞋</a></li> <li><a>文件下载9种场景</a></li> <li><a>在网页中实现裸眼3D</a></li> <li><a>Web Workers 2021现状分析</a></li> <li><a>微前端落地,悬着的心终于放下了</a></li> <li><a>如何搭建适合自己团队的构建部署平台</a></li> <li><a>中国计算机学会的前端会议,前端的发展与未来</a></li> <li><a>你真的了解package.json吗?</a></li> <li><a>前端零成本建站</a></li> <li><a>petite-vue</a> | 6KB 轻量迷你基本版 vue</li> <li><a>awesome-javascript</a> | 优秀前端库合集</li> <li><a>前端性能优化 | 9大策略和6大指标</a></li> <li><a>B站五面面经(附过程、答案)</a></li> <li><a>字节跳动的B面<em>详细解读</em>最新资讯_热点事件_36氪</a></li> <li><a>webpack 最佳实践-微医前端团队</a></li> <li><a>ES6复盘知识点</a></li> <li><a>如何成为优秀的大前端Leader</a></li> <li><a>滴滴前端博客</a>(核心成员<a>黄轶</a>)</li> <li><a>尤雨溪是怎么发布 Vue.js 的?</a></li> <li><a>上传文件夹的API</a> <code>HTMLInputElement.webkitdirectory</code></li> <li><a>前端异常监控和容灾</a></li> <li><a>css houdini</a> :js in css</li> <li><a>Vue3 源码中实用的基础工具函数</a></li> <li><a>http2 &amp; 前端</a></li> <li><a>每个前端都需要知道这些面向未来的CSS技术</a></li> <li><a>Github | Javascript进阶问题列表</a> - 39.8k star</li> </ul> <h3>开发 | 科技</h3> <ul> <li>“技术为业务而服务,不同的场景需要不同的工具,我们的任务就是找到最合适的工具并用好它。”</li> <li>知乎 | <a>探索Notion的实现</a></li> <li>少数派 | <a>2021:树莓派入坑指南</a></li> <li>树莓派实验室 | <a>用树莓派制造一个像样的 NAS</a></li> <li>树莓派实验室 | <a>Raspberry Pi中文资讯站,提供丰富的树莓派使用教程和DIY资讯</a></li> <li>开源 | <a>google面试算法题训练</a></li> <li>开源 | <a>MojoJS-Animation</a>:开源强大、轻量、易用的JS动画引擎</li> <li>政采云 | <a>你需要知道的项目管理知识</a></li> <li>字节 | <a>如何写开发设计方案</a></li> <li>文章 | <a>10款lowcode开发平台</a></li> <li>资源 | <a>编程电子书</a></li> <li>开源 | <a>可视化编程</a></li> <li>科技 | <a>研究人员教会培养皿中的脑细胞打乒乓球</a></li> <li>科技 | <a>双足机器人 Atlas 在表演流畅的跑酷</a></li> <li><a>Google代码审查指南</a>、 <a>中文版</a></li> <li><a>Google开发语言风格指南</a> - 29.4k star</li> <li><a>Google软件工程经验</a>、<a>中文版</a></li> </ul> <h3>话题🎙️</h3> <ul> <li>公开目标 | 公开之后就会有社会压力,你会感受到别人在看你。其实没有人会看,但这会让你对自己多一个旁观的视角,让你能好好审视自己。</li> <li>自省 | ”在愚昧之峰狂欢,在信息孤岛独舞,在一滩死水里永世长存“以此提醒不要太固执、太自信、太墨守成规、<a>邓宁-克鲁格效应</a></li> <li>吃苦 | 高级的吃苦能力,不是单纯的忍受贫穷、耗费体力,是一种自控能力。长时间聚焦于一件事情,没有无效社交 没有无意义的消费 没有娱乐生活 忍受孤独。</li> <li>视频推荐 | <a>不要活在别人的评价体系中</a> - 小唯up</li> <li>视频推荐 | <a>社恐自救指南</a>: be yourself is cool enough、别人怎么对待你,是你自己交给别人的 - 小唯up</li> <li>视频推荐 | <a>HSP自救指南</a>:接纳自己、停止过度共情、精简社交 - 小唯up</li> <li>文章 | <a>46 六个对我影响最大的效率习惯</a></li> <li>文章 | <a>如何提升自己的幽默感?</a></li> <li>文章 | <a>我们为什么爱郑渊洁?</a>:犀利有度、幽默加持</li> <li>文章 | <a>为什么你需要一个自己的网站</a>:拥有品牌和属于自己的听众、回避审查、掌握数据、避免骚扰、长期经营,享受长远复利</li> <li>文章 | <a>外圆内方</a> 、<a>思维导图</a></li> <li>少数派 | <a>每年更新一次遗嘱、数字遗产保护</a></li> <li>少数派 | <a>如何追求精力充沛的生活</a></li> <li>少数派 | <a>DPS 周刊 01 - 如何努力?</a></li> <li>少数派 | <a>目标这个 Flag,是对自己的承诺</a></li> <li>性别差异 | <a>中华人民共和国妇女权益保障法(修订草案)</a></li> <li>性别差异 | <a>韩国作家孙雅兰演讲《性别歧视的代价&amp;逆向性别歧视》</a></li> </ul> <h3>极简 | 低消费🛒</h3> <ul> <li>极简主义 | <a>在极简中寻找平衡</a></li> <li>理性消费 | 自问“这种东西你买了你不觉得亏吗”</li> <li>低消费主义 | 承认并管理<a>生活方式的膨胀</a></li> <li>低消费主义 | <a>豆瓣低消费研究所小组</a>创建人小松悠:买东西不是为了快乐,我所认为的消费就是正常的因需购买”</li> </ul> <h3>Grow Up With You 指路人系列🤝(世上没有任何一人是绝对善恶,请择善而从</h3> <ul> <li><a>两个站在时代风口的首富:世界首富马斯克、”中国新首富”币安赵长鹏</a></li> <li><a>TomKeeper</a></li> <li><a>v站一位前端前辈的简历</a></li> <li><a>于航</a></li> <li><a>掘金前端卷王</a>(年终总结都卷到提前一个月发😅</li> </ul> <h3>读书📔(开卷有益</h3> <ul> <li><a>《心流》| 最优体验心理学</a></li> <li><a>《高敏感是种天赋》 | HSP人群必读</a></li> <li><a>书单 | 豆瓣2021年度图书榜单</a></li> <li><a>书单 | 看了十张年度书单,我挑选出这 16 本不容错过的好书 - 少数派</a></li> <li><a>书单|澎湃新闻编辑们推荐的2021年度十大好书</a></li> <li><a>书单 | 2020 多抓鱼鲜鱼榜</a></li> </ul> <h3>信息源📑</h3> <ul> <li><a>掘金八大分类百强文章可视化分析</a></li> <li><a>抖音数据</a></li> <li>国外社区 | <a>顶流论坛Reddit、优质内容平台Medium、国外版知乎问答社区Quora</a></li> <li><a>国内外行业报告查询网站集合</a></li> <li>播客 | <a>一派·再读 Feed</a></li> </ul> <h3>知识管理📑</h3> <ul> <li><a>Cubox 6.0 | 全能网络收藏夹、语音、视频、速记 - 少数派</a></li> <li><a>一个文科博士生的资料管理、阅读和笔记系统-基于 DEVONthink 3,Obsidian - 少数派</a></li> <li><a>一个“阅读工作流”例子</a> | 信息源-&gt;稍后阅读-&gt;划线批注-&gt;临时笔记-&gt;永久笔记(知识库)-&gt;回顾系统-&gt;创作输出</li> <li><a>一个(自动化)信息流管理的案例</a></li> </ul> <h3>Notion📑</h3> <ul> <li>Notion 2.11 更新日志 <a>What's New?</a> (sync block、ifttt api、<a>https://www.integromat.com/en/integrations/notion</a>)</li> <li><a>Notion (Beta) works better with IFTTT</a></li> <li><a>Request page data for Next.js from the Notion API | egghead.io</a></li> </ul> <h3>有趣的网站🪀</h3> <ul> <li>解压 | 声音视觉动效网站<a>Patatap</a> 、 <a>初音未来版</a></li> <li><a>镜像式炫光生成器</a></li> <li><a>乐器模拟器</a></li> <li><a>io游戏站</a></li> <li><a>茶杯狐</a></li> <li><a>小霸王其乐无穷</a></li> <li><a>随机带你去一个没用的网站</a></li> </ul> <h3>职场💼</h3> <ul> <li><a>如何应对变相裁员</a></li> <li><a>如何看一个人有没有领导力</a></li> </ul> <h3>投资 | 理财 | 副业💰</h3> <ul> <li>投资理财 | <a>普通人如何有效投资理财? - 少数派</a></li> <li>远程工作 | <a>UpWork:打字、翻译、客户支持、开发</a></li> </ul> <h3>种草🛍️</h3> <ul> <li><a>编程工作适合用什么鼠标? - V2EX</a></li> <li><a>腾讯云羊毛 :云开发Webify个人网站扶持</a></li> <li>Ipad端 图形创作APP:Lazyshare 搭配 Procreate</li> <li>路人:联通 500M 宽带 包年 700 咸鱼租的</li> <li>路人:中国移动 300 Mbps 家庭宽带套餐,首年资费 39 元 /月,次年 30 元 /月,套餐含 5GB 4G 流量。2 年合约期。</li> </ul> <h3>工具🔧</h3> <ul> <li>小程序 | <a>极客词典</a>:中国互联网超爱读错的单词</li> <li>浏览器 | <a>管理浏览器插件的插件</a></li> <li>浏览器 | <a>ImageAssistant</a>图片助手:自动提取网页图片、批量下载、以图搜图</li> <li>Windows工具 | <a>抖音无水印下载用户视频</a></li> <li>Android | <a>Auto.js脚本 安卓设备重复性操作</a></li> <li><a>PowerToys</a>:微软官方Windows系统工具、文件管理器插件、分屏</li> <li><a>Snnedacity</a>:开源免费的音频编辑工具</li> <li><a>DataEase</a>:开源数据可视化分析工具</li> <li><a>App Star Walk 2</a>:打开AR 相机对着天空 就能识别出星空</li> <li><a>Potplayer</a>:全网最强 播放器</li> <li><a>RustDesk</a>:免费的 开源的 远程桌面软件</li> <li><a>全国移动电话卡“一证通查”</a></li> <li><a>万有导航</a></li> </ul> <h3>设计 | 创作✍️</h3> <ul> <li><a>非设计师也该学的排版知识:视觉动线 - 少数派</a></li> <li><a>用好 Keynote 和 iMovie,在 iPad 上做出有高级感的视频 - 少数派</a></li> <li><a>想做视频?这里有一份入门到进阶知识完整指南 - 知乎</a></li> <li><a>Youtube运营者必备12个工具</a></li> <li><a>图片处理App|VSCO 用了六年的照片调色 App</a></li> <li><a>手绘插画库/人物库</a></li> <li><a>图片特效生成器</a></li> <li><a>网站 | 人像转卡通</a></li> </ul> <h3>生活 | 健康🏃</h3> <ul> <li>少数派 | <a>你的家庭小药箱,从这 8 种非处方药开始</a></li> <li>体检 | <a>你该掌握的自查手段</a></li> <li>保健 | <a>提升好胆固醇, 降低坏胆固醇</a></li> <li>住房 | <a>筛选房源的第一步,读懂户型图</a></li> <li>装修 | <a>三万字装修经验「验收」</a></li> <li>服装 | <a>我们需要学习的挑选与购买</a></li> </ul> 信息源https://www.scarsu.com/monthly_6_2021_08-12/#post-comment/逆商:我们该如何应对坏事件https://www.scarsu.com/aq_adversity_quotient/https://www.scarsu.com/aq_adversity_quotient/及时止损永远是糟糕状态下的最优选择。Wed, 15 Dec 2021 00:00:00 GMT<h3>前言</h3> <p><a>豆瓣链接 - 《逆商》</a></p> <p>以前我觉得消极、积极的态度,来自于身处的环境和人的内在性格,是很难改变的。</p> <p>读了这本书之后,才意识到自己过去对待事物的消极态度,其实完全没有必要、没有意义。</p> <p>如书中所说,“我们无法选择身处的时代和环境,唯一能选择的是如何有效和积极地去应对“。</p> <p>及时止损永远是糟糕状态下的最优选择。</p> <p><img src="/images/picgo/20230709103001.png" alt="封面" /></p> <h3>逆商是什么</h3> <p>众所周知,<code>IQ</code>是<code>智商</code>,是一个人在其年龄段的智力和认知能力。</p> <p><code>EQ</code>是<code>情商</code>,是一个人认识、了解、控制情绪的能力。</p> <p>而<code>AQ</code>是<code>逆商</code>,即<code>Adversity Quotient</code>,能反映出一个人抵御、应对、战胜逆境的能力如何。</p> <h3>为什么要提升逆商</h3> <ul> <li>人生就是会面临一个又一个逆境</li> </ul> <p>从最轻微的挫折到最惨烈的悲剧都算上,你通常一天会遇到多少大大小小的难题?</p> <blockquote> <p>我和我的研究团队在1991年开始收集这个问题的答案时发现平均数量是三个。如今,这个问题的全球平均答案数是32个,而且这一数字还在上升。</p> </blockquote> <blockquote> <p>在大多数社会里,深受焦虑、无助、失眠、抑郁甚至是自杀倾向之苦的人数持续攀升。</p> </blockquote> <p>我们从出生起,就要面临各种问题:幼童时学步要面临不断地摔跤、青年时要应对各种学业课程、成年后要面临各种人际关系的矛盾、工作事务的难处、社会生活的压力。</p> <ul> <li>我们身处在逆境时代</li> </ul> <p>我们处在一个<code>RUPT</code>时代,即急速、莫测、矛盾、缠结。</p> <p>全球变暖情况持续加重、海平面持续上升;</p> <p>信息化、国际化使全球各个国家的关系越来越紧密、纠缠,经济战使经济环境变得更难预测;</p> <p>新冠病毒带来的疫情经久不衰、影响范围持续扩大;</p> <p>不论是个人健康、家庭生活、职场经济和社会,随时都可能将各种难题抛到我们面前,必须应对。</p> <ul> <li>提高逆商,那么生活的各个方面就会渐渐改善:</li> </ul> <p>提升活力、幸福感,对心理健康有益(因逆境而受伤的人容易感到无助,转而觉得抑郁);</p> <p>提升学习能力(积极的心态有益于保持冷静、充满活力的学习状态);</p> <p>提升竞争力、生产力、创造力、动力、毅力、韧性;</p> <p>提升身体健康,多项研究表明心理健康对身体健康有一定的影响,人的想法和感受与其体内的活动有着直接而显著的联系,传递人类情绪的化学物质会直接影响人类的身体健康,在压力面前表现得非常抑郁和焦虑的人,其体内的白细胞要弱得多。</p> <h3>如何提升逆商</h3> <ul> <li>告别习得性无助</li> </ul> <p>习得性无助是指将“做什么都没有用”这一想法内化,从而削弱一个人的掌控感。</p> <blockquote> <p>科学家塞利格曼做过两个实验。 在第一阶段,A组的狗被背带绑住并受到轻微电击。它们可以用鼻子去按控制杆,让电击停止。很快它们就学会这样做了。 B组的狗也是被同样的背带绑住并受到同样的电击,但它们无法让电击停止。这些狗只能忍受痛苦。 C组是对照组。C组的狗被背带绑住,但没有受到电击。</p> <p>第二天,塞利格曼进行实验的第二阶段。他将这些狗逐个放进一个叫作穿梭箱的装置里,这个箱子中间立着一块低矮的挡板。每只狗都被放到挡板的一侧并受到轻微电击。它们只需要跨越矮挡板跳到另一侧就能停止电击。 A组的狗(可以控制电击)和C组的狗(没有受到电击)很快就明白怎样跨越挡板,摆脱不适。 但B组的狗(不能控制电击)则有不同的反应,它们躺下来呜咽啜泣,没有尝试逃脱。</p> <p>塞利格曼等人发现,这些狗学会了无助,这一行为几乎摧毁了它们采取行动的干劲。 此后,科学家还发现,猫、鱼、狗、大鼠、蟑螂、小鼠和人类都能学到这一特性。</p> </blockquote> <p>不要将一件事情带来的消极情绪带入到其他事情中。</p> <ul> <li>不要扮演受害人的角色</li> </ul> <p>扮演受害者,是人类自我防御机制的一种方式。</p> <p>将责任推到外部环境,就有借口放弃掌控力、放弃自我努力。</p> <ul> <li>乐观的归因风格</li> </ul> <p>如果一个人认为逆境是永久的(“这永远不会改变”)、普遍的(“我会把所有的事搞砸”)和个人的(“这都是我的错”),那这个人就会拥有悲观的归因风格;</p> <p>如果一个人认为逆境是<code>暂时的</code>、<code>外在的</code>和<code>有限的</code>,那这个人则拥有乐观的归因风格。</p> <p>一个人的成功,很大程度上是由他归因或应对生活事件的方式所决定的。</p> <ul> <li>建设性应对逆境</li> </ul> <p>处理事情时考虑如何应对,而不是担心哪里会出问题。</p> <ul> <li>止念法</li> </ul> <p>改变潜意识的行为和习惯,在自己的消极想法和悲伤蔓延时,及时制止自己,例如:转移注意力、运动、用力拍手喊“停”、用手腕上的小皮筋弹自己一下、访问自己的初衷和目标是什么、等等...</p> <p>停止灾难化,不要因为一个逆境,就臆测“一切都完了”。</p> <p>把假设和事实区分开,停止无助的臆测,将逆境的影响范围最小化。</p> <ul> <li>放大格局</li> </ul> <p>凝视无垠的海洋或天空会让你意识到,在浩瀚的宇宙面前,自己的问题是多么地微不足道。</p> <ul> <li>LEAD法</li> </ul> <p>L= Listen,倾听自己的逆境反应:自己当下应对逆境,表现了高逆商还是低逆商?</p> <p>E= Explore,探究自己对结果的担当:我应该对结果的哪些部分担起责任?</p> <p>A= Analyze,分析证据:有什么实际证据可以表明此次困境脱离了我的掌控、一定会蔓延到生活的其他方面?</p> <p>D= Do,做点事情:搜集信息、列出行为清单,如何及时止损、如何控制此次逆境的影响范围和结果?</p> <hr /> <p>生活是艰难的,但你应对生活的方式决定了你的命运</p> 个人成长https://www.scarsu.com/aq_adversity_quotient/#post-comment/怦然心动的人生整理魔法笔记https://www.scarsu.com/life_reorganize/https://www.scarsu.com/life_reorganize/整理是一个发现自己、认清自己、复盘人生的过程,你所拥有的物品会准确地诉说你做过的所有选择Fri, 03 Dec 2021 00:00:00 GMT<p><img src="/images/picgo/picgo20211203174148.png" alt="封面" /></p> <h3>豆瓣链接</h3> <p><a>《怦然心动的人生整理魔法》</a></p> <h3>笔记大纲</h3> <p><img src="/images/picgo/picgo20211203173926.png" alt="笔记大纲" /></p> <h3>思维导图</h3> <p><a>文件链接</a></p> 个人成长https://www.scarsu.com/life_reorganize/#post-comment/极简主义:如何用更少的东西过更有意义的生活https://www.scarsu.com/minimalim/https://www.scarsu.com/minimalim/充满热情和自由,实现个人成长、以有意义的方式为他人做出贡献Fri, 22 Oct 2021 00:00:00 GMT<h2>关于《极简主义》这本书</h2> <p><a>《极简主义》豆瓣链接</a></p> <p><img src="/images/picgo/picgo20211022184503.png" alt="《极简主义》" /></p> <p>这本书的作者是乔舒亚和瑞安,曾经是两个年薪六位数(美元)的美国职场精英,拥有香车、豪宅、昂贵服装及大量玩物。</p> <p>但是他们对这种“一周工作七八十个小时、买更多东西”的生活感到不满足、焦虑又空虚,于是开始了极简主义。</p> <p>我最初对极简主义的印象,来自于扎克伯格满衣柜的灰色同款衣服,和乔布斯平生不变的穿搭</p> <p><img src="/images/picgo/picgo20211022144109.png" alt="扎克伯格的衣服" /></p> <p><img src="/images/picgo/picgo20211022145246.png" alt="乔布斯的穿搭" /></p> <p>但是这本书介绍的极简主义,<strong>重心不是在如何扔东西、如何降低物欲,而是如何过更有意义的生活</strong>。</p> <p>答案就是关注人生中最重要的五个方面:<strong>1.健康 2.人际关系 3.热情 4.成长 5.奉献</strong></p> <h2>快乐源自内心,而不是物质财富</h2> <p>我们处在被商业营销充斥的环境:<em>各种购物app创造了接连不断的购物节,短视频app不停的推送带货直播,微博、知乎、b站、小红书充斥着商业广告;下班回家路上有各种广告牌,小区电梯有24h不间断播放的广告视频,回家开门还时不时发现门把手被塞上了小广告......</em></p> <p>商家在营造一种购物、消费就能让我们生活更幸福的假象。</p> <p>但全世界的商家、营销的根本目的是赚钱,而不是我们的幸福快乐。</p> <p>每次购物会带来些许快感,但是它会瞬间消散。</p> <p>如果要依赖物质带来快乐,随着边际效应递减,获得快乐的阈值会越来越高,我们只会走向对金钱永无止境的追逐。</p> <p><img src="/images/picgo/picgo20211022173507.png" alt="消费陷阱" /></p> <p>所以,<strong>快乐不是来自金钱、物质,而是来自于内部、来自我们的内心</strong>。</p> <p>那么如何去追寻内心的快乐呢?</p> <p>答案就是追寻有意义的生活。</p> <blockquote> <p>如果我们的短期行为和长期价值相符,那么我们就会在自己所做的所有事情中找到意义。</p> <p>矛盾的是,这种生活方式(有意识的生活)才会带领我们走向真正的幸福快乐。</p> <p>不是转瞬即逝的欢愉,而是长久的满足,来自自律、专注、觉知、目的明确的生活。</p> </blockquote> <p><strong>过有意义的生活,快乐自然而然会成为副产品</strong>。</p> <blockquote> <p>我们在这世上只有有限的时间,</p> <p>这些时间可以用来积攒金钱财富,也可以花在有意义的事情上。</p> <p>后者不一定会妨碍人们追求前者,</p> <p>但对财富永无止境的追求并不能将我们带向有意义的生活。</p> </blockquote> <h2>为有意义的生活 清除障碍</h2> <p>当我们意识到“快乐不是来自金钱、物质,而是源自内心”这个真相后,</p> <p>就能发现我们身边充斥了许多事物,也许阻碍了我们自由地追求有意义的生活。</p> <p>例如,需要大量时间却没有给生活增添相应价值的东西:</p> <ul> <li>房子(和随之而来的大笔按揭还贷)</li> <li>某些人际关系(没有为我们的生活增添价值的不健康关系)</li> <li>汽车贷款和其他大额账单、</li> <li>大笔债务、</li> <li>我们的事业</li> <li>...</li> </ul> <p>会消耗我们时间和注意力的小事:</p> <ul> <li>有线电视费、</li> <li>网费、</li> <li>其他账单、</li> <li>小额债务、</li> <li>不穿的衣服、</li> <li>没用的家居用品、</li> <li>家庭杂物、</li> <li>某些徒劳的次要关系、</li> <li>日常的开车时间</li> <li>...</li> </ul> <p>上面举了一些例子,抛弃这些对我们不重要的事物、财物,扔掉多余的东西,</p> <p>只留下我们喜欢和享受的、那些在日常生活中实实在在用得到的东西。</p> <p>当达到物质上的极简后,就会发觉自己必须去追求精神上的富足。</p> <p>摆脱混乱的身外之物,就会有足够的时间和精力,去实现有意义的人生:<strong>充满热情和自由的人生,可以实现个人成长、以有意义的方式为他人做出贡献的人生。</strong></p> <h2>健康</h2> <p>健康是生命的基础。</p> <p>虽然疾病与死亡不可避免,但是我们仍然应该在自己力所能及的范围内过着最为健康的生活。</p> <p>书中给出了具体的建议:</p> <ul> <li>不吃加工食品、包装食品、糖、甜品</li> <li>少吃麸质、面包;少喝水以外的一切饮料</li> <li>多吃自然果蔬、豆类、鱼类</li> <li>坚持运动</li> </ul> <h2>人际关系</h2> <p>人际关系能满足最基本的人类情感需求。</p> <p>不好的、不必要的人际关系会浪费我们大量的时间和精力、甚至会伤害我们的情感。</p> <p>有三种方法可以建立更好的关系:</p> <ul> <li>评估现有关系,舍弃掉不必要的,无法给你带来价值的关系。</li> <li>寻找超棒的新人际关系。确定自己寻求的是什么?想要避免的是什么?为了想要的管旭你又必须让自己改变什么?</li> <li>改造你现有的人际关系,花更多时间维护。</li> <li>改变你自己,以身作则影响身边的人、吸引同类的好的人际关系。</li> </ul> <h2>热情</h2> <p>热情,有所热爱才会感到充实。</p> <p>找到自己真正感兴趣的事物,专注地投入热情和热爱。</p> <p>找到至少三个以你的爱好谋生的人,找到正在做你想做的事情的人,向他们学习,吸收他们的知识经验,然后大步行动。</p> <h2>成长</h2> <p>成长,持续进步而不是停在原地。</p> <p>我们生命的意义:实现个人成长,为他人做出贡献。</p> <p>想要长久的幸福,就必须继续做出改变。</p> <p>你的多数改变,都是通过每天在小的方面逐渐改善积累而成的。</p> <h2>奉献</h2> <p>成长和奉献相互成就,为自己添加人生价值</p> <blockquote> <p>你越成长,就越能帮助其他人成长;而越是帮助他人成长,你自己就越能获得更多成长。</p> </blockquote> <h2>总结</h2> <p>可以通过一个简单的等式来衡量自己在五大价值的各个方面是否成功:</p> <p><code>成功 = 快乐 + 持续进步</code></p> <p>为五大价值中某个方面的现状感到快乐,而且持续地进步着,那么你在这一领域便是成功的。</p> <h2>看完书,然后做什么?</h2> <p>行动。</p> <p>从你的物品开始。</p> <ul> <li>精简你的壁橱/抽屉。</li> <li>献出时间去帮助他人。</li> <li>把你的东西捐献给慈善机构。</li> </ul> <p>从你自己开始,以身作则。</p> <ul> <li>改变你的习惯。</li> <li>改变你的消费观念。</li> <li>改变你的饮食习惯、锻炼方式。</li> <li>找回你的时间。</li> <li>追求你的爱好。</li> <li>找到你的使命。</li> </ul> 个人成长https://www.scarsu.com/minimalim/#post-comment/最好的告别:如何优雅地走向生命终点https://www.scarsu.com/being_mortal_update_210902/https://www.scarsu.com/being_mortal_update_210902/无论我们面临怎样的局限和阵痛,我们都希望保留 我们作为自己生活篇章的作者 的自主和自由。Tue, 31 Aug 2021 00:00:00 GMT<h2>我最期望的死法</h2> <p>《人生果实》是我最喜欢的纪录片,讲述了日本建筑师津端修一夫妇的隐居生活。</p> <p><img src="/images/picgo/picgo20210901143845.png" alt="" /></p> <p>片中的老夫妻一个90岁,一个87岁,他们的老年生活令我羡慕不已,种树、种菜、种花、种水果、做甜品、做饭、自给自足......</p> <p>纪录片拍到一半的时候,90的老爷爷去世了。</p> <p>像往常每个午后一样,他安详的躺在床上午休,再也没有醒来。</p> <p>以前的我总是不敢想象自己和身边人的死亡,但是纪录片看到这的时候,我就在想,既然死亡不可避免,那么希望所有人告别人世时,都能像老爷爷这样安详、体面。</p> <h2>坦然地聊聊死亡</h2> <p><strong>死亡</strong>是一个沉重的话题,但是看完《最好的告别》这本书后,也许能更加坦然的面对这个话题。</p> <blockquote> <p>死亡本身是可怕的。</p> </blockquote> <p>人类历史发展30万年,数不清的灵魂诞生、消逝,无一逃脱死亡的命运。</p> <p>现代医学再怎么发愤图强,依然无法摆脱一个很确定的结局,那就是永远也无法战胜死神。</p> <blockquote> <p>死亡的未知性更令人恐惧。</p> </blockquote> <p>谁也无法预知自己的死亡时间、死亡方式。</p> <p>中国近年死亡人口的2/3是正常死亡,其中主要包括癌症、心脑血管疾病、呼吸系统疾病、新生儿疾病、阿尔兹海默症与痴呆等;1/3是非正常死亡,其中主要包含自杀、交通事故、工伤事故、刑事案件死亡、中毒死亡、自然灾害等。</p> <p>我们都希望能像纪录片中老爷爷一样善始善终,但是也应该对衰老、疾病和意外做好心理准备。</p> <p>如果未知是令人恐惧的,那么了解衰老与死亡就是我们克服恐惧的必修课。</p> <h2>关于本书</h2> <p>《最好的告别》是一本关于死亡的书,作者是哈佛大学医学院的外科教授。</p> <p>这本书梳理了作者所处的美国社会养老的发展历程、医学界对末期病人的不当处置、医药的局限性。</p> <p>但更多地,作者详尽地说明了“善终服务”、“辅助生活”、“生前预嘱”的理念</p> <p>通过这些理念,我们能找到这些问题的答案:</p> <ul> <li>当独立、自助的生活不能再维持时,该怎么办?</li> <li>在生命临近终点时,该和医生谈些什么?</li> <li>如何优雅地跨越生命的终点?</li> </ul> <h2>衰老的真相</h2> <blockquote> <p>生命老化的故事就是身体器官走向衰竭的故事</p> </blockquote> <p>牙齿、骨头软化脆弱,心脏、血管、关节、肺部变硬,肌肉流失,器官运行速度减缓,记忆力减退,感官退化。</p> <p>饮食有限制,行动有限制,听觉、视觉、触觉减弱,还有一定可能性患上痴呆。</p> <p>外表上的变化也很明显,但相比于健康,已不是最重要的事情。</p> <blockquote> <p>衰老是我们的宿命,死亡总有一天会降临。</p> </blockquote> <p>书中说高龄老人们害怕的并不是死亡,而是那之前的种种状况——丧失听力、记忆力,失去最好的朋友和固有的生活方式。</p> <blockquote> <p>老年是一系列连续不断的丧失</p> </blockquote> <p>凭着<strong>运气和严格的自我控制</strong>(注意饮食、坚持锻炼、控制血压、在需要的时候积极治疗),人们可以在很长一段时间内掌控自己的生活。</p> <p>但是,最终所有的丧失会累积到一个点</p> <p>到这个点时,我们会有相当长的一段时间由于身体太衰老、太虚弱而<strong>无法独立生活</strong>。</p> <p>我们不愿意思考这种可能性,结果,大多数人都没有为之做好准备。</p> <h2>过度治疗</h2> <p>一个理智的人在死亡降临的时候还是无法舍弃求生的欲望</p> <blockquote> <p>拉扎罗夫,一位市政府的行政官,60多岁患上转移性的癌症。病中癌症扩散到了胸椎,对脊椎形成压迫,右腿无法动弹,大便失禁。</p> <p>癌症此时已经无法彻底治愈。医生给了两个方案:一是安宁缓和医疗;二是实施手术,切除脊椎处生长的肿瘤包块。</p> <p>尽管手术风险很高,他依然选择了手术,“别放弃我,”他说,“只要我还有任何机会,你们一定要让我尝试。”</p> <p>他的妻子死在监护室里,死的时候全身插满了管子,戴着呼吸机。</p> <p>当时,他曾经说过,他绝不想这样的情形发生在他的身上。但是,时至今日,他却坚决要求采取“一切措施”。</p> <p>从医学技术角度看,手术达到了切除肿瘤的目的,但是他一直没能从手术中恢复过来。</p> <p>他住在监护室,并发了呼吸衰竭、系统性感染,卧床不动又导致了血栓,然后,又因治疗血栓的血液稀释剂而引起了内出血。</p> <p>第十四天,他的儿子告诉医疗组,我们应该停止“治疗”了。</p> <p>医生取出了他嘴里的呼吸管,他咳了几声,眼睛睁开了一小会儿,然后又闭上了。他的呼吸变得越来越吃力,然后终止了。</p> </blockquote> <p>这是书中的真实案例,显然,故事的主人公还没有做好死亡的心理准备。</p> <p>随着现代医疗的发展,像他一样死亡在医院的人越来越多,他们希望这个世界竭尽全力地留住他,但是医疗无法战胜死亡。</p> <p>这是临终病患中最为普遍的情况,拼命抵抗,牺牲病人的生存质量,通过手术、化疗、把他们送到监护室。于是,死的时候,血管里留着化疗药物,喉头插着管子,肉里还有新的缝线。</p> <blockquote> <p>2008年,美国全国抗癌协会发表的研究表明,使用呼吸机、电除颤、胸外按压,或者在临死之前入住监护室的末期癌症患者,其生命最后一周的质量比不接受这些干预措施的病人差很多。在去世之后 6周,他们的照料者患严重抑郁的可能性大了三倍!</p> </blockquote> <p><strong>过度的技术干预</strong>增加了对逝者和家属的伤害,剥夺了他们最需要的<strong>临终关怀</strong>。</p> <h2>临终关怀</h2> <p>当一个人已经无法避免地走向死亡,任何治疗都无法阻止这一过程,甚至会伤害到当事人时,</p> <p>采取<strong>姑息疗法</strong>(不加速也不拖延死亡),只减缓疾病症状,提升病人的心理和精神状态,</p> <p>可以让生命的最后一程走得完满有尊严。</p> <blockquote> <p>临终关怀不是等死,而是好好的走到终点</p> </blockquote> <p>临终关怀并不是放弃,而是给予当事人尊严、舒适感、控制感和有质量的生命。</p> <p>除了单纯地延长生命之外,重病患者还有其他的优先考虑事项。</p> <p>调查发现,重病患者的主要关切包括<strong>避免痛苦、加强与家人和朋友的联系、意识清醒、不成为他人的负担,以及实现其生命具有完整性的感觉</strong>。</p> <p>所以,临终关怀应该做的有:</p> <ul> <li>放弃过度治疗,关注他们的疼痛感,护理、照顾他们的生活</li> <li>维护他们的尊严,尊重他们的意见和选择</li> <li>共同面对死亡,帮助他们完成最重要的心愿</li> </ul> <h2>现在能做什么</h2> <h3>正视死亡</h3> <p>在中国,我们的传统教育和思想,让我们避讳死亡的话题。</p> <p>我的外婆在2018年初头疼,查出肺癌晚期,已经脑转移,在脑部形成大大小小的肿瘤,家人们不敢告诉她真相,安慰她一定会治好。后来带她辗转医院,住院,接受放疗和药物治疗,外婆精神渐渐不清醒,我自始至终不知道,外婆是否知道自己的情况很糟糕,但直到去世,都没有人能够和外婆坦诚地聊一聊死亡。</p> <p>2018年底外婆就走了,外婆不吸烟也没有长期生活在坏空气中,无论是诊断出肺癌晚期还是去世,对我们来说都太突然了。</p> <p>那是我身边第一次有人去世,我后知后觉,但凡当时能在她还清醒时,和她聊一聊她的心愿、情绪、遗憾、对我们的期望,妈妈和小姨失去母亲的痛苦都能减轻一分,我们对外婆的遗憾也不会留存终生。</p> <h3>从死亡的视角 重新考量我们的现在</h3> <p>当你年轻、身体健康的时候,你相信自己会长生不老,从不担心失去自己的任何能力,周围的一切都在提示你“一切皆有可能”。你愿意延迟享受,比方说,花几年的时间,为更明媚的未来获取技能和资源。你努力吸收更多的知识和更大的信息流,扩大自己的朋友圈和关系网,而不是和妈妈黏在一起。当未来以几十年计算(对人类而言这几乎就等于永远)的时候,你最想要的是马斯洛金字塔顶端的那些东西——成就、创造力以及“自我实现”的那些特质。</p> <p>但如果面临死亡的境遇,你的视野会收缩,你开始觉得未来是有限的、不确定的,你的关注点开始转向<strong>此时此地</strong>,放在了日常生活的愉悦和最亲近的人身上。</p> <blockquote> <p>生活是一种技能。老年的平静和智慧是在时间历程中实现的。</p> </blockquote> <p>随着年龄的增长,我们从在意<strong>实现、拥有和得到</strong>转而懂得<strong>欣赏日常生活的愉快和亲密关系</strong>,如果我们发现这更具满足感,那么,为什么我们要等这么久才去做?为什么我们要等到老了才去做?</p> <blockquote> <p>每个早晨我都对着镜子自问, 假如今天是我生命的末日, 我还会想去做 我今天打算做的事情吗? 如果连续几天我的回答都是“No” 我就明白,我需要改变了。 记住“你即将死去”,会使你受益匪浅。</p> </blockquote> <p>这是乔布斯在斯坦福的演讲说过的话,从死亡的视角重新考量我们当下的生活,也许可以让我们找到真正想做的事情。</p> <hr /> <blockquote> <p>如果我明天死去,我也已经度过了愉快的一生。我能做的事都做了,想做的事都做了。</p> </blockquote> <p>希望在我临终前,可以说出这句话。</p> 个人成长https://www.scarsu.com/being_mortal_update_210902/#post-comment/月刊#5 | 2021.07https://www.scarsu.com/monthly_5_2021_07/https://www.scarsu.com/monthly_5_2021_07/信息流管理、话题推荐、开发资源、Chrome图片工具Thu, 01 Jul 2021 00:00:00 GMT<h2>【Grow Up With You】指路人系列</h2> <ul> <li><a>Mike Shakes</a>:从0开始自学一切</li> </ul> <h2>信息流管理</h2> <ul> <li><a>一个(自动化)信息流管理的案例</a></li> <li>RSS收集:大多数网站都有RSS源;没有RSS的网站可以上<a>rsshub</a>、<a>rss.lilydjwg.me</a>找;可以在Feedly中搜索;可以用 <a>feed43</a> 转一个;可以自己写个 serverless function 转下,部署在 <a>now</a> 上</li> <li><a>Feedly 工具</a>用于抓取你收集的RSS源上更新的内容</li> <li><a>笔记应用Obsidian</a>:本地化存储、工作区 文件树 管理、个人用户免费、开放丰富的插件API库、双向链接、关系图谱、思维导图。(我做为一个Notion深度用户,Obsidian对我的吸引力是本地存储和关系图谱,但是还不足以让我弃用Notion转投Obsidian,因为Notion的数据库功能对我来说很重要)</li> <li><a>播客简介&amp;推荐</a></li> </ul> <h2>话题</h2> <ul> <li>小唯UP:<a>不要活在别人的评价体系中</a></li> <li>happy xiao:<a>B级玩家</a></li> <li><a>niche</a>:细分主题、市场定位、长尾效应</li> <li><a>一次网购维权经历</a></li> <li><a>日本老人三行诗</a>:仿佛看到了我们这代人的未来</li> </ul> <blockquote> <p>逗猫棒,挥的太慢,被猫嫌弃了一脸。 ——见边千春 69岁</p> </blockquote> <blockquote> <p>那个医生,以前教我养生,竟然比我先死了。 ——森田志郎 79岁</p> </blockquote> <h2>开发</h2> <ul> <li><a>小程序 极客词典</a>:中国互联网超爱读错的单词</li> <li><a>chiphuyen / ml-interviews-book</a> :机器学习面试指南</li> <li><a>geerlingguy / internet-pi</a>: 树莓派的所有网络配置</li> <li><a>eugeneyan / applied-ml</a>: 公司的论文和技术博客,分享他们在生产中的数据科学和机器学习工作。</li> <li><a>AllThingsSmitty / css-protips</a>:收集CSS tips</li> <li><a>tuteng / Best-websites-a-programmer-should-visit-zh</a>:程序员应该访问的最佳网站中文版</li> <li><a>fent / node-ytdl-core</a>:javascript写的Youtube视频下载器</li> <li><a>webpack老项目 迁移到 Vite</a> :实战经验</li> <li><a>为你的产品量身定制一个图标</a></li> </ul> <h2>Chrome图片工具</h2> <ul> <li><a>ImageAssistant</a>图片助手:自动提取网页图片、批量下载、以图搜图</li> <li><a>Fatkun</a>:微博图片批量下载、转webp图片</li> <li><a>Octo微博相册批量下载</a>:微博用户 相册 照片原图</li> </ul> 信息源https://www.scarsu.com/monthly_5_2021_07/#post-comment/PodCast 播客简介与推荐https://www.scarsu.com/podcast_intro/https://www.scarsu.com/podcast_intro/慢消费、轻内容Wed, 30 Jun 2021 00:00:00 GMT<h3>为什么听播客</h3> <p>和博客、公众号的长文章、短文章、长视频、短视频这些互联网内容相比,有什么特点?</p> <ul> <li>没有视频和文章直观、快速,是一种<strong>慢消费</strong>内容,快进、倒退、分享不便</li> <li>不占用太多注意力、专注度,更方便在上下班通勤、做家务等场景收听</li> <li>晦涩的内容通过口语表达出来,比看书、看文章更<strong>易接收</strong></li> <li>相比于文章,更能从播者的语言中,得到他传递的情感、力量、态度,更容易和播者建立<strong>情感粘性</strong></li> <li>从生理和记忆的角度看,相比于文字,声音更能给人留下印象</li> <li>没有视频的信息量大,留有边听边<strong>自主思考和想象</strong>的空间</li> <li>比视频尺寸小,更易传输、制作、存储</li> </ul> <h3>播客工具</h3> <ul> <li><a>Android 平台有哪些优秀的播客 (podcast) 应用?</a></li> <li>IOS有原生podcast应用</li> <li>小宇宙App:自用,中文播客app,纯播客app、界面简洁、有平台推荐节目、有社交属性 加时间戳评论类似弹幕 进度条可以显示高能点赞,主要是中文内容,国外内容很少</li> <li>Pocket Casts:自用,外国播客app,英文界面,国外内容较多,中文内容较少</li> </ul> <h3>播客推荐</h3> <ul> <li><a>知乎-有哪些值得关注的播客节目</a></li> <li><a>豆瓣-一些播客推荐</a></li> <li><a>不丧</a>-已更新137期,夫妻档,很真实</li> </ul> 信息源https://www.scarsu.com/podcast_intro/#post-comment/关于我 | 简短的年中总结https://www.scarsu.com/2021_mid/https://www.scarsu.com/2021_mid/6月底了,复盘了一下上半年做的事情,对下半年的计划略作调整Fri, 25 Jun 2021 00:00:00 GMT<h3>上半年看了3本书</h3> <p>看《忍不住的新努力》,跟胡适学习了如何做一个温和、沉稳、务实,而又乐观、积极的人。</p> <p>看《麦肯锡教我的写作武器》,让我更高效、更合理、更有逻辑的写出你此刻所见到的文章。</p> <p>看《亲密关系》,让我更了解自己的情绪,更懂得维护和伴侣、家人的关系。</p> <h3>开了月刊,更新了4期,会持续更新。</h3> <p>顺便想在此聊一聊为什么开月刊,我写博客、更新公众号,是想做一个能分享一些有价值内容的输出者。</p> <p>但是作为一个25岁没有足够人生阅历、视野认知有局限、没有硕博学历、事业技术水平都没达到行业金字塔顶部的平凡程序员,</p> <p>可能只处于互联网内容产出者金字塔的底部。</p> <p>之前看happy xiao的文章,说互联网内容大多是由B级玩家产出的,内容消费者是C级玩家,真正的A级玩家,是顶部的行业大亨、专家、学者、作家,他们是很少产出互联网内容的。</p> <p>在如今的互联网中,内容产出几乎没有门槛,谁都可以发文章、发视频、开直播,因此B级玩家是一个庞大的群体。</p> <p>每个B级玩家,都有他自己的一套信息渠道,去定期获取新信息,结合自己的思考,才能输出见解。</p> <p>这些信息渠道、信息源不是固定不变的,每个信息源都有其上级信息源,直至追溯到源头的A级玩家。</p> <p>我做月刊的目的,就是把自己不断更新的那些信息渠道、信息源分享出来,让我的博客不仅仅有自己的见解,也有日益更新的信息来源。</p> <p>假如我分享了自己的见解A,分享了这个见解的信息源头B,C,D,那么我传递给你的信息就从A扩展到了B,C,D,</p> <p>你还可以自己从每个B,C,D中继续向上溯源,找到更多有价值的信息,这样就间接实现了这个博客的价值~</p> <p>另一个方面的原因,其实是我忍不住。</p> <p>我觉得好的信息值得分享,不分享出来很可惜,我相信每一次分享,都是对 我想看到的优质互联网内容的一次投票~</p> <h3>优化了我的时间管理方案 GTD</h3> <p>TODO List + Inbox 收集箱 + 知识体系,感兴趣的博友可以看<a>这篇文章</a></p> <p><img src="/images/picgo/picgo20210127180326.png" alt="GTD时间管理" /></p> <h3>优化了我的日记/记账体系</h3> <p>目前稳定实践了三个月,等使用达到半年后,如果觉得省心+高效+有意义,就会分享出来</p> <p><img src="/images/picgo/picgo20210625175717.png" alt="日记" /></p> <p><img src="/images/picgo/picgo20210625175758.png" alt="月结年结" /></p> <h3>上半年<a>NotionX</a>更新了2版本</h3> <p>Google商店中目前的用户量是2160,算是我的开源启蒙项目,希望以后做出更好的技术工具</p> <p><img src="/images/picgo/picgo20210626105832.png" alt="NotionX" /></p> <h3>年初参与了StateOfJS 2020的<a>翻译</a></h3> <p>希望国内外技术社区的隔阂和差异能越来越小</p> <p><img src="/images/picgo/picgo20210626110002.png" alt="StateOfJS 2020" /></p> <h3>上半年只整理了一篇技术文章</h3> <p>上半年在技术学习提升这一方面,主要的时间在看新出的红宝书第四版,学一个算法课程,坚持刷leetcode,处于输入和自我消化的阶段,因此技术输出暂时停滞。</p> <p><img src="/images/picgo/picgo20210626110441.png" alt="红宝书进度" /></p> <p><img src="/images/picgo/picgo20210626110106.png" alt="leetcode热力图" /></p> <p>计划中第四季度会发不少技术文章。</p> <h3>下半年规划</h3> <p>第三季度有两个月要用来考证,还有一个月读两本上半年想看没来得及看的书《卡耐基魅力口才与演讲艺术》和《心流》</p> <p>第四季度集中在技术上,复习一下去年的全栈课、完成红宝书第四版阅读、理清自己的前端知识体系,查漏补缺</p> 个人成长https://www.scarsu.com/2021_mid/#post-comment/亲密关系:好的亲密关系是独立+合作https://www.scarsu.com/relationship/https://www.scarsu.com/relationship/我们都是完整而独立的个体、而爱情就是拥有一个合作伙伴一起经营人生Sat, 05 Jun 2021 00:00:00 GMT<h2>引言</h2> <p>阿德勒曾说过:“一切烦恼都来自于人际关系”</p> <blockquote> <p>因为我们每个人都是社会中的一份子,无法脱离人群和社会独自生存</p> </blockquote> <p>而亲密关系,更是占据了我们人生的大部分篇章</p> <p>子女、父母、爱人、朋友,都是我们人生中不可或缺的角色</p> <p>处理得好,亲密关系能给我们带来极大的快乐</p> <p>处理得不好,则会造成重大创伤和无与伦比的痛苦</p> <h2>恋爱的本质是满足需求</h2> <blockquote> <p>情感是来自人类“爱与被爱”的基本需求</p> </blockquote> <p>开始和维持一段亲密关系背后的真正动机,其实在于需求。</p> <p>在日常生活中,我们的所作所为,绝大部分都是为了让某些需求得到满足。我们追求或吸引别人来做我们的伴侣,是因为我们需要人陪伴、照顾、了解、支持、接受、赞赏、抚摸和相拥而眠……</p> <p><strong>这是人类的本性,并没有什么不对</strong>,但是如果我们认为,我们所需要的快乐、安全感、自尊或其他的许多事物,都要<strong>依赖别人来实现</strong>的话,这就成为一个大问题了。</p> <h2>爱不是依赖、不是占有</h2> <p>每个人的童年时代,没有任何生活能力,所以需要依赖父母来达成的内心的需求、满足归属感、感受自己的重要性。</p> <p>但是当我们长大之后,我们应该培养自己独立生活的能力、自爱的能力,而不是找到一个人,来满足自己的这些感受,弥补这些缺失,从别人身上索取爱。</p> <p>因为如果你依赖别人,当发现对方不满足需求和期望时,就想改造对方,各种“手段”因此而生:</p> <ul> <li>暗示、明示、甚至PUA,以“改造”对方,“如果你真的爱我,你就应该xxx”。</li> <li>吵架,用愤怒当作自我防御、自我欺骗的机制,用愤怒保护自己脆弱的内心。</li> <li>扮演受害者,把自己的伤痛归咎在对方身上。</li> </ul> <p><img src="/images/picgo/picgo20210413155630.png" alt="" /></p> <p>这不是爱,这是把对方当作满足自己内心的需求的工具人。</p> <h2>好的亲密关系是:独立+合作</h2> <blockquote> <p>我们每个人都是完整的个体,不是离开谁活不下去</p> </blockquote> <p>害怕受伤、痛苦、恐惧,渴望永恒真挚、开心、快乐,都是我们生而拥有的情绪,</p> <p>要学会独立消化、处理自己的情绪</p> <p>要学会接受、面对自己,面对自己最好的、最糟的状态</p> <blockquote> <p>每个成年人的行为、决策,都是他生而为人的自由</p> </blockquote> <p>你可以建议、沟通,但是不能干涉、强迫;</p> <p>与自由相应的,每个人都有独立承担其行为后果的责任</p> <p>不要扮演受害者,你的需求未满,不是别人的责任</p> <blockquote> <p>亲密关系,不是我们人生的最终目的</p> </blockquote> <p>亲密关系是丰富我们漫漫人生之旅的风景、增强人生体验的精神补剂</p> <p>要勇于接受未来,舍得放下过去</p> <blockquote> <p>不能把自己的需求和期望,强加在伴侣、亲人、朋友身上</p> </blockquote> <p>要学会自爱,让自己内心变得完整、安全、有爱</p> <p>建立独立完整的自尊体系,心智成熟</p> <p>你跟我在一起,我拥有了<strong>合作</strong>走完人生的伙伴,我可以开心幸福</p> <p>你不跟我在一起,我也能独自看完这世上的风景,我也不会崩溃度日</p> <h2>愉悦与不快都很重要</h2> <p>亲密关系是一种完美设计</p> <p>在亲密关系中,所有的一切都是重要的部分,即使是令人不悦的冲突与不适的情境。</p> <p>当你继续在感情中成长时,你也开始<strong>懂得欣赏你跟伴侣之间所发生的任何事情</strong>。</p> <p>你的伴侣不是你的爱与幸福的来源,满足你的期待与使你开心不是他们的职责。</p> <p>你的伴侣在你的生活中扮演了三个重要的角色:</p> <ul> <li>一面镜子,让你看见引发你关注的不舒服感;</li> <li>一名老师,在你探寻真实自我的时候,激励与启发你;</li> <li>一名“玩伴”,开启并陪伴你一段生命的旅程。</li> </ul> <h2>不要过度追求浪漫主义的恋爱</h2> <p>一见钟情的颜值、小鹿乱撞的心动、一束花、</p> <p>一次表白、几句甜言蜜语、嘘寒问暖、</p> <p>肾上腺素飙升的亲密接触、轰轰烈烈的你追我逐、</p> <p>都是爱情的修饰,而不是爱情本质,</p> <p>不要再通过 小说/影视剧/磕cp去 学习爱情,</p> <p>坚持读书、勇于识人,可以补充我们缺少的“爱情教育”</p> <p>积累知识和人生经验,去成就洒脱、成熟的亲密关系</p> <h2>总结</h2> <p>慕名而读,结果读错了,不是这本,是另一本罗兰·米勒的《亲密关系》。但是看完了这本书,还是有一定收获的。</p> <p>这本书从心理学和人性的角度,直戳亲密关系中的问题,以及问题出现的原因。</p> <p>边看书边审视自己的上一段恋爱,从而发现导致分手的原因双方都有责任,过去对他的埋怨和不满也放下了,把这本书推荐给他看之后,我们复合了。从高中到工作第三年,我们从懵懂无知地向往爱情,到热恋期的亲密无间 ,到归于平淡,再到吵吵闹闹,互相埋怨,分道扬镳......</p> <p>一切都是因为我们不懂爱情,我们在年少无知的时候选择了彼此,把彼此当作依赖,当作生活、工作、压力的唯一寄托和宣泄口,把彼此当作那个 理所当然、应该无条件支持、纵容自己的人。</p> <p>现在我们才懂,我们都是完整而独立的个体、而爱情就是拥有一个合作伙伴一起经营人生</p> 个人成长https://www.scarsu.com/relationship/#post-comment/月刊#4 | 2021.05-06https://www.scarsu.com/monthly_4_2021_05-06/https://www.scarsu.com/monthly_4_2021_05-06/指路人系列、开发资源、有意思的资源、纪录片推荐Tue, 01 Jun 2021 00:00:00 GMT<h2>【Grow Up With You】指路人系列</h2> <ul> <li><a>霍孙杨 hcy</a>: Vue核心团队成员,Vue设计分析文章《Vue Design》作者</li> </ul> <h2>开发资源</h2> <ul> <li><a>MDH • 前端情报日刊</a>:社群活跃,每日更新</li> <li>最新的<a>前端框架性能对比结果</a>、<a>分析文章</a>、<a>了解测试的基准</a></li> <li><a>You-Dont-Need-JavaScript</a>: 用原生CSS实现UI逻辑</li> <li><a>免费公开API搜集仓库</a></li> <li><a>动画算法仓库</a></li> <li>手写<a>easy webpack</a> ,熟悉AST</li> </ul> <h2>纪录片推荐</h2> <ul> <li><a>海豚湾 2009</a></li> </ul> <h2>有意思的资源</h2> <ul> <li><a>FUNN.FUN</a>: 奇趣网站收藏家</li> <li><a>世界电台</a>:从世界地图上探索全世界电台</li> <li><a>Deep Nostalgia</a>:将人脸照片转换成表情视频</li> <li><a>NandGame</a>:从逻辑电路开始一步一步制造电脑的游戏</li> </ul> <p><img src="/images/picgo/picgo20210604101214.png" alt="NandGame" /></p> 信息源https://www.scarsu.com/monthly_4_2021_05-06/#post-comment/月刊#3 | 2021.04https://www.scarsu.com/monthly_3_2021_04/https://www.scarsu.com/monthly_3_2021_04/舒适生活指南、职业发展、投资、话题、文章推荐Thu, 01 Apr 2021 00:00:00 GMT<h2>舒适生活</h2> <ul> <li>成年人<a>如何科学地应对压力?</a></li> <li><a>每天晚上睡觉之前写下当天发生的3件好事</a>:低成本持续幸福</li> <li><a>写日记的意义</a>:和自己对话</li> <li><a>闲鱼攻略</a></li> </ul> <h2>职业发展</h2> <ul> <li>Solo Developer:<a>两位独立开发者</a></li> <li>若川:<a>公众号运营策略</a></li> <li>Happy Xiao博客推荐:<a>你在展示你是谁,你如何思考,而不是你在想什么</a></li> </ul> <h2>投资</h2> <ul> <li>【<a>2020胡润财富报告</a>】目前中国拥有600万人民币资产、千万人民币资产、亿元人民币资产和3000万美金资产的家庭数量和地域分布情况,包括中国内地和香港、澳门、台湾</li> <li>【业界事件】<a>一表看完散户大战华尔街全过程(持续更新)</a></li> <li>【投资思维】<a>复利的谎言</a> 随机性、不连续性、不均匀性、非对称性、思考&gt;勤奋</li> <li>【投资分析】<a>中国居民会增加股票配置吗?</a></li> </ul> <h2>话题推荐</h2> <ul> <li>【自律=压抑欲望?】 所谓自律,就是主动要求自己以积极的态度承受痛苦。——<a>《少有人走的路》</a></li> <li>【感情是信念的基础】“爸爸说我很冷静,他并没有真正理解我,我认为,有时候,感情是信念的基础,这里有我汗水浸过的土地,这里有我患难与共的亲友,这里有我相濡以沫的妻子,这里有我生命的根。”——电影<a>《牧马人》</a></li> <li>【投射】我们所看到的每件事其实都是我们内心的投射。我们怎么评论别人,就是我们怎么看待自己。如果我觉得别人太爱批评而讨厌他,就代表我讨厌自己爱批评的习性。——<a>《亲密关系》</a></li> </ul> <h2>文章推荐</h2> <ul> <li>教育内卷现状:<a>为了鸡娃,上海的家长到底有多拼</a></li> <li><a>「翻墙违法是无可争议的事实」</a></li> </ul> 信息源https://www.scarsu.com/monthly_3_2021_04/#post-comment/麦肯锡教我的写作武器:如何无痛写文章https://www.scarsu.com/writing_tech/https://www.scarsu.com/writing_tech/写作能力是这个时代许多行业的基本功Sun, 28 Mar 2021 00:00:00 GMT<h2>引言 - 写文章为什么令我痛苦</h2> <p>作为一个理科生,要问我学生生涯最讨厌的是什么,我无疑会回答<strong>写作文</strong>。</p> <p>无论是小学的流水账日记,</p> <p>还是高考的800字作文,</p> <p>甚至是现在工作上的文档/报告,</p> <p>都曾为我的脱发症增添几分贡献🤧。</p> <p>自从维护博客/写公众号以来,我常常反思,<strong>写文章为什么令我痛苦</strong></p> <p>我写文章,一是为了将我自己对某些事物的思考/总结记录下来,供自己回顾;二是为了分享给你,听听你不同的见解。</p> <p>总归是有一些东西在脑子里,想表达出来,却缺乏章法🤯。</p> <p>因此在朋友给我推荐这本书的时候,就没有犹豫加入书单了✅。</p> <h2>《麦肯锡教我的写作武器》是怎样的书</h2> <p>这本书可以说是一本<strong>商务文案写作指南</strong></p> <p>虽说是商务文案,但是也同样适合日常写作和技术文章。</p> <p>因为这本书<strong>从信息筛选、遣词造句,到整体结构的设计</strong>这些方面,介绍了写文章的通用技巧和思维。</p> <p>下面的正文,会从上述的三个方面,总结书中的内容。</p> <h2>信息筛选</h2> <h3>信息是组成文章的“零件”</h3> <p>写作本质上就是信息的整合。</p> <p>能明确表现主语与谓语的关系的句子,都是信息。</p> <p>“这瓶农夫山泉的容量是500ml”可以作为一条信息;</p> <p>“农夫山泉”、“500ml”这种单独的对象,都不是信息;</p> <h3>信息分三类</h3> <ul> <li><strong>记述信息</strong>:描述事物的情况和现象本身,常常包含现象、数据、经验、实例(平铺直叙)</li> </ul> <p>例子🌰:本篇文章总结了《麦肯锡教我的写作武器》这本书的主要内容。</p> <ul> <li><strong>评价信息</strong>:表达某一情况或现象的好坏(有形容词)</li> </ul> <p>例子🌰:《麦肯锡教我的写作武器》这本书很值得读。</p> <ul> <li><strong>规范信息</strong>:要求事物应有的状态以及人该采取的行动(有动词)</li> </ul> <p>例子🌰:你应该读一读《麦肯锡教我的写作武器》。</p> <p><strong>区分清楚信息类型非常重要</strong>,以书中的一处对话为例🌰:</p> <blockquote> <p>主管:山田,X公司最近的业绩如何?</p> <p>山田:是……X公司最近一季的销售额为220亿日元,营业利益为5亿日元。自由现金流量(Free Cash Flow)为87亿日元。昨天股票的收盘价为每股358日元。</p> <p>主管:喔,所以呢……</p> <p>山田:啊!是……好像还有特别损失的部分,再扣除税之后,利益为2亿日元。利息支出大概是1千万日元左右。</p> <p>主管:所以呢?</p> <p>山田:啊!还有……该公司利息收入为200万日元。销售成本是……</p> <p>主管:我是问你“他们的业绩怎么样?好还是不好?”</p> <p>山田:喔!是……似乎回升了不少。</p> <p>主管:好啦,有上升就是了,我知道了……</p> </blockquote> <p>从上面的对话可以看出来,主管想要了解的是<strong>评价信息</strong>,并进行了四次提问才得到想要的回答,而山田小呆呆前三次都回答的是<strong>记述信息</strong>。</p> <p>所以为了避免像他一样给上司留下“鸡同鸭讲、对牛弹琴”的不良印象❌,</p> <p>同样为了避免给文章读者造成混淆❌</p> <p>在传达信息前,我们应该明确,究竟要传达哪一类信息。</p> <h3>活用三种类型的信息</h3> <p>记述信息 + 评价标准:有“评价信息”的效果,却比直接评价更委婉。🌰例如小明的妈妈说:你这次考了40分,60分是及格分。</p> <p>评价某种行为的信息:有“规范信息”的效果,却比规范信息更委婉。🌰例如小明的妈妈接着说:下次再考40分就过分了。</p> <p>如果你表达了某一类信息,例如记述信息,别人仍然说“听不懂”时,可以接着说出评价信息、规范信息。🌰例如小明对妈妈说:这台电脑RAM有32G。+运行内存很大,电脑运行十分流畅。+妈妈你应该买给我学习。</p> <h3>文章的主题不是信息</h3> <p>一般来说,文章的主题不应该是一条信息,🌰例如“我分享了一篇关于《麦肯锡教我的写作武器》的文章”不适合作为文章的主题。</p> <p>文章的主题应该告诉别人你文章内<strong>信息的范围</strong>,🌰例如“《麦肯锡教我的写作武器》读后感觉”可以作为文章主题。</p> <p>此外,用“时间”替主题定调,可以增加吸引力,🌰例如"三分钟了解《麦肯锡教我的写作武器》"。</p> <h2>遣词造句</h2> <p>信息的筛选很重要,如何将信息合适的表达出来也很重要,</p> <p>想让信息提升说服力,可以从遣词造句下手。</p> <h3>1. 善用主语</h3> <p>明确表达一条信息,核心在于,高度明确的<strong>主语与谓语的关系</strong>。</p> <p>在日常生活口语中,我们常常习惯于省略主语,但是这个习惯带入到文章中,容易造成误解、加重阅读负担。</p> <p>此外,也可以通过主语影响别人思考,🌰例如:“门要关了”,“列车员要关门了”这两句话,后一句的主语时活生生的人,会引发听者更多思考。</p> <h3>2. 明确逻辑,善用连接词</h3> <p>文字的逻辑性是否强,思维是否流畅,很大程度上取决于<strong>连接词</strong>。</p> <p>连接词用好,可以降低阅读负担,让文章一气呵成。</p> <p>🌰举个例子,如果删去下面这段话中加粗的连接词,会给人一种“这段话每个句子我都认识,但就是不知道想表达什么”的感觉:</p> <blockquote> <p>美国总统明年一月开始进入第二任的任期,<strong>关于执政</strong>(解说),国民年金以及税制的根本改革是优先课题。<strong>首先</strong>(分点1),国民年金将导入确定提拔型的“个人结算”,<strong>以</strong>(目的)防止高龄化带来的年金财政的缺口。<strong>其次</strong>(分点2),简化繁杂的所得税制,<strong>同时</strong>(追加)继续保持减税路线,<strong>为的是</strong>(目的)长期的经济成长。<strong>当然</strong>(让步),要努力减少过去最严重的“双重赤字”,也就是财政赤字和贸易赤字。<strong>不过</strong>(转折),在通往实现的道路上,困难重重。</p> </blockquote> <p>常见的逻辑连接词及分类可以参考下图:</p> <p><img src="/images/picgo/picgo20210324101814.png" alt="高杉逻辑连接词表" /></p> <h3>3. 用词“具体”</h3> <p>滥用抽象的表达,是不负责任的表现。</p> <p>“……的活性化”、“……的多样化”、“重新评估”、“推动”、“调整”这类词汇仅仅可以用于表达一个方向性,如果用多了,会显得文章空泛、圆滑闪躲。</p> <h3>4. 合理分段</h3> <p>一个分段最好传达单一的信息。</p> <p>分段的数量也有小tips,最少3个,5、7这样的质数也比较合适,因为3是稳定结构的最小数量,7是科学证明人类一次能记住的最大数量,而质数更容易被记忆。</p> <h2>文章结构</h2> <p>前两段,分别讲了如何筛选合适的信息、如何遣词造句以更好的传达信息,</p> <p>除了表达独立的信息,整体文章的设计也很重要。</p> <h3>金字塔结构</h3> <p>金字塔结构是写大多数文章的常用结构,分为多个层级</p> <ol> <li>主要信息</li> <li>关键信息</li> <li>次要信息</li> </ol> <p><img src="/images/picgo/picgo20210324122454.png" alt="金字塔结构" /></p> <p>和思维导图一样,金字塔结构可以一路扩展下去,这样的结构,逻辑性强,条理清晰。</p> <h3>由上而下⬇️设计结构(分解</h3> <p>当你拥有一个写作目标时,例如高考的命题作文,就可以由上而下设计文章结构。</p> <p>先选定一个主要信息,然后再分解成个别的关键信息。</p> <p>分解的方法有理由法和详述法,考虑“为了让上层信息更有说服力,要用哪些下层信息比较能够支持论点”,来设计信息。</p> <h3>由下而上⬆️设计结构(抽象、摘要</h3> <p>当你拥有一些零散信息和思维时,可以由下而上设计文章结构。</p> <p>由下而上法就是要将位于下层的信息群往上精炼,成为上层的信息。</p> <p>具体来说,需要先将零散信息分组,再通过结论法和摘要法,得到上层信息。</p> <p>通常我写读书笔记就是采用这种方法:看书时,标记出有收获的字句、段落,输出笔记时,聚合所有的标记、分类、向上提炼,三步套路之后,写读书笔记就能得心应手。</p> <p><img src="/images/picgo/picgo20210324123212.png" alt="由下而上" /></p> <h3>MECE:不重复不遗漏</h3> <p>除了主题的数量、金字塔结构,还有一个在构成关键主题时很重要的概念,那就是主题之间是否为MECE。</p> <p>MECE的全称是“Mutually Exclusive Collectively Exhaustive”,直译之意为“相互排他性、集合网罗性”,也有人翻译成“不重复、不遗漏”。</p> <p>将关键主题设定在三、五、七个,目的在于分类能够清楚,<strong>没有重复冗余</strong>,同时又能<strong>足够完整</strong>地网罗重要条目,没有遗漏。</p> <h2>结语</h2> <p>掌握了信息筛选、遣词造句、结构设计,足够写出一篇逻辑清晰的文章,</p> <ul> <li>如何将脑子里的种种思维,以更有逻辑的形式,形成文章</li> <li>如何提高文章说服力</li> <li>如何流畅写作,提高写作效率</li> </ul> <p>这些写作最核心的问题,也能找到答案。</p> 个人成长https://www.scarsu.com/writing_tech/#post-comment/月刊#2 | 2021.03https://www.scarsu.com/monthly_2_2021_02/https://www.scarsu.com/monthly_2_2021_02/2020年总结收集、学习资源、Notion相关资源、工作、书单、话题Mon, 01 Mar 2021 00:00:00 GMT<h2>2020年总结收集</h2> <ul> <li><a>若川的2020年度总结,水波不兴</a> (川佬的第七个年总结</li> <li><a>前端劝退师:晃荡一年,我那错乱无力的2020 | 年度总结</a> (晃荡又不失风骚的职业旅程</li> <li><a>惊天码盗:2020年度总结(增长的朋友)</a> (偏重于学习/工作/职业成长</li> <li><a>一位阿里前端er的年总结</a> (生活、工作、兴趣、理财,主题丰满</li> </ul> <h2>学习资源</h2> <ul> <li>英文演讲/影子跟读【Never Give Up】尼克·胡哲 <a>音频</a> <a>中英文稿</a></li> <li><a>神经网络入门教程 - freecodecamp</a></li> <li><a>docker教程 - freecodecamp</a></li> <li><a>如何快速进入学习状态 - bilibili</a></li> </ul> <h2>Notion相关资源</h2> <ul> <li>Notion 自动化:Notion API key + <a>Automate.io</a></li> <li>Mac <a>alfred Notion搜索快捷操作</a></li> <li><a>Notion子弹笔记</a></li> </ul> <h2>工作</h2> <ul> <li><a>工作中提高效率的方法</a></li> <li><a>前端软技能,反制职场PUA</a></li> <li>敏捷项目管理:<a>notion 看板</a>,<a>飞书多维表格</a></li> </ul> <h2>书单</h2> <ul> <li><a>女权书单</a></li> <li><a>30+大男孩的世界好奇书单</a></li> <li><a>学科入门书单/短板补充书单</a></li> </ul> <h2>话题</h2> <ul> <li>【自律=压抑欲望?】 所谓自律,就是主动要求自己以积极的态度承受痛苦——<a>《少有人走的路》</a></li> <li>【“人设”的作用】是快速让对方知道能从你身上获得哪一类内容。</li> <li>【投资】<a>一表看完散户大战华尔街全过程(持续更新)</a></li> <li>【职业故事】<a>两位独立开发者</a></li> </ul> 信息源https://www.scarsu.com/monthly_2_2021_02/#post-comment/前端图标的那些事https://www.scarsu.com/iconfont/https://www.scarsu.com/iconfont/更新svg-symbolSat, 13 Feb 2021 00:00:00 GMT<ul> <li>初次发布于2020-02-19</li> <li>第二次编辑于2021-03-13,更新svg-symbol</li> </ul> <hr /> <h2>前言</h2> <p>用了矢量图标,</p> <p>UI再也不吐槽你页面的图标放大后有点糊了...</p> <p>PM再也不会嫌弃你画的页面图片太大,太占load time了...</p> <p>你也不用因为一个hover状态,就写一段换图片src的逻辑了...</p> <h2>矢量图标</h2> <ul> <li>不会因为放大/缩小而导致图标变模糊,即可以任意定义尺寸的icon。</li> <li>在现代前端项目中,除了任意定义尺寸,对图标的要求还有定义颜色等等。</li> </ul> <h2>字体图标</h2> <ul> <li>以字体的形式定义的图标,可以像字体一样定义尺寸,颜色。</li> <li>优点:体积小(用到的图标越多性价比越高);样式便于控制,与字体一样可以调节font-size,color,阴影,旋转,透明度,且兼容低版本浏览器。</li> <li>方法与原理:UI提供svg矢量图 -&gt; 用工具将svg转换成字体文件 -&gt; 前端在css中自定义font-face,通过unicode的方式使用图标。</li> <li>可以使用主流的字体图标库:fontAwesome,阿里的iconfont。</li> <li>也可以使用自动化工具,例如<a>@ztwx/webfont</a>:可以自动化上述过程,运行工具打开网页后,上传svg文件,自动更新代码中的字体文件和css文件。</li> <li>缺点:需要UI合作;每次图标变更都需要重新生成字体文件,更改css中定义的font-face和class。</li> <li>前端引用iconfont主流方式:</li> </ul> <ol> <li> <p>直接使用Unicode字符</p> <ul> <li>兼容性最好,支持 IE6+,及所有现代浏览器。</li> <li>支持按字体的方式去动态调整图标大小,颜色等等。</li> <li>但是因为是字体,所以不支持多色。</li> </ul> <pre><code>/*第一步:自定义@font-face,引用字体文件*/ @font-face { font-family: 'iconfont'; src: url('iconfont.eot'); src: url('iconfont.eot?#iefix') format('embedded-opentype'), url('iconfont.woff2') format('woff2'), url('iconfont.woff') format('woff'), url('iconfont.ttf') format('truetype'), url('iconfont.svg#iconfont') format('svg'); } /*第二步:定义使用 iconfont 的样式*/ .iconfont { font-family: "iconfont" !important; font-size: 16px; font-style: normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } /*第三步:挑选相应图标并获取unicode编码,应用于页面*/ &lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt; </code></pre> </li> <li> <p>font-class(使用最多)</p> <ul> <li>unicode变体,解决了unicode编码语义不明确的问题,书写更直观。可以很容易分辨这个 icon 是什么,著名的<strong>FontAwesome</strong>即使用该方式</li> <li>兼容性良好,支持 IE8+,及所有现代浏览器。</li> <li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li> <li>本质上还是字体,所以多色图标还是不支持的。</li> </ul> <pre><code>/*第一步:自定义@font-face,引用字体文件*/ @font-face { font-family: "iconfont"; src: url("iconfont.eot"); src: url("iconfont.eot?#iefix") format("embedded-opentype"), url("iconfont.woff2") format("woff2"), url("iconfont.woff") format("woff"), url("iconfont.ttf") format("truetype"), url("iconfont.svg#iconfont") format("svg"); } /*第二步:定义iconfont样式*/ .iconfont { font-family: "iconfont" !important; font-size: 16px; font-style: normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } /*第三步:定义每个icon unicode 样式类*/ .icon-gouwuche:before { content: "\e669"; } </code></pre> <pre><code>&lt;!-- 第四步:引入1,2步的css --&gt; &lt;link rel="stylesheet" href="./iconfont.css" /&gt; &lt;!-- 第五步:挑选相应图标并使用定义的类名,应用于页面: --&gt; &lt;span class="iconfont icon-xxx"&gt;&lt;/span&gt; </code></pre> </li> <li> <p>Symbol</p> <ul> <li>本质是svg,支持多色。</li> <li>较新的使用方式,兼容性较差,支持 IE9+,及现代浏览器。</li> <li>通过一些技巧,支持像字体那样,通过 font-size, color 来调整样式。</li> <li>浏览器渲染 SVG 的性能一般,还不如 png。</li> </ul> <pre><code>&lt;!-- 第一步:引入js代码 --&gt; &lt;script src="./iconfont.js"&gt;&lt;/script&gt; </code></pre> <pre><code>/* 第二步:加入通用css样式(引入一次即可) */ .icon { width: 1em; height: 1em; vertical-align: -0.15em; fill: currentColor; overflow: hidden; } </code></pre> <pre><code>&lt;!-- 第三步:挑选相应图标并获取类名,应用于页面: --&gt; &lt;svg class="icon" aria-hidden="true"&gt; &lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt; &lt;/svg&gt; </code></pre> </li> </ol> <h2>icon最佳实践:svg图标</h2> <ul> <li>除了字体图标,现代前端项目中使用更多的是Svg图标</li> <li><code>&lt;svg&gt;</code>及其一系列元素,用于矢量图像的结构、绘制与布局</li> <li><code>&lt;symbol&gt;元素</code>,是可复用的svg图像,用来定义一个图形模板对象,它可以用一个<code>&lt;use&gt;</code>元素实例化。</li> </ul> <pre><code>&lt;svg&gt; &lt;!-- symbol定义模板(symbol本身不会显示图像 --&gt; &lt;symbol id="sym01" viewBox="0 0 150 110"&gt; &lt;circle cx="50" cy="50" r="40" stroke-width="8" stroke="red" fill="red"/&gt; &lt;circle cx="90" cy="60" r="40" stroke-width="8" stroke="green" fill="white"/&gt; &lt;/symbol&gt; &lt;!-- 使用use元素才能实例化 --&gt; &lt;use xlink:href="#sym01" x="0" y="0" width="100" height="50"/&gt; &lt;use xlink:href="#sym01" x="0" y="50" width="75" height="38"/&gt; &lt;use xlink:href="#sym01" x="0" y="100" width="50" height="25"/&gt; &lt;/svg&gt; </code></pre> <ul> <li><code>symbolId</code>:在<code>&lt;use&gt;</code>元素的<code>xlink:href</code>属性需要指向symbol元素的id</li> <li>优点: <ol> <li>svg图标拥有字体图标的各种优点此外</li> <li>svg不需要UI转成字体、定义font-face,只需要原始的svg代码,即可使用。</li> <li>通过现代前端工具整合,svg图标变更时,只需要变更单个svg文件,耦合度低</li> </ol> </li> </ul> <h2>svg symbol应用于现代前端框架</h2> <ul> <li>创建svg目录,存放一个svg文件,例如<code>@/assets/svg/test.svg</code></li> <li>在webpack中配置<code>svg-sprite-loader</code>,匹配上述的svg文件,并将其symbolId配置为svg文件名,详情参考<a><code>svg-sprite-loader</code>文档</a></li> </ul> <pre><code>// 以下为vue cli4的配置 module.exports = { chainWebpack(config){ // 1. 将./src/assets/svg排除在vue的默认webpack配置的svg规则之外 config.module.rule('svg') .exclude.add(resolve('./src/assets/svg')) // 2. 添加一条icons规则 config.module.rule('icons') .test(/\.svg$/) // 匹配svg后缀的文件 .include.add(resolve('./src/assets/svg')).end() // 添加规则生效的路径 .use('svg-sprite-loader') // 使用svg-sprite-loader插件 .loader('svg-sprite-loader') // 加载svg-sprite-loader插件 .options({symbolId: 'icon-[name]'}) // name:文件名,此处的symbolId即svg的xlink:href属性,xlink:href="#icon-文件名" } ... } </code></pre> <ul> <li>在vue模板中即可直接使用</li> </ul> <pre><code>// text.vue &lt;template&gt; ... &lt;svg :class="svgClass" v-on="$listeners"&gt; &lt;use xlink:href="#icon-test"&gt;&lt;/use&gt; &lt;/svg&gt; ... &lt;/template&gt; import '@/assets/svg/test.svg'; ... </code></pre> <ul> <li>更进一步的封装:不需要每个icon都import;<code>&lt;svg-icon&gt;</code>组件;</li> </ul> <ol> <li>通过webpack上下文,将svg文件作为固定上下文,即可避免手动import,用到了webpack中的<a>require.context api</a></li> </ol> <pre><code>// @/assets/svg/index.js // 使用 webpack提供的require.context()指定svg为固定上下文 function importAll(r) { r.keys().forEach(r); } importAll(require.context("@/assets/svg", false, /\.svg$/)); </code></pre> <ol> <li>在main.js中引入上述js文件</li> </ol> <pre><code>import "@/assets/svg/index.js"; // svg上下文 </code></pre> <ol> <li>封装icon组件</li> </ol> <pre><code>&lt;template&gt; &lt;svg :class="svgClass" v-on="$listeners"&gt; &lt;use :xlink:href="iconName" /&gt; &lt;/svg&gt; &lt;/template&gt; &lt;script&gt; export default { name: "SvgIcon", props: { // iconClass要和svg的文件名一致 iconClass: { type: String, required: true, }, // className可以用来定制样式 className: { type: String, default: "", }, }, computed: { iconName() { return `#icon-${this.iconClass}`; }, svgClass() { if (this.className) { return "svg-icon " + this.className; } else { return "svg-icon"; } }, }, }; &lt;/script&gt; &lt;style scoped&gt; .svg-icon { width: 1em; height: 1em; vertical-align: -0.15em; fill: currentColor; overflow: hidden; } &lt;/style&gt; </code></pre> <ol> <li>在main.js中注册全局组件</li> </ol> <pre><code>import SvgIcon from '@/components/common/SvgIcon.vue' Vue.component('SvgIcon', SvgIcon) </code></pre> <ol> <li>使用</li> </ol> <pre><code>&lt;svg-icon iconClass="test"&gt;&lt;/svg-icon&gt; </code></pre> 前端https://www.scarsu.com/iconfont/#post-comment/月刊#1 | 2021.02https://www.scarsu.com/monthly_1_2021_01/https://www.scarsu.com/monthly_1_2021_01/推荐文章、优质信息源、学习资源、流量积累、看看机会Mon, 01 Feb 2021 00:00:00 GMT<h2>我的本月文章</h2> <ul> <li><a>2021年,给自己来点鸡血</a></li> <li><a>《当我谈跑步时我谈些什么》:痛苦难以避免,而磨难可以选择</a></li> <li><a>【GTD时间管理】高效低耗的应对信息洪流</a></li> <li><a>我做了一年公众号有多少收入?</a></li> </ul> <hr /> <h2>推荐文章</h2> <ul> <li><a>构建个人知识体系</a></li> </ul> <blockquote> <p>知识习得的闭环:信息 → 学习内化 → 输出 → 应用 → 信息</p> </blockquote> <ul> <li><a>早起和赚钱,这2件事的逻辑其实一样</a></li> </ul> <blockquote> <p>用培养技能的逻辑,做到早起</p> </blockquote> <hr /> <h2>优质信息源</h2> <ul> <li><a>构建我的被动收入</a> - 马大伟</li> </ul> <blockquote> <p>终身学习(认知杠杆) → 全栈技术(时间杠) → 投资理财(财务杠杆) → 被动收入(人生杠杆)</p> </blockquote> <ul> <li><a>美团技术博客</a></li> </ul> <blockquote> <p>更新稳定,积累多,技术领域宽泛</p> </blockquote> <hr /> <h2>学习资源</h2> <ul> <li> <p><a>美团技术沙龙——85个演讲,70+小时视频</a></p> </li> <li> <p><a>技术人必读书单-美团</a></p> </li> <li> <p><a>技术团队书单-美团</a></p> <ul> <li> <p><strong>通用能力类:6本</strong></p> <p><a>原则</a> 8.3</p> <p><a>系统之美</a> 8.2</p> <p><a>潜力量</a> 8.7</p> <p><a>乔布斯的魔力演讲</a> 7.8</p> <p><a>远见 : 如何规划职业生涯3大阶段</a> 7.7</p> <p><a>事实 : 用数据思考,避免情绪化决策</a> 8.0</p> </li> <li> <p><strong>经济管理类:6本</strong></p> <p><a>孙子兵法</a> 9.4</p> <p><a>格鲁夫给经理人的第一课</a> 9.1</p> <p><a>刷新</a> 7.5</p> <p><a>关键时刻MOT</a> 8.2</p> <p><a>领导梯队</a> 8.1</p> <p><a>经济学通识课</a> 8.3</p> </li> <li> <p><strong>哲学历史类:8本</strong></p> <p><a>光荣与梦想</a> 8.7</p> <p><a>民国大人物</a> 6.5</p> <p><a>极简欧洲史</a> 8.2</p> <p><a>世界观</a> 8.9</p> <p><a>当下的力量</a> 8.0</p> <p><a>枪炮、病菌与钢铁:人类社会的命运</a> 8.8</p> <p><a>传习录</a> 9.3</p> <p><a>西方心理学史</a> 6.7</p> </li> <li> <p><strong>人物传记类:3本</strong></p> <p><a>邓小平时代</a> 9.2</p> <p><a>我的世界观</a> 8.9</p> <p><a>曾国藩传</a> 6.8</p> </li> </ul> </li> </ul> <hr /> <h2>流量积累</h2> <ul> <li> <p><a>独立博客 流量可视化案例</a></p> </li> <li> <p><a>零成本搭建现代博客之订阅推送篇</a></p> </li> </ul> <p>独立博客流量的即时性</p> <hr /> <h2>看看机会</h2> <ul> <li> <p>【JD】莉莉丝(年终抽奖真香</p> <ul> <li>莉莉丝游戏 - 平台组</li> </ul> <pre><code>公司名:莉莉丝游戏 部门名称:平台组 工作城市:上海 经验要求:2年以上 招聘岗位:前端工程师(P6、P6+) 职位描述: 1、负责公司官网,社区,平台开发和维护; 2、负责游戏管理系统的开发; 3、参与平台产品的架构优化,性能优化。 职位要求: 1、精通html5、css3、javascript、ajax等web开发技术,掌握至少一种前端框架,如react,angular,vue。熟悉ECMAscript6/7语法; 2、熟悉不同版本浏览器的兼容性、能够对不同尺寸设备进行适配; 3、至少一门后端开发语言,如nodejs,php,java等。掌握数据库和缓存系统,如mysql,memcached,redis等 ; 4、有一定的架构设计理念,熟悉常用设计模式; 5、有良好的ui交互实现能力、能熟练使用photoshop进行切图; 6、计算机或相关专业本科及以上学历; 内推联系人(微信):Jaked_M 内推联系人(邮箱):liuchao@lilith.com </code></pre> <ul> <li>莉莉丝游戏 - Avatar项目组</li> </ul> <pre><code>公司名:莉莉丝游戏 部门名称:Avatar项目组 工作城市:上海 经验要求:3年以上 招聘岗位:RN工程师(P6 ~ P7) 职位描述 1、负责社区核心产品的设计、开发、维护工作 2、负责App基础组件和架构设计,编写高质量代码 3、和产品经理配合,深度参与产品需求讨论,功能定义,优化产品体验 4、研究移动平台新技术,持续优化App性能,对齐业内一流产品水平 任职要求 1、大学本科或以上学历,3年以上工作经验 2、iOS/Android端开发经验(高级android开发优先),具备一定双端开发能力者优先 3、深入理解Android端界面绘制原理/iOS端内存管理机制 4、熟悉网络通信机制和常用协议,有网络连接优化经验者优先 5、熟悉移动端性能调优方法 6、熟悉设计模式的相关知识 7、有即时通信产品开发经验者优先 8、熟悉React Native框架/JS语言者优先 9、了解swift/kotlin语言者优先 内推联系人(微信):Jaked_M 内推联系人(邮箱):liuchao@lilith.com </code></pre> <ul> <li>莉莉丝游戏 - 测试开发部</li> </ul> <pre><code>公司名:莉莉丝游戏 部门名称:测试开发部 工作城市:上海 经验要求:3年以上 招聘岗位:前端开发工程师 职位描述 1、参与莉莉丝游戏内部测试平台的研发并独立负责前端开发工作 2、与设计师同事合作,对UI图进行高度还原和页面交互的实现 任职要求 1、大学本科或以上学历,3年以上工作经验 2、熟练运用JavaScript语言与HTML5、CSS3等技术 3、熟悉模块化,熟练运用主流的Web端JS库和开发框架,例如:Vue、Webpack、React等 4、有node开发经验优先 内推联系人(微信):Jaked_M 内推联系人(邮箱):liuchao@lilith.com </code></pre> <ul> <li>莉莉丝游戏 - 产品发行中心</li> </ul> <pre><code>公司名:莉莉丝游戏 部门名称:产品发行中心 工作城市:上海 经验要求:2年以上 招聘岗位:前端开发工程师 (P5+) 职位描述 1、负责游戏官网、H5活动页、小程序等相关网站的前端开发与维护工作; 2、与设计师、后端同学紧密合作,负责产出高质量的产品前端层; 3、协助中台系统开发。 任职要求 1、大学本科或以上学历,2年以上工作经验 2、精通HTML5、CSS3、JavaScript等Web开发技术,具备扎实的前端基础; 3、对页面的架构和布局、多端的适配兼容、网站性能的优化、模块/组件等有深入的理解; 4、至少熟悉并上线使用过一种主流的前端开发框架,比如:vue、react; 5、热爱前端、较强的责任感、良好的团队协作能力。 内推联系人(微信):Jaked_M </code></pre> </li> </ul> 信息源https://www.scarsu.com/monthly_1_2021_01/#post-comment/忍不住的新努力:胡适的人生哲学https://www.scarsu.com/shizhi/https://www.scarsu.com/shizhi/保持质疑,保持兴趣,保持对“努力”的自信Sun, 31 Jan 2021 00:00:00 GMT<h2>引言</h2> <p>《忍不住的新努力》是文化大师<strong>胡适</strong>的随笔集,收集了他34篇经典文章。</p> <p>以前对胡适的了解,仅限于历史书中“新文化运动的倡导者”这样一个标签。</p> <p>读完这本书,才感受到一个更有温度的胡适:</p> <p>他的文字透露着他温和、乐观、自由、沉稳的性情和态度,他留学美国师从哲学家,做过北大的教授,参与或创办过《新青年》等等刊物,获得过诺贝尔文学奖提名。</p> <p>但他的建树不仅限于文学:</p> <p>他宣扬个性解放、思想自由、向当时代的学生科普宇宙观、时间观,他追求科学、实践和真理。</p> <p>在我们这一代人中,<strong>鲁迅</strong>先生很受欢迎,他比胡适大10岁,也算是同时代的人,他的文字犀利激烈、令人振聋发聩。</p> <p>但是读完这本书后,我发现自己更喜欢胡适,温和沉稳但坚定、有态度、务实。</p> <p>因为是随笔集,所以内容很宽泛,读完之后,我总结了其中几个令我有收获的主题:</p> <ul> <li>生活的意义</li> <li>读书/问学的方法</li> </ul> <h2>生活的意义</h2> <p>生活的意义、人生的意义,是一个很广很抽象的哲学话题,不同的人有不同的理解。</p> <p>这本书中的有几点能反映作者的人生哲学:</p> <h3>有意思的生活</h3> <p>如何过有意思的生活:一个人做的事应该件件事回的出一个“为什么”,说得出为什么,就是有意思的生活</p> <h3>迷茫?青年困惑?不满社会?</h3> <p>不满于社会,又无能为力,无所作为,怎么办?这是很多青年人的困惑。</p> <p>作者的答案,就是“独善其身”,先努力学习充实自己,然后能兼善天下。</p> <p>大多数的失望,皆起于<strong>奢望&gt;能力</strong>。</p> <p>因此,无论是内因还是外因导致的苦闷,都要先从自己做起。</p> <h3>人生的意义到底是什么?</h3> <p>人生的意义是各人自己造出来的</p> <p>人生的意义在于自己对待人生的态度</p> <p>人生的意义在于自己赋予其的意义</p> <p>“高尚、清贵、污浊、有用、无用”......都在于你自己的追求</p> <h2>对学习的理解</h2> <h3>学习驱动力</h3> <p>我之前专门写过一篇学习方法,但是没讨论过为什么要学习。</p> <p>活学活用,学习的意义在于知道自己“为什么”学习,也就是找到最原始的学习驱动力:</p> <ol> <li>保持<strong>质疑</strong>的态度。问题是一切知识的来源。</li> <li>保持<strong>兴趣</strong>。找到令自己感兴趣的事物,兴趣是驱动力。</li> <li>保持对<strong>努力</strong>的信心。功不唐捐,努力就一定不会后悔。</li> </ol> <h3>求知的原则</h3> <ol> <li>怀疑。始终保持怀疑的态度去看待他人、自己的认知,不盲从,构建自己的知识体系。</li> <li>务实。切实的做,而不是一味的打口号,立flag。</li> <li>讲证据。依靠证据去质疑别人、质疑自己现有的认知,依靠证据支撑自己的认知。</li> <li>追求真理。宇宙无穷,真理无穷。以追求真理为求学态度,以追求真理为乐趣所在。</li> </ol> <h3>学习的目标</h3> <p>学习的目标可以分为两点,就是提升<strong>智、识</strong>:</p> <ul> <li>识:拥有知识</li> <li>智:拥有运用、发挥知识的能力</li> </ul> <h3>学习的方法</h3> <ul> <li>精</li> </ul> <ol> <li> <p>眼到,要理解字面意思</p> </li> <li> <p>口到,熟读</p> </li> <li> <p>心到,思考,横向比较思考,纵向追根究底,不断质疑“为什么”,和已有知识建立连接,融入自己的知识体系</p> </li> <li> <p>手到,抄录、提炼、总结心得,知识只有在经过自己的思考提炼,形成自己的“输出”后,才真正成为自己的知识</p> </li> </ol> <ul> <li>博</li> </ul> <p>构建金字塔型的知识体系,能广大、有专精</p> 个人成长https://www.scarsu.com/shizhi/#post-comment/GTD时间管理https://www.scarsu.com/gtd/https://www.scarsu.com/gtd/Get Things Done,简单高效的应对信息洪流Wed, 27 Jan 2021 00:00:00 GMT<h2>优点</h2> <ul> <li>更好的应对<strong>信息洪流</strong>,不被其打乱<strong>节奏</strong>,减少信息焦虑,减压</li> </ul> <p>遇见一个信息就处理一个,很容易打乱节奏,先收集再定期处理,类似计算机进程调度</p> <ul> <li>和任务管理协同执行,定期处理信息、更新任务,可以使任务更灵活稳定,成长<strong>效率</strong>更高</li> </ul> <p>例如每周7天,前6天专心执行当下的任务,不理会新的信息,只需要将其丢入inbox;</p> <p>第7天专心整理inbox,对任务做相应的调节(毕竟大脑是个单线程机器</p> <ul> <li>利于对信息抽丝剥茧,更高效的将<strong>信息</strong>筛选转化为自己的<strong>认知</strong></li> </ul> <p>举个例子🌰,你养了一个鱼塘,每天都去钓鱼,无论肥瘦只要上钩你都照单全收,最后鱼篓不一定挺得住不说,鱼的质量也不高; 但是你养上一周一个月,再去挑大鱼,又省力,质量又高 😉</p> <h2>简化的GTD流程</h2> <p><img src="/images/picgo/picgo20210127180326.png" alt="GTD流程图" /></p> <h3>1 执行 <strong>&amp; 收集期</strong></h3> <ul> <li>在各种设备、将各种来源的新信息,统一收集到inbox收集箱</li> <li>专心的执行当下的任务,不受信息困扰</li> </ul> <p>inbox的形式千千万,用的开心就好</p> <p>可以使用专业的app,例如:OmniFocus、Doit IM</p> <p>也可以使用更易得的工具,例如:只有自己的微信QQ群、邮箱</p> <p>我个人比较偏向QQ群,1是手机电脑qq常在线,2是比微信方便同步,3支持文字 图片 链接 文件,覆盖大部分场景</p> <h3>2 <strong>处理期</strong></h3> <ul> <li>定期整理:规定定期的时间,例如每周末/每月底,处理inbox</li> <li>理解转化:筛选有价值的信息,理解并记忆,输出自己的东西,归纳融合到自己的知识体系中</li> <li>计划:根据信息的更新,确定/调整下一周期的待办事项</li> </ul> <h2>更多资源</h2> <ul> <li><a>一年多的GTD和自我管理之路文章</a></li> </ul> <hr /> <p>顺嘴提一下,本篇文章也是作者通过GTD方法得来的:听微信群友提到GTD,就把关键词转到了inbox,月末的时候整理inbox,检索GTD信息,有了自己的理解,输出成了本篇文章。</p> <p>希望对你有帮助,成长愉快:)</p> 个人成长https://www.scarsu.com/gtd/#post-comment/关于我 | 2021年,给自己来点鸡血https://www.scarsu.com/2021_hello/https://www.scarsu.com/2021_hello/及时止废Fri, 01 Jan 2021 00:00:00 GMT<h2>为什么要趁年轻多学习&lt;a rel="nofollow" href="https://www.zhihu.com/question/354919014/answer/906152325"&gt;&lt;i class="fa fa-link"&gt;&lt;/i&gt;原文&lt;/a&gt;</h2> <blockquote> <p><strong>爆炸性压力才能带来爆炸性进步</strong></p> <p>每次我状态低迷的时候,我都会看看这个视频,视频18分钟,如果你懒得看,我简述一下:</p> <p>演讲者是许峰源先生,他出身一个非常贫穷的家庭,整个家庭,靠的是父亲踩着三轮车出去卖豆腐微薄的收入支撑着。</p> <p>这不是一个烂仔逆袭的故事,因为从小看到了生活艰苦的一面,许峰源一直很努力想考上台大法律系,因为成为律师才有高收入,才能改变家庭的现状。</p> <p>不幸的是,在他上大学的时候,父亲却查出了舌癌晚期,只剩一年左右的时间,为了让父亲在临终前看到自己的孩子成才,许峰源用了极短的时间通过了司法考试,成为了一名律师,让父亲看到了自己的律师证,才安然去世。</p> <p>祸不单行,很快许峰源的母亲也查出了患有肺腺癌,一种扩散很迅猛的癌症,为了让母亲有一个安享晚年的环境,许峰源在23岁的时候,毅然辞职创业,白天在律师事务所打拼,晚上做培训,最终让母亲住上了好房子,接受更好的治疗,然后平静地送走了母亲。</p> <p>前半生,许峰源先生为之奋斗的两个对象都走了,迷茫了一阵子之后,他依然没有放弃努力,而是选择了实现自我,成为了一名作家。</p> <p>再烂的牌也得打下去,这就是人生</p> </blockquote> <h2>成熟的一些标志</h2> <blockquote> <p>能克制欲望,不追求即时反馈,延迟享受。</p> <p>保持一致性,无论在人群中还是独处时,知行合一,不卑不亢,不矫揉造作,不哗众取宠。心中始终有底线、有原则、有追求。时刻反省自己:what在做什么、why为什么这样做、how如何做的更好</p> </blockquote> <p>—— 尼古拉斯·鱼</p> <h2>别让任何人打乱你的人生节奏</h2> <blockquote> <p>每个人的人生都不同</p> <p>"Not everything that counts can be counted,and not everything that's counted truly counts"</p> <p>"并不是每件算出来的事,都有意义;也不是每件有意义的事,都能被算出来" ——爱因斯坦</p> </blockquote> <p><a>@https://www.bilibili.com/video/BV1WW411F7Hx</a></p> <h2>如何追求快乐</h2> <blockquote> <p>有很多快乐是放纵的快乐,是降低了人性尊严的快乐,而越能体现人性尊严的快乐,越是一种高级的快乐。</p> <p>追求高级的快乐并不意味着放弃低级的快乐,但是如果你的眼目永远只关注地下,你永远不知道向上看有多么的快乐。</p> </blockquote> <p>——罗翔</p> <p><a>@https://www.bilibili.com/video/BV1AE411T7p7</a></p> <blockquote> <p>I don't need dollar bills to have fun</p> </blockquote> <p>——【Cheap Thrills】 Sia</p> <h2>关于坚持</h2> <blockquote> <p>坚持这两个字,远比你想象中的要难的多,但也比你想象中的有效的多。</p> <p>'You do make a difference!'</p> </blockquote> <p><a>@https://www.bilibili.com/video/BV1XJ411d7Xx</a></p> <blockquote> <p>两年,是很容易虚度过去的时长,也是足够改变自己的时长。</p> </blockquote> <p><a>@https://www.bilibili.com/video/BV1NE41197sr</a></p> <h2>就是不想努力怎么办</h2> <blockquote> <p>我就想做一个安于现状的人</p> <p>就想利用上班赚钱过好自己的小日子</p> <p>就想平凡的过完一生</p> <p>我就是不想拼命奋斗,拼命努力,拼命内卷</p> <p>不可以吗?</p> </blockquote> <p>当然可以,每个人的追求不同,淡泊名利,平静一生,真正能做到的话,是一种很高的人生境界。</p> <p>但是你做出这种决定,就要考虑其带来的结果</p> <blockquote> <p>你能做到真正的“淡泊名利”吗?</p> <p>当别人用光鲜亮丽的服装、车子、房子包装和提升自己的生活品质时,你能做到不羡慕吗</p> <p>当别人在马尔代夫浮潜、在阿尔卑斯滑雪、在土耳其滑翔、在富士山脚泡温泉喝清酒,你能做到不羡慕吗</p> <p>你身边的人生活品质都比你高得时候,你会不会后悔</p> <p>你的普通收入扣除房子首付、房贷、车子、奶粉钱之后你还足够安稳吗</p> <p>如果不买房,你可以做到一生租房,并容忍一生到老不断的搬家吗</p> <p>你的普通收入能让你匹配上你心仪的另一半吗</p> <p>你的现状能维持你一生的稳定平凡吗?你能对抗人生所有的风险吗</p> <p>你可以为自己的一生、父母后半生、孩子前半生的大大小小的健康问题买单吗</p> <p>如果你有了孩子,你作为爸爸/妈妈,能给孩子最好的教育吗</p> </blockquote> <p>如果你深刻的考虑了这些问题,得到的答案都是肯定的,那么安于现状,不拼命努力,也没什么不好</p> <p>每个人的人生都不同,人生的路也没有对错之分,只是路上的酸甜苦辣,你需要独自承担</p> <h2>比本文更硬核的鸡血</h2> <p><a>为什么要趁年轻多学习 - 知乎</a> <a>乔布斯 斯坦福大学演讲 - bilibili</a> <a>前端er要向qian看 - BOSS直聘</a> <a>别让任何人打乱你的人生节奏 - bilibili</a> <a>如何对抗平庸的生活 - 罗翔</a> <a>做人一定要坚持 - bilibili</a> <a>改变自己,只需要两年时间 - TED</a> <a>真正的自律 - Will Smith</a> <a>自信心不足? - bilibili</a></p> <hr /> <p>2021,自律 + 坚持,一路向前</p> 个人成长https://www.scarsu.com/2021_hello/#post-comment/动画demo解释 防抖、节流、rAF(CSS Tricks译文)https://www.scarsu.com/debounce_raf/https://www.scarsu.com/debounce_raf/这三种技术用于优化事件处理函数,都很有用,且各有区别,互相补充。Wed, 30 Dec 2020 00:00:00 GMT<p>原文链接:<a>防抖与节流的区别</a></p> <p>译者注:为了文章更易理解,对原文略有改动</p> <hr /> <p><strong>防抖</strong>与<strong>节流</strong>是两种相似(但不同)的技术,用于控制一定时间内函数的执行次数。</p> <p>当我们为<code>DOM</code>事件添加事件处理函数时,防抖或节流函数十分有用。为什么呢?因为我们并不能控制<code>DOM</code>事件被触发的频率,而防抖和节流在事件和事件处理函数之间,为我们添加了一个控制层。</p> <p>例如<code>scroll</code>事件,看这个demo:</p> <p>&lt;iframe height="265" style="width: 100%;" scrolling="no" title="Scroll events counter" src="https://codepen.io/dcorb/embed/PZOZgB?height=265&amp;theme-id=dark&amp;default-tab=css,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"&gt; See the Pen &lt;a href='https://codepen.io/dcorb/pen/PZOZgB'&gt;Scroll events counter&lt;/a&gt; by Corbacho (&lt;a href='https://codepen.io/dcorb'&gt;@dcorb&lt;/a&gt;) on &lt;a href='https://codepen.io'&gt;CodePen&lt;/a&gt;. &lt;/iframe&gt;</p> <p>当使用触控板,滚轮,或者滚动条滚动时,每秒钟可以轻易地触发30个事件。但是在我的测试中,在手机中缓慢滑动屏幕,每秒可以触发多达100个事件。你能确保你的事件处理函数在这种执行频率下正常工作吗?</p> <p>2011年,Twitter网站上出现了一个问题:当你在向下滚动Twitter feed时,网页变得缓慢且无响应。John Resig发表了<a>一篇关于这个问题的博客</a>,文章中解释了将消耗昂贵的函数直接附加到<code>scroll</code>事件上是多么的糟糕。</p> <p>John建议的解决方案(当时是五年前)是在<code>onScroll</code>事件之外,每隔250ms运行一个循环。这样处理程序就不会与事件耦合。通过这个简单的技术,我们可以避免破坏用户体验。</p> <p>现如今,有一些更复杂一些的处理事件的方法。让我给大家介绍一下<code>Debounce</code>、<code>Throttle</code>和<code>requestAnimationFrame</code>,以及相应的demo。</p> <h2><strong>Debounce 防抖</strong></h2> <p><code>Debounce</code> 防抖技术允许我们将多次连续的执行"分组"到一次单一的执行中。</p> <p><img src="https://i0.wp.com/css-tricks.com/wp-content/uploads/2016/04/debounce.png" alt="https://i0.wp.com/css-tricks.com/wp-content/uploads/2016/04/debounce.png" /></p> <p>想象一下这样的场景,你在电梯里,电梯门开始关闭,突然有另一个人想上电梯,电梯则不会运行,门会再次打开。然后又有一个人要上电梯,电梯再次延迟了它的运行(移动楼层),但优化了它的资源。</p> <p>可以在下面的示例中,尝试在顶部的“Trigger area”中点击或移动:</p> <p>&lt;iframe height="265" style="width: 100%;" scrolling="no" title="Debounce. Trailing" src="https://codepen.io/dcorb/embed/KVxGqN?height=265&amp;theme-id=dark&amp;default-tab=css,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"&gt; See the Pen &lt;a href='https://codepen.io/dcorb/pen/KVxGqN'&gt;Debounce. Trailing&lt;/a&gt; by Corbacho (&lt;a href='https://codepen.io/dcorb'&gt;@dcorb&lt;/a&gt;) on &lt;a href='https://codepen.io'&gt;CodePen&lt;/a&gt;. &lt;/iframe&gt;</p> <p>在上面的示例中可以看到,<code>debounced</code>事件是如何代替一组连续快速触发事件的。但如果事件的触发有很大的时间间隔,则不会发生<code>debouncing</code>。(可以这样理解,如果一直有人要上电梯,电梯就不会运行,直到等待一定时间内无人上电梯,电梯就会开始运行,在上述的示例中,这个<em>等待时间</em>被设定为四个刻度,也就是400ms)</p> <h2>l<strong>eading / immediate 参数</strong></h2> <p>在上述的示例中,<code>debouncing</code>事件需要<em>等待</em>,直到事件在一定时间内停止触发,才会执行函数。这种场景与等电梯的场景吻合。</p> <p>如果有另一种场景,需要在事件触发时,就立即执行函数,在快速连续触发的过程中,直到有一个暂停(满足<em>等待时间</em>),才会再次执行函数。</p> <p>这种需求,可以通过<code>leading</code>参数来实现:(在underscore.js中,这个参数的名称叫 <code>immediate</code> )</p> <p><img src="https://i2.wp.com/css-tricks.com/wp-content/uploads/2016/04/debounce-leading.png" alt="https://i2.wp.com/css-tricks.com/wp-content/uploads/2016/04/debounce-leading.png" /></p> <p>“<code>leading</code>”防抖的demo:</p> <p>&lt;iframe height="265" style="width: 100%;" scrolling="no" title="Debounce. Leading" src="https://codepen.io/dcorb/embed/GZWqNV?height=265&amp;theme-id=dark&amp;default-tab=css,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"&gt; See the Pen &lt;a href='https://codepen.io/dcorb/pen/GZWqNV'&gt;Debounce. Leading&lt;/a&gt; by Corbacho (&lt;a href='https://codepen.io/dcorb'&gt;@dcorb&lt;/a&gt;) on &lt;a href='https://codepen.io'&gt;CodePen&lt;/a&gt;. &lt;/iframe&gt;</p> <h2><strong>Debounce 实现</strong></h2> <p>我第一次看到debounce的Javascript实现是2009年,在<a>John Hann的这篇文章</a>中(他也是这个词的发明者)。</p> <p>不久之后,Ben Alman创建了<a>一个jQuery插件</a>(不再维护),一年之后,Jeremy Ashkenas将其<a>添加到了underscore.js</a>中。后来,它又被添加到Lodash中,成为undererscore的替代方案。</p> <p>这3种实现内部有些不同,但它们的接口都差不多。</p> <p>曾经有一段时间,在我于2013年发现<code>_.debounce</code>函数中的<a>一个bug</a>之后,underscore采用了Lodash的<code>debounce</code> / <code>throttle</code>实现。从那时起,两种实现都有了长足的发展。</p> <p>Lodash在其<code>_.debounce</code>和<code>_.throttle</code>函数中 <a>增加了</a> 更多的功能。原来的<code>immediate</code> 标志被替换为<code>leading</code> 和<code>trailing</code> 选项。你可以选择启用一个,或者两个。默认情况下,只有<code>trailing</code> 被启用。(leading可以理解为,在一组连续触发事件的起始,就调用函数;而trailing,则是在一组连续触发事件的末尾,经过<em>等待时间</em>后,执行函数)</p> <p>还有一个新的<code>maxWait</code>选项(目前只在Lodash中使用)在本文中没有涉及,但它可能非常有用。</p> <p>实际上,在Lodash的源码种,<code>throttle</code>节流函数是用通过<code>_.debounce</code>和<code>maxWait</code>选项来定义的。</p> <h2><strong>Debounce 实例</strong></h2> <h3><strong>Resize 实例</strong></h3> <p>当调整(桌面端)浏览器窗口的大小时,可能会触发许多的<code>resize</code>事件。</p> <p>可以在下面的demo中看到:</p> <p>&lt;iframe height="265" style="width: 100%;" scrolling="no" title="Debounce Resize Event Example" src="https://codepen.io/dcorb/embed/XXPjpd?height=265&amp;theme-id=dark&amp;default-tab=js,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"&gt; See the Pen &lt;a href='https://codepen.io/dcorb/pen/XXPjpd'&gt;Debounce Resize Event Example&lt;/a&gt; by Corbacho (&lt;a href='https://codepen.io/dcorb'&gt;@dcorb&lt;/a&gt;) on &lt;a href='https://codepen.io'&gt;CodePen&lt;/a&gt;. &lt;/iframe&gt;</p> <p>如你所见,上面的例子中,启用了默认的<code>trailing</code>选项,因为我们只关心用户停止resize后的最终值。</p> <h3>带有AJAX请求的自动填充输入框的输入事件</h3> <p>有一些场景例如等待用户停止输入后再验证其输入,反馈验证信息。这种场景下 <code>_.debounce</code>可以实现:只有当用户停止输入时才发送请求。</p> <p>此时,<code>leading</code> 标志没有意义,因为我们需要等待至最后的输入。</p> <p>&lt;iframe height="265" style="width: 100%;" scrolling="no" title="Debouncing keystrokes Example" src="https://codepen.io/dcorb/embed/mVGVOL?height=265&amp;theme-id=dark&amp;default-tab=js,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"&gt; See the Pen &lt;a href='https://codepen.io/dcorb/pen/mVGVOL'&gt;Debouncing keystrokes Example&lt;/a&gt; by Corbacho (&lt;a href='https://codepen.io/dcorb'&gt;@dcorb&lt;/a&gt;) on &lt;a href='https://codepen.io'&gt;CodePen&lt;/a&gt;. &lt;/iframe&gt;</p> <h2>如何使用<strong>debounce 和 throttle 以及 常见陷阱</strong></h2> <p>你可以自己写<code>debounce</code>/<code>throttle</code>函数,或者从一些随机的博客文章中复制它,但我的建议是直接使用 <code>underscore</code> 或 <code>Lodash</code>库。</p> <p>如果你只需要<code>_.debounce</code>和<code>_.throttle</code>函数,你可以使用Lodash自定义构建器来输出一个自定义的2KB minified库。下面时构建命令:</p> <pre><code>npm i -g lodash-cli lodash include = debounce, throttle </code></pre> <p>也就是说,大多数人都是通过webpack/browserify/rollup工具,使用模块化形式的<code>lodash/throttle</code>和<code>lodash/debounce</code>或<code>lodash.throttle</code>和<code>lodash.debounce</code>包。</p> <p>一个常见的陷阱是,多次调用<code>_.debounce</code> 函数:</p> <pre><code>// WRONG $(window).on('scroll', function() { _.debounce(doSomething, 300); }); // RIGHT $(window).on('scroll', _.debounce(doSomething, 200)); </code></pre> <p>在lodash 和 underscore.js中,为debounced饭都处理过的函数创建一个变量,可以调用私有方法 <code>debounced_version.cancel()</code></p> <pre><code>var debounced_version = _.debounce(doSomething, 200); $(window).on('scroll', debounced_version); // If you need it debounced_version.cancel(); </code></pre> <h2><strong>Throttle 节流</strong></h2> <p>通过使用 <code>_.throttle</code>, 可以限制函数在 X 毫秒内,最多只能执行一次。</p> <p>与<code>debouncing</code>的主要区别在于,节流保证了函数的定期执行,至少每X毫秒一次。</p> <h2><strong>Throttling 实例</strong></h2> <h3><strong>无限滚动</strong></h3> <p>举一个很常见的例子,用户正在向下滚动你的无限滚动页面。你需要检查用户离底部有多远。如果用户在底部附近,我们应该通过Ajax请求更多的内容,并将其添加到页面中。</p> <p>在这种场景下,<code>_.debounce</code>就不适用了,它只有在用户停止滚动时才会触发......而我们需要在用户到达底部之前开始获取内容。而<code>_.throttle</code>可以保证我们不断地检查用户离底部有多远。</p> <p>&lt;iframe height="265" style="width: 100%;" scrolling="no" title="Infinite scrolling throttled" src="https://codepen.io/dcorb/embed/eJLMxa?height=265&amp;theme-id=dark&amp;default-tab=js,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"&gt; See the Pen &lt;a href='https://codepen.io/dcorb/pen/eJLMxa'&gt;Infinite scrolling throttled&lt;/a&gt; by Corbacho (&lt;a href='https://codepen.io/dcorb'&gt;@dcorb&lt;/a&gt;) on &lt;a href='https://codepen.io'&gt;CodePen&lt;/a&gt;. &lt;/iframe&gt;</p> <h2><strong>requestAnimationFrame (rAF)</strong></h2> <p><code>requestAnimationFrame</code> 是限制函数执行速度的另一种方式。</p> <p>它相当于<code>_.throttle(dosomething, 16)</code>,但保真度要高很多,因为它是浏览器原生的API,拥有更好的准确性。</p> <p>可以考虑使用<code>rAF</code> API,作为节流函数的替代品,以下是它的优缺点:</p> <h3>优点:</h3> <ul> <li>目标为60fps(即每秒60帧),但是由浏览器内部机制决定如何安排渲染的最佳时间。</li> <li>更简单和更标准的API,未来不会改变,更好维护。</li> </ul> <h3>缺点:</h3> <ul> <li>rAFs的启用/取消是我们的责任,不像<code>debounce</code>或<code>throttle</code>,是内部管理的。</li> <li>如果浏览器标签页未激活,它就不会被执行。(对于滚动、鼠标或键盘事件来说,这并不重要)。</li> <li>虽然所有的现代浏览器都提供了RAF,但在IE9、Opera Mini和旧的Android中仍然不支持。仍然需要<a>polyfill</a> 。</li> </ul> <p>根据经验来讲,如果我的JavaScript函数是 "绘画 ",或者会直接变更动画相关属性,我会使用<code>requestAnimationFrame</code>,以及在一切涉及重新计算元素位置的地方使用它。</p> <p>如果要进行Ajax请求,或者决定是否添加/删除一个class(可能会触发CSS动画),我会考虑<code>_.debounce</code>或<code>_.throttle</code>,因为可以设置更低的执行速率(例如200ms,而不是16ms)。</p> <h3><strong>rAF 实例</strong></h3> <p>这个demo灵感来自于 <a>Paul Lewis的文章</a>, 文章做他详细解释了demo中的原理和逻辑。</p> <p>我把<code>rAF</code>和  <code>16ms 的_.throttle</code> 放在一起进行了比较,结果是它们的性能相似。但是在更复杂的情况下,rAF可能性能会更高。</p> <p>&lt;iframe height="265" style="width: 100%;" scrolling="no" title="Scroll comparison requestAnimationFrame vs throttle" src="https://codepen.io/dcorb/embed/pgOKKw?height=265&amp;theme-id=dark&amp;default-tab=js,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"&gt; See the Pen &lt;a href='https://codepen.io/dcorb/pen/pgOKKw'&gt;Scroll comparison requestAnimationFrame vs throttle&lt;/a&gt; by Corbacho (&lt;a href='https://codepen.io/dcorb'&gt;@dcorb&lt;/a&gt;) on &lt;a href='https://codepen.io'&gt;CodePen&lt;/a&gt;. &lt;/iframe&gt;</p> <p>我在headroom.js库里见到过<code>rAF</code>技术更高级的实例,其中的 <a>逻辑被解耦</a> 并且被包装在了对象中。</p> <h2>总结</h2> <p><code>debounce</code>防抖, <code>throttle</code> 节流和 <code>requestAnimationFrame</code> 可以用来优化事件处理函数,三种技术都很有用,且各有区别,互相补充:</p> <ul> <li><strong>debounce防抖:</strong> 将快速连续的多次事件触发分组,归为一次执行。</li> <li><strong>throttle节流:</strong> 确保每隔X 毫秒就有一次稳定的执行,例如每200ms检查一次用户滚动位置以触发一个CSS动画。</li> <li><strong>requestAnimationFrame:</strong> 节流函数的16ms替代选择。更适用于在页面上重新计算/渲染元素的函数,能得到更平滑的动画。但是注意: IE9 不支持。</li> </ul> 前端https://www.scarsu.com/debounce_raf/#post-comment/当我谈跑步时我谈些什么:痛苦难以避免,而磨难可以选择https://www.scarsu.com/running_life/https://www.scarsu.com/running_life/村上春树的跑步与人生哲理Mon, 30 Nov 2020 00:00:00 GMT<h2>引言</h2> <p>即使我是一个不怎么爱看文艺类书籍的理工科出身程序猿,也听过<strong>村上春树</strong>的大名。</p> <p>他是日本著名的作家、小说家,代表作有《挪威的森林》、《1Q84》。</p> <p>我的书单上从没有出现过<strong>村上春树</strong>的书,直到有一天逛书店,看到了这本《当我谈跑步时我谈些什么》。</p> <p>那段时间刚好开始晨跑,每天早上起床5公里,大约坚持了一个多月,十分倦怠,所以希望看看这本书,<strong>为意志力充充电</strong>。</p> <h2>作者的跑步人生</h2> <p>作者年近30时,才转行做一名职业作家。</p> <p>开始专职于写作之后,他发现自己每天需要高强度的脑力工作,一坐就是一整天,一天下来要吸掉60多支烟。</p> <p>要维持体力,又要将体重保持得“恰到好处”,村上春树选择跑步,作为解决健康问题的方法,并发展成了终生爱好。</p> <p>每天一小时的长跑,几乎每年都参加一场马拉松,即使没拿到过名次和奖励,但依然跑了30年。</p> <blockquote> <p>跑步时,人最残酷的对手是自己,其他选手都不是真正的敌人;</p> <p>真正的敌人就是你自己,就是你用智慧和勇气掌控自己情绪的能力。</p> </blockquote> <blockquote> <p>戴好流线型头盔,架上体育专用太阳眼镜</p> <p>水壶里灌满了水,设定好计时器</p> <p>一意猛骑</p> </blockquote> <p><img src="/images/picgo/picgo20210125155333.png" alt="" /></p> <p>书中作者对跑步、以及参加铁人三项的细微感触、日日坚持跑步的所见所闻、所惑所思,十分打动人心。</p> <p>很遗憾的是这本书还没看完的时候,我由于膝盖疼痛没能继续坚持晨跑。</p> <p>但是我依然看完了这本书,因为这本书不仅仅讲了作者的跑步历程和意义。</p> <p>令我收获良多的,还有贯穿全书的<strong>人生哲学</strong>。</p> <h2>坚持与磨砺</h2> <p><img src="/images/picgo/picgo20210201093452.png" alt="目下3米,便是我当下的世界" /></p> <blockquote> <p>无论奔跑速度降了多少,我都不走,这是原则,违背了自己顶下的原则,哪怕只有一次,以后就将违背更多原则</p> </blockquote> <p><img src="/images/picgo/picgo20210125114249.png" alt="" /></p> <p>这是<strong>村上春树</strong>诠释的马拉松精神,更是一种对待人生的态度。</p> <p>无论多么微小的举动,长久坚持,就一定会有其影响力。</p> <blockquote> <p>痛苦难以避免,而磨难可以选择</p> <p>Pain is inevitable, Suffering is optional</p> </blockquote> <p>坚持跑步的理由不过一丝半点,中断跑步的理由却足够装满一辆大型载重卡车。我们只能将那“一丝半点的理由”一个个慎之又慎地不断打磨。见缝插针,得空儿就孜孜不倦地打磨它们。</p> <blockquote> <p>刻意经历这痛苦</p> <p>起码曾经努力的事实会留存下来</p> <p>即使这是虚妄的没结果的行为,也不是愚蠢的行为</p> </blockquote> <p><strong>曾经努力</strong>就不会给日后的自己,留下后悔的机会。</p> <h2>输赢与自卑</h2> <blockquote> <p>在长跑中,如果说有什么必须战胜的对手,那就是过去的自己</p> </blockquote> <blockquote> <p>欧内斯特•海明威好像也说过类似的话:持之以恒,不乱节奏,对于长期作业实在至为重要。</p> <p>一旦节奏得以设定,其余的问题便可以迎刃而解。</p> <p>诚然,我并非毫无争强好胜之心。不过不知何故,跟别人一决雌雄,我自小就不甚在乎胜负成败。这一性格在长大成人后也大致未变。</p> <p>无论何事,赢了别人也罢输给别人也罢,都不太计较,倒是更为关心能否达到为自己设定的标准。</p> </blockquote> <p><strong>村上春树</strong>参加多次马拉松也未获得过名次或奖励,诺奖也陪跑多年,但是不曾气馁,仍然全意追求自己想要的人生,掌握并坚持自己的节奏。</p> <blockquote> <p>世人皆有其唯一性,必定与他人相异,不必与人比较</p> <p>年少时,无力客观的把握自己的定位</p> <p>极易因微不足道的事而沾沾自喜</p> <p>也极易产生自卑感。</p> <p>随着年龄的增长,经历了形形色色的失误</p> <p>该拾起来的拾起来,该抛弃的抛弃掉</p> <p>然后才能形成这样的认知:</p> <p>缺点如果以一去数,必将没完没了</p> <p>可是优点肯定也有</p> <p>我们只能凭借手头现有的东西去面对世界</p> </blockquote> <p>这是他对<strong>自卑</strong>的态度,语言真切,结论也很直观:</p> <p><strong>自卑、与他人比较是虚妄的,只需要利用好现有的条件,做最好的自己。</strong></p> <h2>保持自己的节奏</h2> <blockquote> <p>我是那种喜欢独处的人。更确切地说,我是那种不觉得孤独是痛苦的人。我发现每天花一两个小时独自跑步,不跟任何人说话,还有四五个小时独自坐在办公桌前,既不困难,也不无聊。我从小就有这种倾向,当时如果有选择的话,我更喜欢自己看书或专心听音乐,而不是和别人在一起。我总是能想出自己要做的事情。</p> </blockquote> <blockquote> <p>希望一人独处的念头,始终不变地存于心中。</p> <p>所以一天跑一小时,来确保只属于自己的沉默的时间,</p> <p>对我的精神健康来说,成了具有重要意义的功课。</p> <p>至少在跑步时不需要和任何人交流,不必听任何人说话,只需眺望周围的风光,凝视自己即可。</p> <p>这是任何东西都无法替代的宝贵时刻。</p> </blockquote> <p>从小我的性格,就十分依赖别人,和朋友玩就久久不想分开,不喜欢一个人睡觉,没有人陪伴就会觉得孤独。</p> <p>这种抵触一个人独处的情绪,直到成年才慢慢消除。</p> <p>因为越长大,才越能体味到作者对“独处”的感触。</p> <ul> <li>长大了才知道,人生的路,出生到死亡,没有人能真正陪伴你全程</li> <li>长大了才知道,热闹的人群给你带来的也许是温暖,但不是成长</li> <li>长大了才知道,孤独其实并不是坏事</li> <li>长大了才知道,这世界上没有任何人能真正的与你<strong>感同身受</strong></li> <li>长大了才知道,你所有的行为都要自己承担后果,你要为自己兜底</li> </ul> <p>而当我学会独处,并开始享受独处,我才意识到自己真正的成熟了。</p> <blockquote> <p>不管全世界所有人怎么说,我都认为自己的感受才是正确的。</p> <p>无论别人怎么看,我绝不打乱自己的节奏。</p> <p>喜欢的事自然可以坚持,不喜欢怎么也长久不了。</p> </blockquote> <p>人在失去自我方面浪费的时间越多,形成自己的特点的机会越少,大多数人最后都活成了麻雀群里的一个点。</p> <p>学会独处,更多的发现和探索自己,才能找到真正喜欢的事情,才能独一无二的特别的你。</p> <h2>结语</h2> <p>无论少年还是暮年,</p> <p>希望你心中始终有一面鲜明的旗帜,指示着你自己的坚持;</p> <p>希望你心中始终有一扇嘀嗒的时钟,稳定着你自己的节奏。</p> 个人成长https://www.scarsu.com/running_life/#post-comment/自卑与超越:一本对自我的答疑书https://www.scarsu.com/meaning_of_life/https://www.scarsu.com/meaning_of_life/我为什么是我Fri, 30 Oct 2020 00:00:00 GMT<h2>书与作者简介</h2> <ul> <li>作者:[奥地利]阿尔弗雷德·阿德勒 <ul> <li>医学博士</li> <li>从医:眼科、全科、精神科</li> <li>探索人格、心理与身体,得到了当时心理学大师弗洛伊德的赏识,加入了弗的心理分析学会</li> <li>与弗在产生分歧,退出了弗的心理分析学会,转而自立门派,研究“个体心理学”</li> <li>因“个体心理学”研究、一系列著作出版,而声名远播</li> </ul> </li> <li>书:心理学必读经典书籍《What Life Should Mean To You》 <ul> <li>从个体心理学的观点出发,阐明人生道路和人生意义</li> <li>是一本通俗性读物,但包含着极深的哲理,和丰富的学术创见</li> <li>全书涉及了人生的方方面面:人活着的意义、心灵&amp;肉体关系、自卑感&amp;优越感、早起记忆和梦的意义、原生家庭和学校对人的影响、青春期、犯罪、职业、人&amp;同伴&amp;社交、爱情&amp;婚姻......</li> <li>中文书名的由来:这本书着重讲了自卑感的形成,自卑感对人的影响,如何超越自卑感,如何将自卑感转为对优越地位的追求以取得成就</li> </ul> </li> </ul> <h2>带着问题看文章</h2> <p>很对人从孩童时期、到青春期、到中年,都在不断地苦苦思索人生的意义。</p> <p>很对人活一世,即使到临死前,也没能够了解自我。</p> <p>不知道这一生在追寻什么,最终得到了什么。</p> <p>因此,可以把这本书当作一本对自我的答疑书来看。</p> <p>当对人生的方方面面产生困惑时,可以翻阅本书,跟着阿德勒的个体心理学,探寻自己内心的最深处,摸索答案。</p> <hr /> <h2>生活的意义到底是什么</h2> <p>职业、交际和两性</p> <blockquote> <p>1、我与地球:我们生活在地球上,依靠地球所提供的资源生存,除此之外别无选择。</p> </blockquote> <p>2、我与他人/种族:任何人都是人类族系的一员,每个人必然要与他人发生关系。</p> <p>3、我和她:这一问题涉及爱情和婚姻。人类有两种性别,男和女。任何人的一生都无法避开爱情和婚姻这一问题。</p> <blockquote> <p>1、在地球的有限资源限制下,为了永存,我们应该如何工作?</p> </blockquote> <p>2、为了与人合作,共同发展,我们应该获得怎样的定位和身份?</p> <p>3、面对“人有男女”和“人类延续依赖于爱与婚姻”这一事实,我们应该如何调整自我?</p> <p>所以,个体心理学认为人类的所有问题都可以归于职业、交际和两性这三个问题。</p> <p>比如,一个人完全没有爱情,生活遭遇挫折,在工作上也表现得平平庸庸,并且不善交际,朋友很少,他觉得与同伴交往是非常痛苦的事情。那么生活对于他来说就是痛苦而危险的事。</p> <p>而如果一个人交友广泛,人脉很广,事业有成,拥有甜蜜的爱情和幸福的生活。那么我们可以断定,他的生活是丰富的,是充满创造性的。</p> <p>所以,作者认为,生命的意义在于乐于关注他人,渴望成为社会大家庭一员,梦想着为人类和社会贡献自己的力量。</p> <p>著名国学大师季羡林在望九之年写过一篇文章,叫《人生的意义与价值》,在文章的最后,他是这么说的:</p> <p>如果人生真有意义与价值的话,其意义与价值就在于对人类发展的承上启下,承前启后的责任感。 古往今来,但凡人们认为具有“生命意义”的人或事,都离不开对他人和社会的贡献。那些赋予人生以个人意义的人,他们的人生就此走过,没有留下一丝痕迹。</p> <p>因此作者说:</p> <p>个人意义没有任何价值,真正的生命意义存在于个体与他人的交互作用中。每个人都希望自己变得重要、有价值,但如若不能搞懂个人的成就建立在对他人做出贡献的基础之上,那就太容易走上歧途。 至此我们就能理解前面的话了,在努力追求优越感的过程中,只有那些为了他人的利益而前进的人和为了社会的发展而奋斗的人,才是能够超越生活,从而顺利获得优越感的人。</p> <p>以他人利益为重,那我们自己的利益怎么办?要回答这个问题,我们需要理解个体与社会的关系。</p> <h2>早期记忆/童年 对一个人的影响有多大</h2> <blockquote> <p>一个人的价值观,世界观都和经历有关,所有的经历造就了现在的你,你的所有需求,你的所有期望,都是曾经你经历的没有得到,所以你现在渴望得到。 没有了解一个人的童年,是不会了解他的现在的。</p> </blockquote> <h2>自卑感&amp;优越感</h2> <blockquote> <p>我们每个人都有不同程度的自卑感,因为我们都想让自己更优秀,让自己过更好的生活。自卑感的存在并不是一件坏事,因为它激励了人不断追求卓越,克服自身的障碍,在有限的生命空间内发挥出最大的价值。</p> </blockquote> <h2>家庭</h2> <blockquote> <p>婚姻是一种合作关系,所以两个人都不应该试图驾驭对方。</p> </blockquote> <p>自卑情结</p> <h2>反思</h2> 个人成长https://www.scarsu.com/meaning_of_life/#post-comment/CSS变量https://www.scarsu.com/css_variable/https://www.scarsu.com/css_variable/原生js控制css变量、Vue3响应式css变量Fri, 25 Sep 2020 00:00:00 GMT<h2>资源</h2> <ul> <li><a>文档</a></li> <li><a>在线demo</a></li> <li><a>vue3 css变量文档</a></li> </ul> <h3>是什么</h3> <p>CSS自定义属性、CSS变量、级联变量,可以文档中重复使用的样式变量</p> <h2>声明</h2> <ul> <li> <p>声明一个自定义属性,属性名需要以两个减号(--)开始</p> </li> <li> <p>大小写敏感</p> </li> <li> <p>属性值则可以是任何有效的CSS值。</p> </li> <li> <p>和其他属性一样,自定义属性也是写在<strong>规则集</strong>之内的</p> </li> <li> <p>例子🌰:</p> <pre><code>element { --main-bg-color: brown; } </code></pre> </li> <li> <p><strong>规则集</strong>所指定的选择器 定义了自定义属性的可见<strong>作用域</strong></p> </li> <li> <p>自定义属性具有<strong>继承性</strong>,受级联的约束,从其父级继承其值。</p> </li> <li> <p><strong>最佳实践</strong>💁‍♀️:根伪类<code>:root</code>,相当于全局变量</p> <pre><code>:root { --main-bg-color: brown; } </code></pre> </li> </ul> <h2>使用变量</h2> <p><code>color: var(--main-color);</code></p> <h2>备用值 / 默认值</h2> <pre><code>// 正确做法 var(--my-var, red) var(--my-var, var(--my-background, pink)) // 错误做法 var(--my-var, --my-background, pink) </code></pre> <h2>js更新变量</h2> <pre><code>// 获取一个 Dom 节点上的 CSS 变量 element.style.getPropertyValue("--my-var"); // 获取任意 Dom 节点上的 CSS 变量 getComputedStyle(element).getPropertyValue("--my-var"); // 修改一个 Dom 节点上的 CSS 变量 element.style.setProperty("--my-var", newValue); </code></pre> <h2>Vue3 响应式css变量</h2> <pre><code>&lt;template&gt; &lt;div class="text"&gt;hello&lt;/div&gt; &lt;/template&gt; &lt;script&gt; export default { data() { return { color: 'red' } } } &lt;/script&gt; &lt;style vars="{ color }"&gt; .text { color: var(--color); } &lt;/style&gt; </code></pre> 前端https://www.scarsu.com/css_variable/#post-comment/【学会如何学习】成为更好的终身学习者https://www.scarsu.com/learning_how_to_learn/https://www.scarsu.com/learning_how_to_learn/通过精神学、心理学原理,探寻学习的本质,提高学习效率,降低学习挫败感,成为更好的终身学习者Tue, 15 Sep 2020 00:00:00 GMT<ul> <li>6000字长文预警,建议拉到底部,先看总结❤</li> <li>原创不易,欢迎<strong>点赞,在看,转发</strong>支持</li> </ul> <p><img src="/images/picgo/picgo20200921190445.png" alt="文章大纲" /></p> <hr /> <p>酥鱼我从小学到大学毕业,当了十六年的学生,工作又选择了程序员这个发展日新月异、需要持续学习的行业。</p> <p>如何提升学习效率,减少学习带来的挫折感和痛苦,一直是我所苦苦追寻而不得的。</p> <p>每每看到别人能用更短的时间,学到更多、更深刻、更系统的知识,我都留下了羡慕的泪水。</p> <p>因此我也曾向很多学霸、前辈们请教学习的法门,多多少少能有些学习方法上的收获,但这些方法都因人而异,起不到决定性的作用,始终觉得自己对于<strong>如何学习</strong>这个问题,理不出一个最完美的、有逻辑性的答案。</p> <p>直到我接触到了Coursera上的一门免费课程<a>Learning how to Learn</a>,这门课从神经学、生物学的角度,揭示了大脑认知的底层原理,和学习的本质,从而提供了一系列提升学习效率、减轻学习痛苦与挫败感的技巧。</p> <p>这门课视频内容大概10小时,值得花时间去上,但是如果你想节省时间,可以直接看看本文。</p> <p>如果你刚好学过这门课,可以跟着本文一起<strong>复盘</strong>一遍(学过的你一定知道复盘的重要性。</p> <p>另外有一本书<a>《学习之道》</a>,是这门课的书面材料,书的作者也是课程主讲老师,内容和视频是相对应的,因此也可以直接啃书。</p> <p>废话讲了一堆,下面跟着我一起开始正文吧~</p> <p><img src="/images/picgo/picgo20200915181959.gif" alt="" /></p> <hr /> <h2>人脑的两种思维模式</h2> <p>提到学习,离不开大脑的思维,有了思维才能去理解、才能拥有记忆。</p> <p>人的大脑一共有两种思维模式:</p> <table> <thead> <tr> <th>Focused Mode &lt;br /&gt;专注模式</th> <th>Diffuse Mode&lt;br /&gt; 发散模式</th> </tr> </thead> <tbody> <tr> <td>集中精力解决单一问题</td> <td>放松的思考模式</td> </tr> <tr> <td>熟练掌握的内容</td> <td>新事物学习,获取灵感</td> </tr> <tr> <td>顺序思考</td> <td>整体思考</td> </tr> <tr> <td>熟练掌握的内容</td> <td>新事物学习,获取灵感</td> </tr> </tbody> </table> <p>以弹珠游戏类比大脑的思维:</p> <ul> <li><strong>专注模式</strong>下,大脑遇到已知问题,能快速定位到已掌握的知识,利用训练好的知识回路,专一且迅速的解决问题(弹珠定向发射),此时思维的粒度很细(弹珠盘上的桩很密集),当遇到新问题时,由于过于关注细节,大脑无法进行更广的思维跳跃,无法将更多的知识回路连接(由于桩很密集,弹珠弹射区域很小)。</li> </ul> <p><img src="/images/picgo/picgo20200915094332.png" alt="专注模式" /></p> <ul> <li><strong>发散模式</strong>下,大脑处于放松状态,不考虑细节(弹珠盘上的桩很少),思维灵活跳跃,能从整体层面解决问题,更有助于发挥创造力(弹珠随意发射,在较大的区域弹射)。</li> </ul> <p><img src="/images/picgo/picgo20200915094340.png" alt="发散模式" /></p> <p>这两种思维区别很大,而且不能同时应用,所以我们需要将两种思维模式<code>结合使用,灵活转换</code>。</p> <p>举个例子🌰:</p> <p>Salvador Dali,20世纪著名超现实主义画家。他有一个有趣的方法,来帮他创造富有创造性的作品:<em>坐在椅子上,放松大脑,模糊的思考着之前专注的事情,手上拿着一串钥匙晃悠,当他睡着时,钥匙会掉落在地上,把他吵醒,这样他就能把脑子里刚刚<strong>发散模式</strong>下的联想和点子集中起来,带着它们回到<strong>专注模式</strong>去记录灵感并进行创作。</em></p> <p><strong>专注模式更适合解决细节问题,发散模式更适合寻找灵感和整体解决方案</strong>。</p> <h2>如何拥有更牢固的记忆</h2> <p>学习,其实就是掌握知识的过程,这个过程主要就是两步,<strong>理解 + 记忆</strong>。</p> <p>理解,可以通过很多方式,比如听老师讲课,看书,看视频,看资料,请教前辈等等,方式很多,这一步一般不需要很多时间。</p> <p>先来谈谈记忆,这门课把人类记忆划分为两种:</p> <table> <thead> <tr> <th>Working Memory&lt;br /&gt; 工作记忆</th> <th>Long-term Memory &lt;br /&gt;长期记忆</th> </tr> </thead> <tbody> <tr> <td>短期记忆</td> <td>长期记忆</td> </tr> <tr> <td>负责处理即时的有意识的想法&lt;br /&gt;例如专注学习新知识时&lt;br /&gt;如果不加以复习和记忆,会被其他信息挤掉</td> <td>负责存储已掌握的知识&lt;br /&gt;需要时常复习,才能提升未来能记忆到的几率</td> </tr> <tr> <td>类似于计算机内存,或者一块小黑板</td> <td>类似于硬盘,或者一个存储仓库</td> </tr> <tr> <td>例如你尝试在脑海中用多个概念串联起来,&lt;br /&gt;去解决一个当下遇到的问题</td> <td>例如你回忆99乘法表去计算9×9的结果</td> </tr> <tr> <td>存储于大脑的前额皮质,与大脑的其他部位可以联系</td> <td>占据大脑大片区域</td> </tr> <tr> <td>容量较小,因人而异,大约可以存储四个组块的信息</td> <td>容量巨大</td> </tr> <tr> <td>处于大脑的前额叶皮质区域,与大脑的其他区域可以连接</td> <td>不同类别的长期记忆,处于大脑的不同位置</td> </tr> <tr> <td><img src="/images/picgo/picgo20200915190943.png" alt="image-20200915190943225" /></td> <td><img src="/images/picgo/picgo20200915191016.png" alt="image-20200915191016075" /></td> </tr> </tbody> </table> <p><strong>学习的最终目标,就是将已经理解的知识从工作记忆,转化到长期记忆</strong>。而这个过程,需要的是<strong>练习</strong>。</p> <p>那么怎样<code>在相同练习次数下,获取更牢固的记忆</code>呢?</p> <ul> <li><strong>间隔重复</strong>:刻意的进行反复练习,每次练习中间要有间隔,不断增大两次练习之间的时间间隔。(同样次数的练习,分散在几天中做的效果 比集中在一个晚上做更好)</li> <li>利用比喻、类比、想象,将知识 和 人类<strong>感官联系</strong>,如视觉、听觉、触觉、情感,更有利于记忆。例如:把想要记住的东西,转换成一些难忘的画面、大声朗读单词文章等等</li> <li><strong>充足睡眠+睡前复盘</strong>:睡眠对于学习至关重要,入睡时脑细胞会缩小 使得专注学习时产生的代谢毒物可以被清除,且大脑会在睡眠期间自动清理不重要的记忆,并在潜意识中排演睡前学习的内容。因此睡前花几分钟回顾学习内容,有助于记忆。</li> <li><strong>冷静</strong>。在你感到紧张/生气/害怕时,这些情绪会占用你的工作记忆。因此开始专注前,要排除各种情绪的干扰。</li> </ul> <h2>学习的本质:Chunk 组块</h2> <p><strong>Chunk 组块</strong>:是指大脑可以轻松使用的小而紧凑的<strong>信息碎片</strong>(可以理解成多个神经元组成的回路或思维回路</p> <p><strong>Chunking 组块化</strong>:根据意义和逻辑将信息碎片拼接起来,得到Chunk的思维过程</p> <p>概念有点抽象,举一个<code>拼图</code>的例子🌰:</p> <p>一堆拼图碎片是凌乱无意义的,每块拼图碎片的棱角和图像就是它和其他碎片相互连接的信息和逻辑,理清了所有碎片的逻辑关联,拼成整体后,才能得到一个具有清晰逻辑的整体图片</p> <p><img src="/images/picgo/picgo20200916130211.png" alt="image-20200916130210985" /></p> <p>再以小星星⭐举例:</p> <p>S,T,A,R四个字母单独看,都是单纯的无意义字母,组合成<code>Star</code>后,就是一个有意义的词,你就能联想到五角星的图片形象,也能联想到星空,这就是一个<strong>chunk</strong>的例子,这个<strong>chunk</strong>虽然是一个抽象的概念,但是在你的大脑中,真实存在着相互连接的神经元,其中包含了对四个字母、五角星和星空形象的记忆。</p> <p>最后一个栗子🌰:</p> <p>我们人类出生后最初的学习,就是认识妈妈,一个母亲不断的在孩子面前说“妈妈”这个词,孩子就能学会叫妈妈,并且能把“妈妈”这个词的发音,和母亲的笑容、母亲的形象联系起来,从而不会把别人错认成妈妈。这个学习过程会形成下图👇这样的神经回路,也就是<strong>Chunk</strong>。</p> <p><img src="/images/picgo/picgo20200916131723.png" alt="" /></p> <p>为什么要用这么多内容介绍<strong>Chunk</strong>呢?</p> <p>因为,<strong>专注学习、重复训练的过程,就是建立chunk的过程</strong>,当chunk建立后,神经回路里的任何一点,都能引导你串联整个记忆回路。</p> <p>人类复杂的神经活动、记忆的存储、牛顿从“苹果落地”到“万有引力”,都建立了并依赖于大脑中众多的<strong>Chunks</strong>。</p> <p><strong>Chunk</strong>就像是人脑中<strong>最小可利用的思维回路</strong>,解决复杂问题、掌握复杂知识时,需要利用到众多的相互关联的Chunk,最终形成了你整个大脑的思维网络。</p> <p><img src="/images/picgo/picgo20200918164835.png" alt="" /></p> <p>再回到之前讲的学习的本质,就是<strong>理解+记忆</strong>,记忆这一步的技巧前面已经讲了,理解这一步要做的,就是把现有的外界的知识,转化成自己的知识,在大脑中形成Chunk,为你所用。</p> <p>那么<code>怎样建立牢固可靠的Chunk</code>呢?</p> <p><strong>1. 开启专注模式</strong></p> <p>集中注意力,切断一切外界干扰,不能让有限的工作记忆被其他事情占用。</p> <p>例如呆在一个安静的环境,打开手机电脑的勿扰模式,将手边无关的东西都拿开,打开番茄钟计时,然后开始专注。</p> <p><strong>2. 自下而上学习 - chunking</strong></p> <p>先从<strong>基本概念</strong>开始理解,在理解的前提下,将新知识与已掌握的知识相关联,建立chunk。</p> <p>理解后不断的用<strong>自测</strong>的方式,检验chunk是否真正形成。自测的形式很多,可以合上书回忆所有内容,也可以practice(实践),脱离书本,自己利用Chunk去实际独立操作、独立解决问题,通过这个过程知道<strong>怎么使用chunk</strong></p> <p><img src="/images/picgo/picgo20200916162710.png" alt="image-20200916162217085" /></p> <p><strong>3. 自上而下学习 - context</strong></p> <p>gaining context,获取背景知识,从更广的更高的角度去理解chunk如何融入整体的知识架构,通过这一点去了解<strong>何时何处使用chunk</strong>,掌握了how to之后,思考why to ,when to,从而在遇到问题的各种场景中信手拈来。</p> <p>例如🌰看一本书之前,先看看图片、章节大纲,看完一本书后,画流程图、思维导图,就能更清楚整体的结构,有利于chunk的建立和巩固。</p> <p><img src="/images/picgo/picgo20200916162704.png" alt="" /></p> <h2>最高效的学习方法:间隔重复</h2> <p>Science杂志曾发布一篇论文,让一群学生,使用不同的方法,在相同时间内,学习一篇科技文本,最终的结论是这样的:相较于 重复阅读、边学边画思维导图等方式,通过<strong>recall</strong>方式学习的学生,学的最多、也最牢固。</p> <p>这里的<strong>recall</strong>,我把它总结成<code>间隔重复练习法</code>,也就是不断重复下面的3个步骤:</p> <ul> <li>学习</li> <li>脱离书本回忆(<strong>自测</strong>)</li> <li>留出时间间隔(随着练习的次数增多,逐渐增大时间间隔)</li> </ul> <p>看完这篇文章,你可以忘记所有内容,但是一定要记得这个 <em>经过实验验证有效的</em> 学习方法。</p> <h2>一些学习的误区</h2> <ul> <li> <p><code>看书喜欢画线、画高光</code>:很容易给自己造成”画了就是会了“的错觉,不是不可以画重点,但是记得要通过<strong>自测</strong>的方式检验一下自己是否真的掌握。</p> </li> <li> <p><code>能看懂,就是会了</code>:能看得懂不代表能独立解决,不要觉得你理解的知识,就是你的知识。一定要自己亲自<strong>去实践,去自测</strong>。要建立自己的思维模式,而不是被动的接受知识。</p> </li> <li> <p><code>过度学习</code>:在掌握一个知识后继续反复学习和训练的行为,在需要练出肌肉记忆、自动反应的情况下是必要的(比如体育竞技、演讲),在其他状况下,过度学习是<strong>对时间和精力的浪费</strong></p> </li> <li> <p><code>思维定势</code>:固定的思维形式、牢固的记忆和chunk可能会阻碍你发现更好的灵感,因此在学习新事物时,要<strong>把过去的思维模式先放下</strong>。(有几个关于死亡的句子对这个观点具有启发性:1. There's the old saying that science progresses one funeral at a time,国外有句老话说,科学会随着每个葬礼的进行而进步; 2.乔布斯在斯坦福大学的演讲中曾说,死亡是我们生命中最酷的发明,死亡是生命轮换的代理人,它淘汰旧的以给新生事物发展空间。 3. 死亡意味着根深蒂固的旧思想的流逝)</p> </li> </ul> <h2>一些学习的技巧</h2> <ul> <li><code>记笔记</code>:看书时,减少划线和画高光以避免错觉,可以在知识点旁边写下你<strong>自己的理解</strong>,这样更利于加深印象,巩固记忆(酥鱼我仍然记得,我高中的时候做练习册,都喜欢把练习册写的黑压压的,即使是我掌握了的知识,也会在旁边写上清晰的解题思路。这种习惯一直延续到现在,我看过的书随便翻一翻就能看到笔记。我相信比起看完了还是一片雪白的书,这种方式更容易加深记忆</li> <li><code>换个环境</code>:间隔重复练习的时候,<strong>切换不同的环境</strong>,可以帮助我们脱离记忆对固定场景的依赖,避免单环境下的知识误区,更全面的理解所学知识的各个方面</li> <li><code>transfer知识迁移</code>:联系<strong>不同领域</strong>的相似chunk,也有助于加深记忆</li> <li><code>interleaving交替学习</code>:在已经掌握了基础知识后,可以<strong>交叉</strong>着不同类别的问题、方法、知识一起学习,有利于让大脑更具有灵活性和创造性,也更利于记忆。(用过百词斩的应该知道,他们的逻辑就是背一轮单词,再来一轮,不同的单词交替着出现,比一个单词一直背的效果好很多)另外可以了解一下<strong>Anki软件</strong>,利用交替学习等原理实现了帮助记忆的算法,形式类似于百词斩,只是把单词换成了你想记忆的知识点。</li> <li><code>奖励性学习</code>:在学习或者完成适量的目标后<strong>激励自己</strong>,可以让负责人体动力的多巴胺发挥生理作用</li> <li><code>刻意训练</code>:<strong>专注于学习困难的部分</strong>,是容易和别人拉开差距、超越平均水平的好方法</li> <li><code>关注过程,而不是结果</code>:对于一些困难的任务,需要很多时间和付出才能得到结果,如果只关注结果,会让人产生痛苦,导致拖延。只关注过程恰恰其实是大脑最喜欢的,在deadline之前的时间内,平静地尽最大的努力,关注每个番茄钟的30分钟周期,是否专注成功。</li> <li><code>在睡前坚持写周计划和日计划</code>:研究显示入睡时潜意识会进入类似于 Diffuse Mode 的状态来“消化”和“排练”要完成的项目,从而使你在白天能更好地去完成他们。写计划的另一个好处在于,如果你不这么做,这些待办事项就会停留在你的 Working Memory 中,占据宝贵的精神空间。通过将它们转移到纸上,你能够更好地专注于做事情本身。</li> <li><code>确定好停止学习的时间</code>:计划并严格遵守于 停止学习、专注、工作的时间是很重要的。这么做有助于形成日程规律,形成惯性,还给你更多时间去休息、发展身心健康</li> <li><code>把最困难最厌恶的事情放在早上第一件事做</code></li> <li><code>运动</code>有助于神经元的活跃,有助于学习和记忆</li> <li><code>创建生动的视觉比喻和类推</code>,将知识形象化,能够帮助你更好地理解内容本身,将新事物与旧的神经回路联系了起来,使得大脑能思考得更快、更发散,也能帮助你突破定势 比如 18 世纪的化学家开始想象和可视化分子级别的运动时,他们取得了巨大的突破。</li> <li><code>与其他人一起合作</code>,在专注模式下,大脑倾向于坚持已经建立的推理步骤。与其他人一起合作可以填补你思维上的空缺,建立起更强的自我纠正能力。从这个意义上讲,与你一同合作的人们就好像是对你而言的外部发散思维。对身边的人解释所学的内容也有助于自身的学习。</li> <li><code>考试策略</code>:前文中多次提到<strong>自测</strong>,测试本身是一种非常有用的学习体验,</li> </ul> <h2>如何准备一场考试</h2> <p>这里介绍 Richard Felder 博士 提出的<strong>备考清单</strong>。</p> <ul> <li>是否认真地理解了内容?</li> <li>是否与同学讨论过课后问题?</li> <li>是否尝试列出课后问题的解题大纲?</li> <li>是否积极参加小组讨论?</li> <li>咨询过老师吗?</li> <li>是否弄清楚了所有课后问题的答案?</li> <li>对于不清楚的问题,是否在课堂上提出疑问?</li> <li>是否尝试快速列出一些问题的解题大纲?</li> <li>是否认真通读了辅导书</li> <li>是否参与考前复习?</li> <li>测试前有一个合理的睡眠时间吗?</li> </ul> <p>对于上述问题,在理想的备考状态下,肯定的回答越多越好。</p> <p><code>一些考试时的策略</code>:</p> <ul> <li> <p><strong>先难后易</strong>:如果我们先大概看一眼题目,从困难的问题出发,将它们“加载”到大脑中,然后跳回去做简单的问题,从而使大脑进入 Diffuse Mode 发散模式,这样就很有可能在较短的时间内找到难题的思路(当然,应该控制在你能力范围内,如果短时间内找不到思路,应该直接跳过)</p> </li> <li> <p><strong>保持兴奋</strong>:当你处于紧张状态时,大脑会分泌化学物质引发一系列生理反应。但你可以用不同的方式来解读这些反应。恐惧和兴奋其实是两种很相似的反应。当你坐在考场里,心跳加速,满头是汗,如果你<strong>不去想“这场考试让我恐惧”而是“这场考试让我兴奋”</strong>,这会对你的考试非常有 帮助。</p> </li> <li> <p><strong>深呼吸</strong>:考试时感到心慌是自然反应。你可以通过深呼吸来部分或者全部抵消这一反应。当然,不要等到考试的时候才去做。考前两周、考试开始前的最后时间里做深呼吸,有助于平复心情。</p> </li> <li> <p><strong>不要被大脑欺骗</strong>:我们的大脑经常会欺骗自己,是自己认为自己的解答是正确的。在考试过程中要时刻小心,可以多眨眨眼或是晃晃头,用这种方式来提醒自己稍微往 Diffuse Mode 发散模式 倾斜一点看看有没有出错,然后再用 Focused Mode 专注模式 进行确认。</p> </li> </ul> <h2>拖延症 &amp; 习惯</h2> <p><strong>拖延症的原理</strong>:</p> <p>拖延症是个普遍的现象,在所有人身上多多少少都有体现,这是因为,<strong>拖延是大脑做出的自然反应</strong>。</p> <p>当你遇到不想做的事情时,会感受到不快,这种刺激(Cue)激活了大脑中与疼痛相关的区域,大脑就会迅速作出反应去寻找停止这种负面刺激的方式,即转移注意力到另一件令你愉快的事情上,从而让你在短期内感到舒服一些。</p> <p><strong>拖延症的影响:</strong></p> <p>拖延的负面影响不限于当前被拖延的事情。例如你觉得某一门课或者某一类知识很难,拖延症使你不断地拖迟学习它,当这种拖延行为成为习惯后,即使是想到学习这件事,都会令你痛苦。</p> <p>因此拖延的负面影响是有累积效应的,越拖延,不适的感觉越强。</p> <p><code>对抗拖延症的几个技巧</code>:</p> <ul> <li>有研究人员发现,当人们真正去做不喜欢的事情后,这种精神上的抵触和不适很快就会消失。了解这个原理,在遇到不想做的事情时,暗示自己<strong>先开头去做,很快就能克服</strong>,就可以减轻负面刺激带来的不快感</li> <li><strong>番茄工作法</strong>:利用计时器或者番茄钟,<strong>计时25分钟</strong>,这25分钟内排除一切干扰集中精力专注,专注结束后,<strong>计时5分钟</strong>,给自己一些奖励:放松一下/起来溜达一圈/上网冲冲浪/吃点零食/聊会天。30分钟一次循环,这样的时间效率会相当高,计时器的作用,就是Cue,提醒你切换专注模式和发散模式。(25分钟的专注,对于大多数人来说应该不难。但是如果你发现自己很难持续专注25分钟,那可以循序渐进,先从10分钟开始训练自己的专注耐力)</li> <li>利用<code>习惯</code></li> </ul> <p>对抗拖延症,是对抗身体的本能,需要消耗精力和意志力,而<strong>习惯就是我们的节能机制</strong>。</p> <p>一旦形成习惯,只需要一点点的Cue(信号),后面的行为就会<strong>像呼吸一样自然</strong>,消耗很少的精力和毅力</p> <p>就像你刚开始学车,倒车入库会让你手足无措、手心流汗、提心吊胆,但是当你成为了老司机,看后视镜、转动方向盘就会一气呵成,流畅自然。</p> <p>那么<code>如何养成好习惯</code>呢:</p> <ol> <li>Cue信号:触发惯性行为的外界刺激。比如待办清单上的第一项,办公桌前的便利贴。Cue 大致可以分为四类:时间、地点、感受、反应,从这四个方面,<strong>为自己的好习惯,找一个显眼的信号</strong>。</li> <li>Routine惯性行为:大脑受到信号刺激后,习惯性做出的反应。<strong>反复多次的练习</strong>,就可以养成。</li> <li>Reward奖励:任何习惯得以延续,都是因为它可以回报我们,它会立即给我们带来愉悦感。拖延极易养成习惯,就是因为拖延能带给我们迅速即时的愉悦感。因此为了克服拖延症,<strong>奖励好习惯</strong>很重要。</li> <li>Belief信念:习惯的力量之所以强大,是因为你在内心深处往往认为它们是无法被改变的。</li> </ol> <h2>总结</h2> <ul> <li>灵活运用<code>两种思维模式</code>:专注模式更适合解决细节问题,发散模式更适合寻找灵感和整体解决方案</li> <li><code>牢固记忆</code>的4个技巧:间隔重复、感官联系、充足睡眠+睡前复盘、保持冷静</li> <li>学习的本质是<code>建立组块</code>Chunks,建立过程有三个步骤:开启专注模式、自下而上学习、自上而下学习</li> <li>最高效的学习方法:<code>间隔重复</code>练习法(可以用Anki应用辅助)</li> <li><code>拖延症</code>没那么可怕,只要开始入手做,痛苦就会减轻;可以利用<code>番茄钟</code>、良好的<code>习惯</code>,来帮助你减轻拖延症提高效率</li> <li>4个学习误区、14个学习技巧、关于考试的几个技巧也值得掌握~</li> </ul> 个人成长https://www.scarsu.com/learning_how_to_learn/#post-comment/Harmony OS | 作为前端技术人,体验刚开源的鸿蒙OShttps://www.scarsu.com/hmos/https://www.scarsu.com/hmos/鸿蒙OS中的轻量级响应式前端框架Sat, 12 Sep 2020 00:00:00 GMT<p><img src="/images/hmos/000.png" alt="" /></p> <p>华为2020开发者大会在9月10号如约而至</p> <p>从2019年大会鸿蒙发布后,很多人的目光都聚焦在了鸿蒙OS的开源计划上,“PPT系统”的声音不绝于耳</p> <p>今天发布会之前,吃瓜的我无意间在gitee上看到了这个横幅👇,我知道,终于它来了</p> <p><img src="/images/hmos/001.png" alt="HDC2020" /></p> <p>截至到我发稿前,开源仓库已经有了2k+ star</p> <p><img src="/images/hmos/002.png" alt="鸿蒙OS即将开源" /></p> <p>并且提供了看起来比较完善的中文文档</p> <p><img src="/images/hmos/003.png" alt="鸿蒙OS开源" /></p> <p>同时发布了一款配套的IDE <strong>「DevEco Studio」</strong>,注册开发者即可下载</p> <p><img src="/images/hmos/004.png" alt="鸿蒙OS - DevEco Studio" /></p> <h2>前端er上手体验</h2> <p>作为一个前端技术人,比较令我兴奋的是,鸿蒙OS有一套基于<strong>前端技术栈</strong>的UI开发框架</p> <p><img src="/images/hmos/005.png" alt="鸿蒙OS - JS框架" /></p> <p>于是我上手体验了一下,下面简单介绍一下步骤。</p> <p>安装IDE之后,创建项目,这里我选择了一个TV设备的项目模板</p> <p><img src="/images/hmos/006.png" alt="鸿蒙OS" /></p> <p>做一些简单的配置</p> <p><img src="/images/hmos/007.png" alt="鸿蒙OS" /></p> <p>然后会自动打包构建出一个demo项目,并且在IDE内提供了远程模拟设备</p> <p><img src="/images/hmos/008.png" alt="鸿蒙OS" /></p> <p>选取合适的模拟设备后,就可以运行项目了,得到的效果是这样的</p> <p><img src="/images/hmos/009.png" alt="鸿蒙OS" /></p> <h2>代码</h2> <p>效果图这样的一个电视页面,用到了 <strong>hml+css+js</strong> 三部分代码</p> <p>hml:</p> <pre><code>&lt;div class="container"&gt; &lt;div class="tv_box"&gt; &lt;div class="title_box"&gt; &lt;text class="title"&gt;{{title}}&lt;/text&gt; &lt;text class="title"&gt;酥鱼TVtest&lt;/text&gt; &lt;button type="circle" icon="{{icon_src}}" class="setting_box" onfocus="iconFocusFunc" onblur="iconBlurFunc" &gt;&lt;/button&gt; &lt;/div&gt; &lt;tabs class="tab_box"&gt; &lt;tab-bar mode="scrollable" class="bar_box"&gt; &lt;block for="[1,2,3,4,5,6,7,8,9]"&gt; &lt;text class="tab_text"&gt;{{$t('strings.tab')}} &lt;/text&gt; &lt;/block&gt; &lt;/tab-bar&gt; &lt;tab-content&gt; &lt;block for="[1,2,3,4,5,6,7,8,9]"&gt; &lt;div class="content_box"&gt; &lt;list class="content_img"&gt; &lt;block for="[1,2,3,4]"&gt; &lt;list-item type="listItem" class="list_img"&gt; &lt;image focusable="true" class="tab_img" src="/common/img-large.png" &gt;&lt;/image&gt; &lt;/list-item&gt; &lt;/block&gt; &lt;/list&gt; ... &lt;/div&gt; &lt;/block&gt; &lt;/tab-content&gt; &lt;/tabs&gt; &lt;/div&gt; &lt;/div&gt; </code></pre> <p>js:</p> <pre><code>import app from "@system.app"; export default { data: { title: "", subtitle: "", icon_src: "/common/plus.png", appName: app.getInfo().appName, }, onInit() { this.title = this.appName; this.subtitle = this.$t("strings.subtitle"); }, iconFocusFunc: function () { this.icon_src = "/common/plus-black.png"; }, iconBlurFunc: function () { this.icon_src = "/common/plus-white.png"; }, }; </code></pre> <p>css:</p> <pre><code>.container { flex-direction: column; justify-content: center; align-items: center; background-color: #000000; } .title_box { flex-direction: row; justify-content: space-between; align-items: center; height: 60px; } .title { font-size: 36px; color: rgba(255, 255, 255, 0.9); margin-left: 48px; } ... </code></pre> <h2>JS架构和源码</h2> <p>鸿蒙的 JS 框架 <strong>ace_lite_jsfwk</strong>,官方介绍是“轻量级 JS 核心开发框架”</p> <p>&lt;!-- <img src="https://gitee.com/openharmony/docs/raw/master/readme/figures/js-framework.png" alt="架构图" /> --&gt;</p> <p><img src="/images/hmos/012.png" alt="鸿蒙OS 前端框架 架构图" /></p> <blockquote> <p>提供了一套跨平台的类web应用开发框架,通过Toolkit将开发者编写的<strong>HML、CSS和JS</strong> 文件编译打包成<strong>JS Bundle</strong>,然后再将JS Bundle<strong>解析运行成C++ native UI的View 组件</strong>进行渲染。通过支持三方开发者使用声明式的API进行应用开发,以数据驱动视图变化,避免了大量的视图操作,大大降低了应用开发难度,提升开发者开发体验。</p> </blockquote> <p>源码的地址在:<a>https://openharmony.gitee.com/openharmony/ace_lite_jsfwk</a></p> <p>其中JS的核心代码,主要在以下几个文件</p> <pre><code>runtime-core\src\core\index.js runtime-core\src\observer\ |----observer.js |----subject.js |----utils.js runtime-core\src\profiler\index.js </code></pre> <p>也提供了一些测试用例:</p> <p><img src="/images/hmos/010.png" alt="鸿蒙OS" /></p> <p>从源码看,实现了一个轻量的响应式MVVM系统,使用了 vue2 同样的属性劫持技术,即 <code>Object.defineProperty</code> API。</p> <h2>总结</h2> <p>整体体验下来,感觉开发过程还是很丝滑的,api和开发模式很有vue的味道,应该存在借鉴。对于vue技术栈的前端er来说应该很好上手</p> <p><img src="/images/hmos/011.png" alt="鸿蒙OS" /></p> <p>自从去年的贸易战到后来的疫情,国际局势日趋复杂,鸿蒙OS的开源,对于国家和国内技术行业都有非凡的意义</p> <p>单从前端行业的角度来看,鸿蒙OS的发布,给前端技术人提供了web之外,扩展向物联网行业的,更广的发挥空间和更多的应用场景</p> <p>值得前端技术人向国内鸿蒙开源社区,提供更多的关注,注入更多的技术力量</p> <h2>资源</h2> <ul> <li><a>鸿蒙OS开源地址</a></li> <li><a>鸿蒙OS IDE下载</a></li> <li><a>鸿蒙OS开发者文档</a></li> <li><a>鸿蒙OS前端js框架文档</a></li> <li><a>鸿蒙OS前端js框架源码</a></li> </ul> 前端https://www.scarsu.com/hmos/#post-comment/Vu3响应式原理https://www.scarsu.com/vue3_reactive/https://www.scarsu.com/vue3_reactive/vue2 & vue3 响应式原理对比,手写mini版vue3响应式代码Fri, 24 Jul 2020 00:00:00 GMT<h2>关于Vue3</h2> <p>话说,Vue3已经进行到rc4版本了,4月份beta发布的时候前端圈红红火火,不知道大家开始学了没</p> <p>整理了一些资源,现在开始学习应该还不算晚[狗头]</p> <ul> <li><a>vue-next仓库</a></li> <li><a>20200723 Vue3 官方发布的beta文档</a></li> <li><a>Vue3 Roadmap &amp; FAQ</a></li> <li><a>Vue3仓库已经合并的780多个PR</a></li> <li><a>尤大在Vue Mastery的Vue3课:Vue 3 Deep Dive with Evan You</a></li> <li><a>202007 尤大在前端会客厅节目关于Vue3的访谈</a></li> <li><a>202005 The process: Making Vue 3</a></li> <li><a>202004 尤大 - 聊聊 Vue.js 3.0 Beta 官方直播</a></li> <li><a>2018 VueConf 杭州 尤大关于Vue3的演讲视频</a></li> </ul> <h2>vue2 响应式原理回顾</h2> <ul> <li>对象响应化:遍历每个key,通过 <code>Object.defineProperty</code> API定义getter,setter</li> </ul> <pre><code>// 伪代码 function observe() { if (typeof obj != "object" || obj == null) { return; } if (Array.isArray(obj)) { Object.setPrototypeOf(obj, arrayProto); } else { const keys = Object.keys(); for (let i = 0; i &lt; keys.length; i++) { const key = keys[i]; defineReactive(obj, key, obj[key]); } } } function defineReactive(target, key, val) { observe(val); Object.defineProperty(obj, key, { get() { // 依赖收集 dep.depend(); return val; }, set(newVal) { if (newVal !== val) { observe(newVal); val = newVal; // 通知更新 dep.notify(); } }, }); } </code></pre> <ul> <li>数组响应化:覆盖数组的原型方法,增加通知变更的逻辑</li> </ul> <pre><code>// 伪代码 const originalProto = Array.prototype; const arrayProto = Object.create(originalProto)[ ("push", "pop", "shift", "unshift", "splice", "reverse", "sort") ].forEach((key) =&gt; { arrayProto[key] = function () { originalProto[key].apply(this.arguments); notifyUpdate(); }; }); </code></pre> <h2>vue2响应式痛点</h2> <ul> <li>递归,消耗大</li> <li>新增/删除属性,需要额外实现单独的API</li> <li>数组,需要额外实现</li> <li>Map Set Class等数据类型,无法响应式</li> <li>修改语法有限制</li> </ul> <h2>vue3响应式方案</h2> <p>使用ES6的 <strong><a><code>Proxy</code></a></strong> 进行数据响应化,解决上述Vue2所有痛点</p> <p>Proxy可以在目标对象上加一层拦截/代理,外界对目标对象的操作,都会经过这层拦截</p> <p>相比 <code>Object.defineProperty</code> ,Proxy支持的对象操作十分全面:get、set、has、deleteProperty、ownKeys、defineProperty......等等</p> <pre><code>// reactive 伪代码 function reactice(obj) { return new Proxy(obj, { get(target, key, receiver) { const ret = Reflect.get(target, key, receiver); return isObject(ret) ? reactice(ret) : ret; }, set(target, key, val, receiver) { const ret = Reflect.set(target, key, val, receiver); return ret; }, deleteProperty(target, key) { const ret = Reflect.deleteProperty(target, key); return ret; }, }); } </code></pre> <h2>响应式原理</h2> <p><img src="/images/vue3/reactive.png" alt="vue3响应式原理图" /></p> <ul> <li>通过 <strong><code>effect</code></strong> 声明依赖响应式数据的函数cb ( 例如视图渲染函数render函数),并执行cb函数,执行过程中,会触发响应式数据 <code>getter</code></li> <li>在响应式数据 <code>getter</code>中进行 <code>track</code>依赖收集:建立 <strong>数据&amp;cb</strong> 的映射关系存储于 <code>targetMap</code></li> <li>当变更响应式数据时,触发 <code>trigger</code> **,**根据 <code>targetMap</code> 找到关联的cb执行</li> <li>映射关系 <code>targetMap</code> 结构:</li> </ul> <pre><code>targetMap: WeakMap{ target:Map{ key: Set[cb1,cb2...] } } </code></pre> <h2>手写vue3响应式</h2> <p>大致结构</p> <pre><code>// mini-vue3.js /* 建立响应式数据 */ function reactice(obj) {} /* 声明响应函数cb(依赖响应式数据) */ function effect(cb) {} /* 依赖收集:建立 数据&amp;cb 映射关系 */ function track(target, key) {} /* 触发更新:根据映射关系,执行cb */ function trigger(target, key) {} </code></pre> <h3>reactive</h3> <pre><code>/* 建立响应式数据 */ function reactive(obj) { // Proxy:http://es6.ruanyifeng.com/#docs/proxy // Proxy相当于在对象外层加拦截 // Proxy递归是惰性的,需要添加递归的逻辑 // Reflect:http://es6.ruanyifeng.com/#docs/reflect // Reflect:用于执行对象默认操作,更规范、更友好,可以理解成操作对象的合集 // Proxy和Object的方法Reflect都有对应 if (!isObject(obj)) return obj; const observed = new Proxy(obj, { get(target, key, receiver) { const ret = Reflect.get(target, key, receiver); console.log("getter " + ret); // 跟踪 收集依赖 track(target, key); return reactive(ret); }, set(target, key, val, receiver) { const ret = Reflect.set(target, key, val, receiver); console.log("setter " + key + ":" + val + "=&gt;" + ret); // 触发更新 trigger(target, key); return ret; }, deleteProperty(target, key) { const ret = Reflect.deleteProperty(target, key); console.log("delete " + key + ":" + ret); // 触发更新 trigger(target, key); return ret; }, }); return observed; } </code></pre> <h3>effect</h3> <pre><code>/* 声明响应函数cb */ const effectStack = []; function effect(cb) { // 对函数进行高阶封装 const rxEffect = function () { // 1.捕获异常 // 2.fn出栈入栈 // 3.执行fn try { effectStack.push(rxEffect); return cb(); } finally { effectStack.pop(); } }; // 最初要执行一次,进行最初的依赖收集 rxEffect(); return rxEffect; } </code></pre> <h3>track</h3> <pre><code>/* 依赖收集:建立 数据&amp;cb 映射关系 */ const targetMap = new WeakMap(); function track(target, key) { // 存入映射关系 const effectFn = effectStack[effectStack.length - 1]; // 拿出栈顶函数 if (effectFn) { let depsMap = targetMap.get(target); if (!depsMap) { depsMap = new Map(); targetMap.set(target, depsMap); } let deps = depsMap.get(key); if (!deps) { deps = new Set(); depsMap.set(key, deps); } deps.add(effectFn); } } </code></pre> <h3>trigger</h3> <pre><code>/* 触发更新:根据映射关系,执行cb */ function trigger(target, key) { const depsMap = targetMap.get(target); if (depsMap) { const deps = depsMap.get(key); if (deps) { deps.forEach((effect) =&gt; effect()); } } } </code></pre> <h3>测试demo</h3> <pre><code>&lt;!-- test.html --&gt; &lt;div id="app"&gt; {{msg}} &lt;/div&gt; &lt;script src="./mini-vue3.js"&gt;&lt;/script&gt; &lt;script&gt; // 定义一个响应式数据 const state = reactive({ msg:'message' }) // 定义一个使用到响应式数据的 dom更新函数 function updateDom(){ document.getElementById('app').innerText = state.msg } // 用effect声明更新函数 effect(updateDom) // 定时变更响应式数据 setInterval(()=&gt;{ state.msg = 'message' + Math.random() },1000) &lt;/script&gt; </code></pre> <p>效果:</p> <p><img src="/images/vue3/demo.png" alt="" /></p> <p>如果想获取上述代码,放在了这个<a>仓库:mini-vue3-reactive</a></p> 前端https://www.scarsu.com/vue3_reactive/#post-comment/非暴力沟通:有些话真的可以好好说https://www.scarsu.com/nonviolent_communication/https://www.scarsu.com/nonviolent_communication/当我们褪去隐蔽的精神暴力,爱将自然流露。Sun, 14 Jun 2020 00:00:00 GMT<p><img src="/images/nvc/nvc-map.png" alt="思维导图" /></p> <h2>前言</h2> <p>当有人批评指责你的时候,你的愤怒和失望会让你作出什么反应?</p> <p>你是否会以同样的方法去报复?</p> <p>还是干脆置之不理,实施冷暴力?</p> <p>有时候,你是否很想与家人、朋友、爱人进行友爱的沟通,和同事进行高效的沟通,却以矛盾、吵架和不愉快收场?</p> <p>当你看见别人的恶行、听见别人的恶语、在网络上遇到扛精喷子的时候,</p> <p>你是不是很想重拳出击,指责、批评、贬低、嘲讽、惩罚他?</p> <p>上面列举的这些沟通问题都可以归类到 <strong>暴力沟通</strong> 的范畴。</p> <p><strong>暴力沟通</strong> 困扰着我们生活的方方面面,对我们造成精神伤害,蒙蔽了我们的爱和情感。</p> <p>如果你也被类似的沟通问题所困扰,那么《非暴力沟通》这本书能启发你,如何通过 <strong>好好说话</strong>,来解决这些问题~</p> <h2>简介</h2> <p>今天分享的《非暴力沟通》这本书,于2018年,由华夏出版社出版,作者是美国的 马歇尔·卢森堡 博士,豆瓣评分: 8.8。</p> <h3>非暴力的表达+聆听</h3> <p>这本书指导我们转变谈话和聆听的方式。</p> <p>让我们不再条件反射式的反应,而是去了解自己的观察、感受和需求,有意识地使用语言。</p> <p>使我们既诚实清晰地表达自己,又尊重与倾听他人。</p> <h3>非暴力沟通的4要素</h3> <p>非暴力沟通模式下,我们需要关注4个要素:观察、感受、需求、请求。</p> <ul> <li>第1是表达我们此刻观察到什么,说出人们所做的事情,清楚表达观察的客观结果,而不是去主观判断或者评价。</li> <li>第2是了解和体会感受,比如受伤害怕喜悦开心气愤等等</li> <li>第3,我们需要去弄清楚,是哪些需求导致了我们这样的感受。</li> </ul> <p>举一个常见的例子来说:一位母亲可能对他处于青春期的儿子说</p> <blockquote> <p>我看到桌子下面有两只脏袜子, 我不太高兴, 因为我比较看重整洁</p> </blockquote> <ul> <li>接着她可以立即提出非暴力沟通的第4个要素,也就是具体的请求。</li> </ul> <p>她会说</p> <blockquote> <p>你是否愿意将袜子拿到房间或者放进洗衣机</p> </blockquote> <p>这一要素,要明确的告知他人,我们期待他采取哪种行动来满足我们的需求。</p> <p>这样这位母亲就清楚的说出了非暴力沟通的4个要素,借助这4个要素,诚实高效地表达了自己。</p> <p>下面我们将这4个要素拆分开来看,逐一分析,如何将这4个要素做好。</p> <h2>01 观察和评论</h2> <p>非暴力沟通的第1个要素是 <strong>描述观察</strong>。</p> <p>它强调的是我们要如实的表达出观察的客观结果,而不是我们的主观评价。</p> <p>举几个主观评价的例子:</p> <blockquote> <p>哥哥昨天无缘无故的对我发脾气 我男朋友是一个没有主见的人 我女朋友是一个很霸道的人</p> </blockquote> <p>其实以上这三个例子,在我们以往的沟通中十分常见。</p> <p>我们常常通过单一的行为去给一个人贴标签,</p> <p>我们通过静态的语言去定性变化不断的现实。</p> <p>印度哲学家<code>克里希那穆提</code>曾经说:</p> <blockquote> <p>不带评论的观察是人类智力的最高形式</p> </blockquote> <p>对于大多数人来说,观察他人及其行为,而不去评判指责,或以其他方式进行分析,是难以做到的。</p> <p>将客观的观察和主观的评价混淆,往往会在沟通中造成误解,让人产生逆反心理。</p> <p>想要更合理的表达出我们的观察,而不是评论,可以通过以下几点去改善。</p> <ul> <li>我们应该去关注有事实依据的具体行为</li> <li>而不是我们的愿望情感推测</li> <li>不应该把形容词和副词当作观察结果</li> <li>应该更少的使用“总是,从不,每次”这种言过其实的夸张词汇</li> </ul> <p>附上一张书中的对比表格:</p> <p><img src="/images/nvc/nvc2.jpg" alt="观察和评价" /></p> <h2>02 体会和表达感受</h2> <p>非暴力沟通的第2个要素是 <strong>表达感受</strong>。</p> <p>当我们的需求得到满足时,我们的感受可能会有:兴奋,喜悦,甜蜜,开心,振奋等等。</p> <p>当我们的需求没有得到满足的时候,我们的感受可能是:害怕,担心,焦虑,忧虑,着急,绝望,失望,不满,尴尬,遗憾等等。</p> <p>附上一张书中的感受词汇表:</p> <p><img src="/images/nvc/nvc3.jpg" alt="感受词汇表" /></p> <p>在往常的人际交往沟通中,我们往往不愿意表达自己的感受。</p> <p>因为社会文化并不鼓励我们表达个人需求。</p> <p>我们从小到大的教育,使我们习惯于考虑:人们期待我怎么做,而不是倾听自己的内心。</p> <p>但是积极的表达自己的感受,可以使别人更好的了解我们的需求,更容易得到积极的回应。</p> <h2>03 挖掘感受背后的需求</h2> <p>非暴力沟通的第3个要素是 <strong>表达需求</strong>。</p> <p>在分析非暴力沟通第2个要素的时候,我们强调,我们的喜悦或者失望的感受,都来源于 <strong>我们的需求是否得到满足</strong>。</p> <p>这一点其实至关重要,我们通常会错误的认为自己的感受是由他人的行为引起的。</p> <p>举一个简单的例子。</p> <p>我有一个闺蜜冬梅,有一次情人节,她男朋友因为加班没有陪她。</p> <p>如果冬梅跟她男朋友说</p> <blockquote> <p>你昨天没陪我,令我很失望</p> </blockquote> <p>那么她就是认为:<strong>她的感受是由别人的行为引起的</strong>。</p> <p>如果他跟她的男朋友说</p> <blockquote> <p>你昨天没陪我,我很失望,因为我需要你的陪伴</p> </blockquote> <p>那么此时冬梅能够清楚地了解到:<strong>自己感到失望,是因为她的需求没有得到满足</strong>。</p> <p>如果我们认为自己的感受是他人的行为引起的,那么我们更倾向于指责别人</p> <p>我们想利用他人的内疚来达到我们的需求,把自己不愉快的感受归咎于对方。</p> <p>如果我们通过批评来提出主张,人们的反应通常都是反驳和申辩。</p> <p>反之,如果我们直接说出需求,对方就更有可能做出积极的回应。</p> <p>但不幸的是大多数人并不习惯于从需求的角度来考虑问题,在不顺心的时候,我们倾向于考虑别人有什么错。</p> <p>在沟通中,如果双方都习惯于指责对方,这样的沟通往往都不会得到好的结果,伤害彼此的情感。</p> <p>因此从我们的感受,去发掘我们的个人需求,而不是下意识指责他人,是十分重要的。</p> <h2>04 发出请求</h2> <p>在我们清楚地表达观察感受和需求之后,对方往往会做出积极的回应。</p> <p>如果对方没有对我们的需求所处反应,那么我们可以提出请求。</p> <p>这也就是非暴力沟通的第4个要素。</p> <p>在提出请求时,我们应该提出更加具体可行的请求。</p> <p>举一个例子来说</p> <blockquote> <p>我希望你尊重我的个人隐私 我希望你进我房间之前敲门</p> </blockquote> <p>这两种表达,后者是非暴力沟通所倡导的,具体的请求。</p> <p>另外,区分请求和命令也很重要:</p> <p>请求没有得到满足时,如果提出请求的人批评和指责对方,那么这就是命令。他想利用对方的内疚来达到目的。</p> <p>如果别人拒绝了你的需求,那么你也可以通过更深的沟通,去了解别人拒绝你请求的意图,和隐藏在背后的需求。</p> <h2>需求驱动</h2> <p>在有些场景下,书中的固定模式应用起来也许不太合适,</p> <p>但是,只要掌握了非暴力沟通的 <strong>核心思想</strong> ,都能达成非暴力沟通。</p> <p>那就是 <strong>以需求为驱动</strong> 。</p> <p>无论是怎样的沟通场景,</p> <p>无论你是表达的一方,还是聆听的一方,</p> <p>不要急于表达和作出反应,先去 <strong>观察</strong> 和 <strong>感受</strong> ,去发觉彼此的需求,</p> <p>当你透过语言,洞察到了别人的需求,你会用全新的眼光,去看待我们的人际关系,让自己和家人、朋友、同事、爱人,都拥有更好的交际体验。</p> <p>当你透过情绪和感受,洞察到了自己的需求,你能够用更高效更友善的方式,去达到自己的需求,令自己更舒适,令你的生活更有乐趣和爱意。</p> <h2>好好说话的力量</h2> <p>通过这本书,我感受到了好好说话的非凡力量</p> <p>非暴力沟通这种充满善意和爱的沟通方式。</p> <p>能使我们脱离情绪的控制,更好的了解自我,与自我建立和谐的关系。</p> <p>使我们拥有更清晰的沟通思路,更高效的掌握沟通信息,达成沟通目的,</p> <p>同时,还拥有更好的沟通体验。</p> <p>让我们能更加舒适、更加专注的去追求人生的方向。</p> <h2>反思</h2> <p>读完这本书,可以发现,非暴力沟通的实践和应用,不是一朝一夕能达成的。</p> <p>我分享的只言片语,也并不能传达全书的信息。</p> <p>因此这本书,值得你反复阅读、思考,并亲身实践。</p> <p>附上书中的一首诗歌:</p> <p><img src="/images/nvc/nvc.jpg" alt="语言是窗户,否则它们是墙" /></p> 个人成长https://www.scarsu.com/nonviolent_communication/#post-comment/富爸爸穷爸爸:为什么你很穷https://www.scarsu.com/rich_dad/https://www.scarsu.com/rich_dad/《富爸爸穷爸爸》被誉为“全球最好的”理财入门书,这本书不会教你如何理财,但是会让你对“金钱”有一个全新的观念和认知。Sun, 14 Jun 2020 00:00:00 GMT<h2>简介</h2> <ul> <li>文章标题只是想侧面说明这本书的主要内容,请勿对号入座~</li> <li>我本人是个工作不到两年、背着房贷、没什么存款的理财门外汉,读完这本书,彻底改变了我对“钱”的认知和观念,因此把书中启发到我的地方分享出来,希望对你有些帮助~</li> <li>《富爸爸穷爸爸》从1997年最初版至今已经23年,在全球范围大受欢迎,被誉为“全球最好的理财入门书”,连续六年在纽约时报畅销书榜都榜上有名,目前已翻译超过51国语言。后续又出了一系列以达成财务自由为中心的 <strong>“富爸爸系列”丛书</strong>,。</li> <li>书名中的 <strong>穷爸爸</strong>,指的是作者的亲生父亲,受过良好的教育:从斯坦福大学和芝加哥大学毕业,博士学位,身居夏威夷州教育部门的要职,一生勤奋工作,收入颇丰,是一个看起来十足“成功”的高级知识分子。但是他终其一生都在个人财务问题的泥潭中挣扎,操劳一生离开人世留下了一堆账单。他总是教育作者:要努力学习,取得好成绩,这样才能有好的工作。</li> <li>书名中的 <strong>富爸爸</strong>,指的是作者好友的父亲,初中学历,没有很高的教育水平,但是是一个成功的商人,充分理解金钱的力量,拥有很高的财商,富爸爸是成为了全夏威夷最富有的人之一,他身后留下的是慈善机构、教堂以及巨额的遗产。作者和朋友很小的时候,就开始接受了富爸爸的财商教育。</li> <li>作者:<strong>Robert T. Kiyosaki,Robert ·清崎</strong>,日裔美国人,在1994年47岁的时候,因为遵循了富爸爸教给他的关于金钱和投资的知识,实现了财务自由,创造了“现金流”游戏,财务自由后因出版《富爸爸》系列书而成名,成为金融教育领域的领头人。</li> <li>书中用很多篇幅,对比富爸爸和穷爸爸,指出性格、思想、行为和结果上的差异,从而引出造成贫富差异的原因。</li> </ul> <h2>带着问题看文章</h2> <ul> <li>上班、工作、打工几十年,真的能积累财富吗?</li> <li>退休依靠养老金的模式可靠吗?</li> <li>买房是稳赚不赔的投资吗?</li> <li>普通家境的人用父母前十几年+自己后几十的劳动剩余价值换来的房子值得吗?</li> <li>财商是什么?、财务自由是什么?</li> <li>富人和穷人的差异有哪些?消费观、财商、勇气、自律...</li> </ul> <hr /> <h2>老鼠赛跑的人生</h2> <p>我成长在一个普通家庭,和周围的大多数普通家庭的同学一样,从小到大都接受着来自父母、亲戚、老师的教育:</p> <p>小学中学阶段,他们让我好好学习考一个好大学</p> <p>大学阶段,他们让我好好学习找一个稳定的好工作。</p> <p>工作之后,我拿着在父母眼中还算体面的工资,开始有了消费的自由,买一些自己喜欢的东西。</p> <p>也许不久的将来,我会遇到心爱的人,开始组建新家庭,在我们多年不断努力的工作下,我们的薪水实现了增长,进入 “<strong>中产阶级</strong>” ,但是我们依然需要依靠双方父母的积蓄买房付首付,我们的消费和纳税也水涨船高,我们买车、计划旅行、养孩子......</p> <p>这时候工作就会变成我人生最重要的事情。</p> <p>我需要努力的为老板工作、通过纳税为国家发展做贡献、通过房贷为银行工作。因为工资是我唯一的收入来源,我需要依靠工资来支付生活成本,维持消费,还花呗信用卡,支付房贷月供。</p> <p>于是,我需要不停不休的朝九晚五(甚至996),上班工作,直到退休。</p> <p>我可能还会把同样的教育施加在我的孩子身上,让这样的人生在下一代身上继续循环重复。</p> <p>也许看到文章的朋友中,有创业者,有事业有成的成功人士,有对理财投资颇有心得的朋友。但是当代乃至我们的上一代人,大多数人都有着类似的人生轨迹。</p> <p>这就是《富爸爸》这本书里写的 <strong>“老鼠赛跑”的游戏</strong> :每一代人都不懂理财规划,只会通过拼命工作和加班,用大量的工作时间来换取金钱,再用这些金钱来养育子女赡养父母,而自己的子女也在重复着父母心这一辈的命运。</p> <blockquote> <p>人们的生活总是被恐惧和贪婪控制,太努力工作,而忘记了思考</p> </blockquote> <p>我们因为 <strong>恐惧</strong> 而工作:害怕付不起房贷、养不起老人孩子;</p> <p>我们因为 <strong>贪婪</strong> 而工作:随着工资增加,消费也增加;</p> <blockquote> <p>穷人为钱工作,富人让钱为他工作</p> </blockquote> <p>我们每天都在为了更稳定的生活、更好的生活水平,努力勤恳的上班、挣工资。</p> <p>但是这样的生活方式根本就不是任何一个富人的生活方式。</p> <p>实现了财务自由的富人,不会为了钱而工作,他们用钱创造更多的钱,为自己的消费买单。</p> <h2>区分资产和负债</h2> <p>想要向富人迈进,创造财富,最重要的第一步,就是要分清楚 <strong>资产和负债</strong>:</p> <ul> <li>资产:带来正向“现金流”的个人拥有的东西 =&gt; 能把钱放进你口袋的东西。</li> <li>负债:产生支出的个人拥有的东西 =&gt; 把钱从你口袋拿走的东西。</li> </ul> <h2>关注自己的现金流</h2> <p>资产和负债强调的,就是 <strong>现金流</strong>。</p> <p>现金流更多用于分析企业是否良好经营,但是对于个人来说,<strong>越早关注现金流,有利于越早实现财务自由</strong>。</p> <p>《富爸爸》中用了 <strong>收益表+资产负债表</strong> 分别描述了穷人、中产阶级、富人的现金流:</p> <ul> <li>穷人的现金流</li> </ul> <p><img src="/images/rich/poor_cf.png" alt="穷人的现金流" /></p> <p>对于大多数穷人来说,他们的收入基本全部来源于工资,工资通过日常开支、教育支出等费用消耗掉。他们的资产和负债项是空的。</p> <ul> <li>中产阶级的现金流</li> </ul> <p><img src="/images/rich/middle_cf.png" alt="中产阶级的现金流" /></p> <p>中产阶级的现金流中多了一部分来自于负债的支出。负债项目包括:房贷、车贷、消费分期等。对于大多数买了刚需住房的人来说,房子只能算是他们的“负债”,因为带来不了正向的现金流,如果失业,他们可能会因为这些资产比穷人产生更多的压力,因为他们的开支中除了每月的生活开销,还有他的房贷、车贷。</p> <ul> <li>富人的现金流</li> </ul> <p><img src="/images/rich/rich_cf.png" alt="富人的现金流" /></p> <p>富人和穷人以及中产阶级最大的区别就是:富人的现金流,更多的来自他们的资产项,也就是所谓的“税后收入”,而不是工资。</p> <p>这也与Robert 对 <strong>财富</strong> 的定义相匹配:</p> <blockquote> <p>财富:一个人没有工作后能生活多久的能力</p> </blockquote> <p>对于实现了财务自由的富人来说,这个时间就是无限长,因为他们拥有足够多的资产,为他们创造足够支出的现金流收入,如果收入减去支出还有盈余,他们的资产就会不断增加。</p> <h2>合理的消费观</h2> <p>想要像富人那样更多的积累资产,拥有正向的现金流,培养合理的消费观,最小化支出+负债很重要。</p> <blockquote> <p>富人购买资产,穷人购买负债</p> </blockquote> <blockquote> <p>重要的不是挣了多少,而是能留下多少;</p> </blockquote> <p>身边经常有人在说,越有钱的人越抠门,还有人总抱怨自己的老板,如何俭省成本,苛待员工。</p> <p>其实不是富人抠门,而是富人深知,最小化支出,才能有更多的钱 用于购买资产,产生更多的正向现金流。</p> <blockquote> <p>富人赚的比你多,花的比你少</p> </blockquote> <p>作者Robert 提倡 <strong>享受要与财富匹配</strong> ,先把收入用于买入资产,用资产项的得利买想要的东西。</p> <p>也就是要<strong>自律消费</strong>。</p> <p>因为消费一定属于支出和负债,不要追求与自身资产不匹配的、不必要的虚荣和表层物质,不要被近几年消费升级的宣传所影响,网红带货、短视频即时营销、直播...资本市场越鼓励消费,说明资本市场从消费获利越大。</p> <h2>税收与公司</h2> <p>除了消费,赋税也是每个上班族不可避免的一部分。</p> <blockquote> <p>中产阶级在承担着沉重的税负,尤其是那些受过良好教育、高收入的中产阶级。</p> </blockquote> <p>这个观点似乎与普遍的认知有所出入,普遍的观点都认为富人应该缴纳更多的税让穷人受益,但事实上是这样的吗?</p> <p>这要从税收的历史讲起。</p> <blockquote> <p>英国和美国在早期是不需要纳税的,只有一些因战争而临时收的税,称为“纳捐”。</p> <p>直到1874年,英国规定纳税是国民义务,1913年,美国将征收所得税,纳入宪法。</p> <p>其后虽然有过冲突和争议,但是英国和美国都花了几乎50年来培养公民缴纳所得税的意识。</p> <p>最初只针对富人收税,但是随着国家发展,政府规模扩大,就需要征收更多的税以维持平衡运营。以致中产阶级也要被征税,且税收范围不断向穷人扩展。</p> </blockquote> <p>表面上来看,税收对富人和中产阶级是公平的。但实际上,有关企业的法律知识,给予了富人远超出穷人和中产阶级的优势。</p> <p>原因在书中也有提及:</p> <blockquote> <p>因为政府需要利用法制,刺激企业主和投资者创造更多的工作机会和住房,这些刺激政策降低了富人的赋税。</p> </blockquote> <p>因此,了解更多法律和财务知识的富人,总有办法从赋税中脱身,用Robert 的原话来说,就是:<strong>只要你拥有一种合法资产,我就可以找出以企业的形式提供的好处和保护</strong>,这也就是赋税最终落到中产阶级身上的原因。</p> <p>这种税收状况和解释,在中国也是基本适用的。</p> <p>因此,公司可以帮助富人避税,公司,并不一定是实体意义上的公司,不一定是有公司名称的办公楼、厂房,可以只是一份没有精神和灵魂的法律文件</p> <p>拥有公司的富人:挣钱~支出~缴税</p> <p>为公司工作的人:挣钱~缴税~支出</p> <p>了解更多的财务、法律知识,利用合理的方式避税,也是穷人和富人的区别。</p> <h2>财商</h2> <p>想要积累资产,除了要最小化支出和负债,用合理的方式避税之外,更重要的是,我们要懂得如何让自己的收入,换来更多的资产,Robert 把这种能力称为 <strong>财商</strong>。</p> <p>财商由四个方面构成:</p> <blockquote> <p>1、会计--财务知识,这是非常重要的技能,你管理的钱越多,越需要精确,否则这大厦就会倒下来!财务知识能帮你读懂财务报表,借助这种能力,你还能分辨业务的优势和劣势。</p> <p>2、投资--钱生钱的科学,投资涉及策略和方案,右脑做的事,或者说是创造。</p> <p>3、了解市场--供给与需求的科学,这要求了解受感情驱动的市场的“技术面”,市场的另一个因素是“基本面”,或者说一项投资的经济意义。一项投资究竟有无意义最终取决于当前的市场状况。</p> <p>4、法律--它可以帮助你有效运营一个进入会计、投资和市场领域的企业并实现爆炸性增长,了解税收优惠政策和公司法律的人能比雇员和小业主更快致富,这就像一个人在走,而另一个人却在飞,若从长远看这种差距会更大。</p> </blockquote> <p>踏实的学习上面的四个知识,提升财商,才能积累更多资产,让自己的每一块钱收入都能夜以继日的替自己工作,产生复利。</p> <h2>勇气</h2> <p>除了合理的消费观和财商,勇气也是影响我们致富的一个重要因素。</p> <blockquote> <p>我们一定是不断的摔倒才学会骑自行车的,我从就没见过一球都不失的高尔夫球手,也从来没见过不曾伤心过的恋人,更没见过从来不亏钱的富人,但是我却遇到过很多从来没有在投资活动中亏掉一毛钱的穷人。</p> </blockquote> <p>Robert 认为,我们应该克服对亏钱和失败的恐惧,为了获得更多的选择和机会而勇于冒险。</p> <p>因为惧怕风险和失败而止步不前,待在舒适圈,就一定会失去成功的机会。</p> <p>我们都听过“不要把鸡蛋放在一个篮子里”的经验,但是如果你的鸡蛋本来就很少,还只追求低风险,那只会让你的财富值止步不前,永远实现不了跃迁。</p> <p><strong>储蓄</strong>,是一种很常见的低风险投资,但是 Robert 认为,储蓄不一定是资产,储蓄不但ROI(投资回报率)低,不一定能跑赢通货膨胀,更重要的是,储蓄会使我们失去投资增值的机会。</p> <p><strong>买房</strong>,对于很多普通人来说,也是牵动人生的一大“投资”,依照短期的国情来看,也是一项稳定不会亏损的投资,但是房子一定是资产吗?虽然 Robert 本人的财务自由,有相当一部分是依靠投资,但是他认为,房子不一定是资产。</p> <p>区分房子是资产还是负债,根据前文说的方法其实很简单,如果你买房是刚需住房,那么你的房子无法给你带来正向现金流,反而会消耗你和家人前十几年(全款买房)的积蓄,或者后几十年(贷款买房)的劳动剩余价值,是“从你口袋拿钱出去”的负债。</p> <h2>持续学习是最大的投资</h2> <p>Robert 一生做了无数的投资抉择,有的给他带来了大量的财富和持续的正向现金流,但是他坚定地认为,持续学习才是他收益最高的一项投资。</p> <p>书中有多处描述,都印证了这一观点:</p> <blockquote> <p>人生是一场无知与觉醒的斗争</p> </blockquote> <blockquote> <p>人最大的财富是所受的教育</p> </blockquote> <blockquote> <p>钱不能解决一切问题,只有知识才能解决问题并创造财富</p> </blockquote> <p>Robert 认为,我们不应该单纯为了赚钱和稳定的生活而工作,应该更多的关注事业而不是职业,关注长远的发展而不是眼下的工资。</p> <p>他在实现财务自由之前,没有遵循“穷爸爸”的建议:长期从事在一个稳定的岗位,而是积极的投身于多种跨行业的工作,对于他来说,不同的工作经验,有助于他掌握更多维的知识,这些知识都对他实现财务自由,起到了关键作用。</p> <blockquote> <p>全世界到处都是才华横溢、极具天赋的人,但是只有天赋是不够的</p> </blockquote> <blockquote> <p>越极度专业化的人才,价值范围越有限</p> </blockquote> <p>不光是持续学习,Robert 更加强调的是横向发展。</p> <p>除非你是所在行业金字塔最顶端的人,否则过度局限的认知,会阻碍你的发展,局限你的人生。</p> <p>之前跟朋友聊天,他说过一句话我十分认同,也和作者的观点十分契合:我们无法赚到超出自己认知的钱,我们所赚的每一分钱都是我们对这个世界认知的变现。</p> <p>做一个“T型”人才,斜杠青年,有自己专业的领域,也要有宽阔的认知面,才能离成功更近。</p> <h2>克服本能</h2> <p>无论是 自律消费,还是 持续学习,都需要我们拥有坚定而强大的内心。</p> <p>前几天看新闻看到了博纳影业副总裁跳楼的消息,有一个<a>知乎回答</a>令我印象十分深刻:</p> <blockquote> <p>很多人向上看,只能看到富贵和纸醉金迷。可是真正一步步向上走,才会发现越往上越暗流汹涌。重回平凡的路被堵死,只能咬牙继续向上。在我们用奋斗的勇气和不服输的精神向上爬的过程中,别忘了打磨自己的心,让心变得无坚不摧。</p> </blockquote> <p>一切成功的前提,都需要我们有足够的自控力,让思想控制情感,让思考先于情感反应,要克服对失败的恐惧,克服懒惰,克服自负。</p> <p>打磨好自己的心,才能在上升时顺风而行,在下落时稳住脚步,不落入万丈深渊。</p> <h2>反思</h2> <ul> <li>其实看完这本书会发现,这不是一本急功近利的财富指南,因为我们不可能因为读一本书,就实现财富自由。</li> <li>但是至少我们知道了,在每一份支出之前,应该有更冷静、自律的判断,不被短暂的享受和营销影响,在每一份收入之后,应该更合理的分配投资和支出。</li> <li>读完这本书,也不仅仅给我带来了对“金钱”的改观,除了致富,想要在其他领域做的更好,持续学习、自律、扩展认知,都是必修课。</li> </ul> 个人成长https://www.scarsu.com/rich_dad/#post-comment/结合谈谈对Vue中nextTick的理解https://www.scarsu.com/nexttick/https://www.scarsu.com/nexttick/tick这个词到底时什么意思😯?Wed, 10 Jun 2020 00:00:00 GMT<h2>带着问题看这篇文章</h2> <ul> <li>tick这个单词有点抽象,应该怎么理解?</li> <li>通过nextTick包装的回调,到底何时执行?</li> <li>nextTick存在的意义是什么?</li> </ul> <h2>event loop 中任务执行顺序</h2> <ol> <li>同步代码执行,直至调用栈清空</li> <li>microtask:调用栈清空后,优先执行<strong>所有</strong>的microtask,如果有新的microtask,**继续执行新microtask,**直至microtask queue清空(<strong>微任务</strong>)</li> <li>task queue:执行task queue第一个任务,后续的task暂不处理(<strong>宏任务</strong>)</li> <li>每当调用栈清空后,重复2-3步骤</li> </ol> <p>(关于 Event Loop的细节,我写过一篇很详细的总结<a>试图解释清楚Javascript Event Loop</a>。)</p> <h2>微任务与宏任务</h2> <p>根据event loop的执行机制,微任务的调度优先级比宏任务高.</p> <p>微任务异步API:Promise.then,MutationObserver</p> <p>宏任务异步API:setTimeout,MessageChannel,postMessage,setImmediate</p> <h2>Vue中nextTick的实现</h2> <p>vue中的 nextTick 实现在 util 模块的单个文件中,代码总共100多行:</p> <pre><code>// src\core\util\next-tick.js import { noop } from 'shared/util' import { handleError } from './error' import { isIE, isIOS, isNative } from './env' const callbacks = [] let pending = false function flushCallbacks () { pending = false const copies = callbacks.slice(0) callbacks.length = 0 for (let i = 0; i &lt; copies.length; i++) { copies[i]() } } let timerFunc // nextTick行为利用了微任务队列,微任务队列可以通过原生Promise.then或MutationObserver访问到。 // MutationObserver具有更广泛的支持,但是在iOS&gt; = 9.3.3中的UIWebView中,在触摸事件处理程序中触发时会发生错误。触发几次后,它将完全停止工作 // 因此,如果原生Promise可用,优先使用Promise: if (typeof Promise !== 'undefined' &amp;&amp; isNative(Promise)) { const p = Promise.resolve() timerFunc = () =&gt; { p.then(flushCallbacks) // 在有问题的UIWebViews中,会出现奇怪的状态:微任务队列中有回调但是不被清空,直到浏览器有其他任务,例如处理计时器 // 因此此处使用一个空计时器,来强制触发微任务队列执行 if (isIOS) setTimeout(noop) } } else if (!isIE &amp;&amp; typeof MutationObserver !== 'undefined' &amp;&amp; ( isNative(MutationObserver) || // PhantomJS and iOS 7.x MutationObserver.toString() === '[object MutationObserverConstructor]' )) { let counter = 1 const observer = new MutationObserver(flushCallbacks) const textNode = document.createTextNode(String(counter)) observer.observe(textNode, { characterData: true }) timerFunc = () =&gt; { counter = (counter + 1) % 2 textNode.data = String(counter) } } else if (typeof setImmediate !== 'undefined' &amp;&amp; isNative(setImmediate)) { // setImmediate,宏任务,但是相比 setTimeout 是个更好的选择 timerFunc = () =&gt; { setImmediate(flushCallbacks) } } else { // setTimeout 0 宏任务 timerFunc = () =&gt; { setTimeout(flushCallbacks, 0) } } export function nextTick (cb?: Function, ctx?: Object) { let _resolve callbacks.push(() =&gt; { if (cb) { try { cb.call(ctx) } catch (e) { handleError(e, ctx, 'nextTick') } } else if (_resolve) { _resolve(ctx) } }) if (!pending) { pending = true timerFunc() } // $flow-disable-line if (!cb &amp;&amp; typeof Promise !== 'undefined') { return new Promise(resolve =&gt; { _resolve = resolve }) } } </code></pre> <p>源码中, <code>Vue.nextTick/vm.$nextTick</code> 的具体逻辑:</p> <ul> <li>定义一个 <code>callbacks</code> 数组,用于存储 nextTick 接口传来的回调函数们</li> <li>定义一个 <code>flushCallbacks</code> 方法,用于遍历执行 callbacks 数组中的所有回调函数</li> <li>调用 <code>timerFunc</code> 方法,将 flushCallbacks 方法作为回调任务,添加到异步队列</li> <li>timerFunc由环境决定,<strong>微任务</strong>优先,宏任务作为折衷方案, <code>Promise.then &gt; MutationObserver &gt; setImmediate &gt; setTimeout 0</code></li> </ul> <p><strong>一句话总结</strong>:将回调作为异步任务,添加到(微/宏)任务队列,在当前调用栈清空后再执行。</p> <h2>对nextTick这个词的理解</h2> <p>对于<strong>tick</strong>我的理解是:<code>每次从调用栈开始有函数帧,直到调用栈被清空为止的过程</code>,这个过程可能是:</p> <ul> <li>页面初始加载时<strong>同步脚本执行</strong>的过程</li> <li>也可能是任何一个<strong>异步任务回调执行</strong>的过程</li> </ul> <p>对于<strong>nextTick(cb)</strong>:回调函数cb不在当前调用栈执行期间立即执行,而是被立即添加在任务队列中,在当前调用栈清空后执行。</p> <p>使用nextTick的目的:必须等待当前调用栈的后续代码执行完,才能执行回调,例如这种情况:回调函数中,需要依赖上一个调用栈操作后的某些状态。</p> <p><strong>举个例子:</strong></p> <p>画一个 echarts 图表,希望根据数据的长度来动态调整图表的宽度</p> <pre><code>.. &lt;template&gt; &lt;div id="chart" :style='{width:chartWidth,height:"200px"}' &lt;/template&gt; ... this.chartWidth = getWidthByData(data) this.nextTick(()=&gt;{ let chart= echarts.init(document.getElementById('chart')) chart.setOption({...}) //echarts渲染 }) </code></pre> <p>宽度属性chartWidth存在vue data中,由于vue data是<code>响应式</code>的,变更data值后,div#chart的宽度并不是立即变更的,中间存在一系列过程:</p> <ul> <li>chartWidth 属性上的 descriptor <code>setter</code> 向其依赖的(vue组件的<code>renderWatcher</code>)发布更新</li> <li>watcher 的更新也是一个<strong>异步</strong>过程(queueWatcher,通过nextTick来调度)</li> </ul> <p>因此在chartWidth变更后,对应的dom宽度不是立即更新的,此时如果立即执行echarts的渲染工作,会导致echarts不能按照最新宽度来渲染。</p> 前端https://www.scarsu.com/nexttick/#post-comment/Javascript & 异步机制https://www.scarsu.com/event_loop/https://www.scarsu.com/event_loop/长文 + 动图 + 实例,试图解释清楚:Javascript Event Loop如何调度异步任务Mon, 08 Jun 2020 00:00:00 GMT<h2>带着问题看这篇文章</h2> <ul> <li>我们写的各种回调什么时候执行?按照什么顺序执行?</li> <li>setTimeout(cb,0)和Promise.resolve().then(cb)谁的回调先执行?</li> <li>Javascript的单线程是如何实现异步并发的?</li> <li>Event Loop到底是如何调度任务的?</li> <li>如何利用RAF优化性能?</li> <li>下面这段代码输出是什么?回答不对的朋友,看完这篇文章也许你的思路就会清晰~</li> </ul> <pre><code>console.log(1); setTimeout(() =&gt; { console.log(2); Promise.resolve().then(() =&gt; { console.log(3); }); }); new Promise((resolve, reject) =&gt; { console.log(4); resolve(5); }).then((data) =&gt; { console.log(data); }); setTimeout(() =&gt; { console.log(6); }); console.log(7); // 结果:1475236 </code></pre> <h2>JS Runtime 的几个概念</h2> <h3>call stack 调用栈</h3> <ul> <li>定义:调用栈是浏览器的JavaScript解释器追踪<strong>函数执行流</strong>的一种机制,函数调用形成了一个由若干帧组成的栈。(栈的特点是后进先出)</li> <li>作用:通过调用栈,我们能够追踪:哪个函数正执行;执行的函数体中又调用了哪个函数;以及每一帧的上下文+作用域</li> <li>机制: <ul> <li>每调用一个函数,就把该函数添加进调用栈并执行</li> <li>如果正在调用的函数还调用了其他函数,把新函数也添加到调用栈中,立即执行</li> <li>执行完毕后,解释器会将函数清除出栈,继续执行当前执行环境下剩余的代码</li> <li>当分配的调用栈被占满时,会引发“<strong>Stack Overflow堆栈溢出</strong>”错误</li> </ul> </li> </ul> <h3>heap 堆</h3> <p><strong>堆</strong>一大块内存区域(通常是非结构化的),对象被分配在堆中</p> <h3>task queue 消息队列</h3> <p>JS运行时包含了一个<strong>消息队列</strong>,每个消息队列关联着一个用于处理这个消息的回调函数。(队列的特点是先进先出)</p> <ol> <li>当调用栈为空时,event loop会消息队列中的下一个消息</li> <li>被处理的消息被移出队列,</li> <li>消息被作为参数调用与之关联的回调函数</li> <li>同时为该函数调用向调用栈添加一个新的栈帧</li> <li>调用栈再次为空时,event loop会重复1-4步骤</li> </ol> <p>通常,task queue中的任务被称为:<strong>macrotask 宏任务</strong>.</p> <p>以下几种异步API的回调属于<strong>宏任务</strong>:</p> <ul> <li>setTimeout</li> <li>MessageChannel</li> <li>postMessage</li> <li>setImmediate</li> </ul> <h3>Single Thread 单线程</h3> <ul> <li>单线程 = 单调用栈 = one thing at a time,不能并发,一次只能做一件事</li> <li>为什么单线程能实现异步和并发?</li> <li>因为单线程指的是js runtime</li> <li>而浏览器和Node提供了API,使我们可以调用其他线程去做并发的异步任务,例如网络请求、DOM、setTimeout</li> </ul> <h3>Non-blocking 非阻塞</h3> <ul> <li>blocking:阻塞,是指浏览器在等待耗时长的代码(eg.网络请求,I/O)期间,不能处理任何其他事情,包括用户响应。</li> <li>解决阻塞的方法:异步任务</li> <li>异步任务怎么实现的?依赖的就是<strong>异步API</strong>和<strong>event loop事件循环</strong></li> <li>JavaScript的事件循环模型与许多其他语言不同的一个非常有趣的特性是,它<strong>永不阻塞</strong>,所以当一个应用正等待一个异步任务时,它仍然可以处理其它事情,比如用户输入。(由于历史原因有一些<strong>例外</strong>,如 <code>alert</code> 或者<code>同步 XHR</code>,但应该尽量避免使用它们,<a>例外的例外也是存在的</a>(但通常是实现导致的错误而非其它原因)。</li> </ul> <h3><strong>不被抢占</strong></h3> <p>每个消息被完整的执行后,其他消息才会被执行。</p> <p>优点:当一个函数执行时,它不会被抢占,只有在它运行完毕后才会去运行其他代码,才能修改这个函数操作的数据。</p> <p>缺点:当一个消息需要太长时间才能处理完,浏览器就无法处理用户交互,eg.滚动和点击,这也是性能较差的网页“卡顿现象”的原因。</p> <p>因此良好的操作方式是:缩短单个消息处理时间,在可能的情况下尽量将一个消息裁剪成多个消息。以保证浏览器 <code>60 frames per second</code> 的流畅渲染,即每个消息处理时间 &lt; 1000ms/60=16ms,</p> <h2>Event Loop 事件循环</h2> <p><strong>event loop是一个执行模型,在不同的地方有不同的实现。浏览器和NodeJS基于不同的技术实现了各自的Event Loop。</strong></p> <ul> <li>浏览器的Event Loop模型是在<a>html5的规范</a>中明确定义的,具体的实现由浏览器厂商来做。</li> <li>NodeJS的Event Loop是基于libuv实现的。可以参考Node的<a>官方文档</a>以及libuv的<a>官方文档</a>。</li> </ul> <h3><strong>浏览器EventLoop运行机制(不考虑microtask)</strong></h3> <ul> <li>所有同步任务都在<strong>主线程</strong>上执行,形成一个<strong>call stack</strong>调用栈</li> <li>可以通过<strong>浏览器API</strong>调用 运行在其他线程的<strong>异步任务</strong></li> <li>主线程之外,存在一个待处理消息的<strong>消息队列task queue</strong>。每一个消息都关联着一个用以处理这个消息的回调函数。</li> <li>当主线程调用栈中的所有同步任务执行完毕,系统就会读取task queue,取最先进的消息作为参数,将其关联的回调函数放入主线程调用栈中执行</li> </ul> <h3><strong>添加消息</strong></h3> <ul> <li>浏览器中,如果一个事件有事件监听器,事件被触发后,一个消息就会被添加到消息队列中。</li> <li>除了事件,浏览器提供的其他API,例如setTimeout、xhr等异步任务,都会在任务结束后向消息队列添加消息</li> </ul> <h3><strong>setTimeout(fn,n)</strong></h3> <ul> <li><code>setTimeout</code> 中的第二个参数n是指 消息被加入消息队列的最小延迟</li> <li>因此,不是保证回调在n毫秒内必须执行,而是保证回调在n毫秒之后被添加到消息队列,具体什么时候执行,取决于消息队列中待处理的消息 和 调用栈中已有的函数。</li> <li><strong>零延迟</strong>:<code>setTimeout 0</code> 的作用:将回调立即放入消息队列,而不是0s内立即执行</li> </ul> <h3>debug 一个 demo</h3> <pre><code>// demo function bar() { debugger; console.log("bar"); foo(); } function foo() { debugger; console.log("foo"); setTimeout(function () { debugger; console.log("setTimeout"); }, 1000); } (function all() { debugger; console.log("anounymous"); bar(); })(); </code></pre> <p><img src="/images/event-loop/Untitled.png" alt="" /></p> <p><img src="/images/event-loop/Untitled%201.png" alt="" /></p> <p><img src="/images/event-loop/Untitled%202.png" alt="" /></p> <p><img src="/images/event-loop/Untitled%203.png" alt="" /></p> <p><strong>原理图</strong></p> <p><img src="/images/event-loop/Untitled%204.png" alt="" /></p> <h3>知识延伸:webWorker &amp; 跨运行时通信</h3> <ul> <li>每个 <strong>WebWorker</strong> 、跨域的 **iframe 、**浏览器不同窗口都有各自的运行时,即都有各自的 call stack 、heap、queue。</li> <li>不同的运行时,可以通过 <a>postMessage</a> 方法来通信。</li> </ul> <p><strong>postMessage:</strong></p> <pre><code>// eg. 当一个窗口可以获得另一个窗口的引用时,例如targetWindow = window.opener otherWindow.postMessage(message, targetOrigin, [transfer]); </code></pre> <p>otherWindow:其他窗口的引用:</p> <ul> <li>iframe的contentWindow</li> <li>执行window.open返回的窗口对象</li> <li>通过window.frames获取到的子frame窗口对象</li> </ul> <p>message:要发送到其他窗口的数据,会被<a>结构化克隆算法</a>序列化</p> <p>targetOrigin:用来指定哪些窗口能接收到消息事件</p> <p>transfer:一串和message 同时传递的 <a><code>Transferable</code></a> 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。</p> <p><strong>结构化克隆算法:</strong></p> <p>用于克隆复杂对象</p> <p>不能克隆:Error、Symbol、Function对象、DOM节点</p> <p>不能克隆:属性的描述符、RegExp对象的 lastIndex字段、原型链上的属性</p> <p><strong>Transferable对象:</strong></p> <p>一个抽象接口,代表可以在不同可执行上下文中传递的对象。(抽象:没有定义任何属性和方法)</p> <p>不同执行上下文:例如主线程和webworker之间。</p> <p>ArrayBuffer 、MessagePort 和 ImageBitmap 实现于此接口。</p> <p><strong>接收消息:</strong></p> <pre><code>window.addEventListener("message", receiveMessage, false); function receiveMessage(event) { // event.data:传递来的对象 // event.origin:消息发送方窗口的origin // event.source:对消息发送窗口的引用 } </code></pre> <h2>UI Rendering Task &amp; 性能优化</h2> <h3>浏览器渲染 - Rendering Task步骤</h3> <ul> <li>requestAnimationFrame API(在chrome,火狐,符合WEB标准)</li> <li>style calculation 计算样式</li> <li>layout 计算布局</li> <li>paint 实际渲染像素数据</li> <li>requestAnimationFrame API(在edge,safari)</li> </ul> <h3><strong>render blocking 渲染阻塞</strong></h3> <p>具体来讲,如果js runtime 的 call stack 一直不能清空,例如event loop将一个耗时的回调放进了call stack,会导致浏览器主线程被占用,无法执行render相关的工作,用户交互的事件也被添加在消息队列等待调用栈清空得不到执行,因此无法响应用户的操作,造成阻塞渲染的“卡顿”现象。</p> <h3>60FPS</h3> <p>在event loop处理消息队列时,我们提倡要缩短单个消息处理时间,在可能的情况下尽量将一个消息裁剪成多个消息,rendering task 可以在消息之间执行,以保证保证UI Rendering调用的频率能达到 <code>60 frames per second</code> (UI Rendering Task执行次数通常是每秒60次,但在大多数遵循W3C建议的浏览器中,回调函数执行次数通常与浏览器屏幕刷新次数相匹配。),即每次event loop处理消息执行回调所占用的时间 小于 16.67 毫秒。</p> <h3>demo1:</h3> <p>看下面这段代码,先 append 一个元素再设置display=none去隐藏这个元素,<strong>不必担心</strong>这个元素会闪现,因为这两行代码会在某一次event loop中执行,只有这两行代码执行完,并且清空了当前调用栈,才有可能执行下一次UI Render task</p> <pre><code>document.body.appendChild(el); el.style.display = "none"; </code></pre> <h3>demo2:</h3> <p>下面这段代码,重复的显示隐藏一个元素,看起来开销很大,但其实在RenderingTask期间,只会取最终结果来渲染,</p> <pre><code>button.addEventListener ('click,()=&gt;{ box style. display='none'; box style. display ='block'; box style. display ='none'; box style. display ='block'; box style. display='none'; box style. display ='block'; box style. display ='none'; box style. display ='block'; box style. display ='none'; }) </code></pre> <h3>requestAnimationFrame</h3> <ul> <li>简称RAF,是一个web api,要求浏览器在下一次重绘之前调用指定的回调函数,通常用于执行动画</li> <li>通过RAF,使浏览器可以在单次回流和重绘中优化处理并发动画,每次UI刷新之前执行RAF,使动画帧率更高</li> <li>当requestAnimationFrame() 运行在后台标签页或者隐藏的<code>&lt;iframe&gt;</code> 里时,requestAnimationFrame() 会被暂停调用以提升性能和电池寿命</li> </ul> <p>demo1:requestAnimationFrame优化动画的一个例子</p> <pre><code>// 使用RAF function callback() { moveBoxForwardOnePixel(); requestAnimationFrame(callback); } callback(); // 使用setTimeout function callback() { moveBoxForwardOnePixel(); setTimeout(callback, 0); } </code></pre> <p>效果:</p> <p><img src="/images/picgo/preview.gif" alt="" /></p> <p>demo2:用RAF控制动画执行顺序,需求是box元素的水平位置变化:1000→500</p> <pre><code>button addEventListener ('click,()=&gt;{ box.style.transform = 'translateX(1000px)' box.style.transition= 'transform 1s ease-in-out' box.style.transform = 'translateX(500px)' }) //由于上述代码会一起执行, //因此渲染时,1000px会被忽略,浏览器会取500作为最终值,在下一帧渲染, //因此上述代码的效果是:元素位移0-&gt;500 //换一种写法 button addEventListener ('click,()=&gt;{ box.style.transform = 'translateX(1000px)' box.style.transition= 'transform 1s ease-in-out' requestAnimationFrame(()=&gt;{ box.style.transform = 'translateX(500px)' }) }) // 上述代码,1000的初始值是有效的, //但是在下一次的rendering task期间,由于RAF先执行,因此500将1000覆盖 //最终渲染的效果还是元素位移:0-&gt;500 //如何令500在下下一次渲染再生效?嵌套调用RAF button addEventListener ('click,()=&gt;{ box.style.transform = 'translateX(1000px)' requestAnimationFrame(()=&gt;{ requestAnimationFrame(()=&gt;{ box.style.transition= 'transform 1s ease-in-out' box.style.transform = 'translateX(500px)' }) }) }) </code></pre> <h2>可视化:event loop和rendering</h2> <h3>理想的状态</h3> <p><img src="/images/event-loop/Untitled%205.png" alt="" /></p> <h3>setTimeout的浪费</h3> <p>间隔调用setTimeout的效果:导致浪费</p> <p><img src="/images/event-loop/Untitled%206.png" alt="" /></p> <p>以前的动画仓库的处理方式:<code>setTimeout(animFrame, 1000/60)</code></p> <p>但是这种处理方式不稳定,可能会不准确,因为</p> <p><img src="/images/event-loop/Untitled%207.png" alt="" /></p> <p><img src="/images/event-loop/Untitled%208.png" alt="" /></p> <h3>RAF的稳定有序状态</h3> <p><img src="/images/event-loop/Untitled%209.png" alt="" /></p> <h2>MicroTask 微任务</h2> <p><strong>微任务,microtask,也叫jobs。</strong></p> <h3>微任务 异步类型</h3> <p>一些异步任务执行完成后,其<strong>回调</strong>会依次进入microtask queue,等待后续被调用,这些异步任务包括:</p> <ul> <li><strong>Promise.then</strong></li> <li>MutationObserver</li> <li>process.nextTick (Node独有)</li> <li>Object.observe</li> </ul> <h2>⭐event loop运行机制(含microtask)</h2> <p>event loop中任务的执行顺序:</p> <ol> <li>同步代码执行,直至调用栈清空</li> <li>microtask:调用栈清空后,优先执行<strong>所有</strong>的microtask,如果有新的microtask,**继续执行新microtask,**直至microtask queue清空</li> <li>task queue:执行task queue第一个任务,后续的task暂不处理</li> <li>每当调用栈清空后,重复2-3步骤</li> </ol> <p><strong>两个重点:</strong></p> <ul> <li>微任务阻塞浏览器:如果执行微任务期间,不停的有新的微任务,会导致浏览器阻塞</li> <li>微任务的执行会因为JS堆栈的情况有所不同,要根据<strong>调用栈是否清空</strong>去判断微任务是否会执行。</li> </ul> <p>一个直观的例子:</p> <pre><code>Promise.resolve().then(() =&gt; { console.log("microtask 1"); }); Promise.resolve().then(() =&gt; { console.log("microtask 2"); }); console.log("sync code"); setTimeout(() =&gt; { console.log("macro task 1"); Promise.resolve().then(() =&gt; { console.log("microtask 3"); }); }, 0); setTimeout(() =&gt; { console.log("macro task 2"); }, 0); //结果: //sync code 同步代码优先执行 //microtask 1 同步代码执行完后,调用栈清空,优先执行 microtask //microtask 2 同上 //macro task 1 调用栈清空,microtask queue清空,此时可以执行一个位于队首的macro task,执行期间新增一个microtask //microtask 3 调用栈清空后,由于存在microtask,因此优先执行microtask //macro task 2 最后执行macro task,清空task queue </code></pre> <p><strong>流程图</strong> <img src="/images/event-loop/Untitled%2010.png" alt="" /></p> <p><strong>demo1:调用栈未清空,不执行microtask</strong></p> <p>在控制台中执行一段代码,会当做同步代码来处理。listener1执行后,微任务队列+1,但是因为是同步执行的代码,所以会立即执行listener2,微任务队列+1,所以顺序是<code>listener1,listener2,microtask1,microtask2</code></p> <p><img src="/images/event-loop/Untitled%2011.png" alt="" /></p> <p><strong>demo2:调用栈清空后,microtask 优先于 macro task执行</strong></p> <p>同步执行两个setTimeout,会将 listener1和listener2加入到task queue,同步代码执行就结束。先执行listener1,将microtask1加入微任务队列,listener1执行完后,调用栈清空,即使这时候task queue还有listener2,也会先执行所有微任务,将所有微任务清空后,再执行listener2,因此输出顺序是 <code>listener1,microtask1,listener2,microtask2</code></p> <p><img src="/images/event-loop/Untitled%2012.png" alt="" /></p> <p><strong>demo3:同demo2</strong></p> <p>用户点击事件</p> <p>由于点击事件会被添加到task queue,因此,这个 demo3 的结果和 demo2 结果相同</p> <p><img src="/images/event-loop/Untitled%2013.png" alt="" /></p> <p><strong>demo4:同demo1</strong></p> <p>js调用click()事件</p> <p>由于是在代码中手动执行click,所以会同步执行两个listener,因此demo4和demo1结构相同。</p> <p><img src="/images/event-loop/Untitled%2014.png" alt="" /></p> <p><strong>demo5:micro 优先于 macro执行</strong></p> <p><img src="/images/event-loop/Untitled%2015.png" alt="" /></p> <p><strong>demo6:综合实例</strong></p> <pre><code>// 浏览器中执行 console.log(1); setTimeout(() =&gt; { console.log(2);// callback2,setTimeout属于宏任务 Promise.resolve().then(() =&gt; { console.log(3)// callback3,Promise.then属于微任务 }); }); new Promise((resolve, reject) =&gt; { console.log(4)// 这里的代码是同步执行的 resolve(5) }).then((data) =&gt; { console.log(data);// callback5,Promise.then属于微任务 }) setTimeout(() =&gt; { console.log(6);// callback6,setTimeout属于宏任务 }) console.log(7); // 结果:1475236 // 逻辑: 147是同步执行,同步代码执行完后的queue: task queue:callback2,callback6 microtask:callback5 此时调用栈已清空,优先执行微任务callback5,调用栈清空 再执行callback2,调用栈清空 此时的queue: task queue:callback6 microtask:callback3 优先执行微任务callback3,调用栈清空 最后执行callback6 </code></pre> <p><img src="/images/event-loop/Untitled%2016.png" alt="" /></p> <p><strong>demo7:综合实例</strong></p> <pre><code>console.log('main start'); setTimeout(() =&gt; { //cb1 console.log('1'); Promise.resolve().then(() =&gt; { //cb2 console.log('2') }); }, 0); Promise.resolve().then(() =&gt; { //cb3 console.log('3'); Promise.resolve().then(() =&gt; { //cb4 console.log('4') }); }); console.log('main end'); //结果: // main start,main end,3412 main start 和 main end同步执行,同步代码执行完后,调用栈清空,此时的queue: task queue:cb1 microtask queue:cb3 先执行微任务cb3,执行完后,调用栈清空,此时的queue: task queue:cb1 microtask queue:cb4 先执行微任务cb4,执行完后,调用栈清空,此时的queue: task queue:cb1 microtask queue:空 最后执行cb1,然后执行cb2 </code></pre> <p><img src="/images/event-loop/Untitled%2017.png" alt="" /></p> <p><strong>rendering task的执行顺序</strong> 在上面的event loop执行机制中,没有提到rendering task,是因为rendering task是由浏览器自行去决定何时运行的,与当前设备的屏幕刷新率等因素相关,确定的是:</p> <ul> <li>RAF 在 rendering task 初始期间执行</li> <li>如果定义了多个 RAF 回调,会被加入到 <code>Animation queue</code>中,在UI Rendering 期间,会清空 Animation queue,与 microtask 不同的是,如果清空 Animation queue 期间,有新的 animation task 被加入到 queue 中,此次 rendering task 执行期间,不会处理新的 animation task。</li> </ul> <p>macrotask、microtask、animation task的区别,可以看在下面的动图中横向对比:</p> <p><img src="/images/event-loop/raf.png" alt="" /></p> <p><img src="/images/picgo/event_loop.gif" alt="" /></p> <h2>参考资料</h2> <ul> <li><a>HTML规范</a></li> <li><a>NodeJS Event Loop 文档</a></li> <li><a>mdn相关文档</a></li> <li><a>Jake Archibald在JSConf.Asia的演讲视频【In The Loop】,很值得看:</a></li> <li><a>Philip Roberts在JSConf的演讲视频【What the heck is the event loop anyway】,很值得看</a></li> <li><a>Philip Roberts做的Event Loop可视化网站</a></li> <li><a>JS Runtime运行时 - MDN</a></li> </ul> 前端https://www.scarsu.com/event_loop/#post-comment/4点起床:舒适而高效的作息方式https://www.scarsu.com/3-8lifestyle/https://www.scarsu.com/3-8lifestyle/这是一本我用两周地铁通勤时间看完的书,虽然这本书没什么系统性,废话也比较多,但是看完这本书,确实对我的生活有所影响,让我养成了早睡早起的习惯,这篇文章总结一下书中的(我认为的)精华。Thu, 21 May 2020 00:00:00 GMT<p><img src="/images/read/3-8lifestyle.jpg" alt="" /></p> <h2><code>REM</code> 睡眠</h2> <p><a><strong>REM : rapid eye movement</strong></a>,快速眼动睡眠,是人睡眠周期的一个阶段。</p> <p><code>REM</code>即<code>快速眼动睡眠</code>睡眠阶段中,身体肌肉放松,单紧闭的眼皮下眼球在来回运动,这个阶段是联系'清醒状态'和'意识体温低下的睡眠状态'的桥梁,为人们“睡醒”做了准备。</p> <p><code>Non-REM</code>、<code>NREM</code>是<code>非快速眼动睡眠</code>,这个阶段是大脑休息的时间,也就是深度睡眠阶段,这个阶段是睡眠中最重要的阶段,也是睡眠效率最高的阶段。</p> <h2>睡眠周期</h2> <p>通常一个成年人的睡眠是这样的:</p> <ul> <li><code>NREM</code>与<code>REM</code>交替出现,交替一次称为一个<code>睡眠周期</code></li> <li>两种循环往复,每夜通常有 <code>4~5个睡眠周期</code>,每个周期90~110分钟。</li> </ul> <p>国际睡眠医学将<code>一个睡眠周期</code>分为五个阶段:</p> <ul> <li>入睡期</li> <li>浅睡期</li> <li>熟睡期</li> <li>深睡期</li> <li>快速眼动期:</li> </ul> <p><img src="/images/read/rem.png" alt="Sleep Cycle" /></p> <p>上图是对一个睡眠周期的近似描述,<code>W</code>是Wake清醒状态,<code>R</code>是<code>REM</code>,<code>N</code>代表<code>NREM</code>非快速眼动睡眠,<code>N3</code>代表最深度的睡眠。</p> <p>由图中可以看出,一个90分钟的睡眠周期中,<code>深度睡眠</code>大约占到了整个睡眠周期的一半以上。</p> <h2>依照睡眠周期来休息</h2> <p>我们在深睡阶段是轻易叫不醒的,如果在深睡阶段被吵醒,身体和大脑从深度睡眠中被突然拉出,通常会使身体和大脑<strong>产生不适</strong>,即使睡眠时间总和很长,也会有没睡好的感觉。</p> <p>相反,如果在浅睡眠阶段,清晨的阳光照射、晨起的鸟叫都能轻易的把我们从快速眼动期唤醒,由于大脑已经经历过处在睡眠周期中间的深度睡眠,得到了休息,这个时候的清醒,身体和大脑都会<strong>感到舒适</strong>。</p> <p>因此,按照睡眠周期的模式来休息至关重要。</p> <p>当然,每个人的睡眠周期不可能都是严格的90分钟,因此也要掌握好自己的身体规律。</p> <p>比如你入睡后一段时候,<strong>开始翻身</strong>或者<strong>容易被吵醒</strong>,这个时候很大概率就是你处在<strong>睡眠周期末尾</strong>的<code>快速眼动阶段</code>。</p> <p>掌握自己身体的睡眠周期,同时让自己处于可以自然醒的环境,例如靠近窗边睡眠,让大自然的声音光线带着身体自然醒,就可以得到最<strong>舒适高效</strong>的睡眠。</p> <p>高效的睡眠也就意味着可以在拥有舒适睡眠的同时,缩短睡眠时间,<strong>可利用的时间</strong>也就增多了,这就是书中作者所提倡的观点。</p> <h2><code>3-8作息</code></h2> <p>前面睡眠周期介绍了如何利用缩短睡眠时间,来提升可利用时间,而<code>3-8作息法</code>要介绍的,是在相同睡眠时间的情况下,如何<strong>提升可利用时间的效率</strong>。</p> <p>答案就是<strong>早起</strong>。</p> <p><code>3-8作息法</code>是指:将一天时间分为3块,上午8小时,下午8小时,晚上8小时。也就是4点起床,下午8点休息。</p> <h2>为什么要早起</h2> <p>其实<code>3-8</code>模式,强调的起早,是让晚上的时间去置换早上的时间。</p> <p>那么为什么要早起呢,书中用大量的篇幅介绍了早起的好处。</p> <p>例如,从生理学的角度来说,人的身体会分泌两种令人“精力充沛”的荷尔蒙,<strong>肾上腺素、肾上腺皮质类脂醇</strong>,这两种荷尔蒙在早上分泌的量比晚上分泌的多,大概是3倍左右,因此早上大脑的<strong>效率</strong>比晚上的高,早上的大脑更加清醒,精力更加旺盛。</p> <p>另一方面,<strong>日出而作,日落而息</strong>是人类进化几千年形成的习惯,只是到了现代,人们在夜里可以做的事情越来越多,加班的情况也越来越多,很多人的睡眠时间越来越晚,甚至有些自由工作制的公司里,很多人都是<code>11-12</code>的作息方式,在正午起床,在月影朦胧时才睡去,这是违背大自然和人体规律的。</p> <p>当你利用睡眠周期规律,养成早睡早起的习惯后,会发现一些<strong>美妙</strong>的事情,比深夜的手机、视频、夜宵、电脑、小说更加精彩,比如:</p> <ul> <li>光线、鸟叫带来的自然醒的舒适</li> <li>清晨你所在城市的样貌,和形形色色早起的人</li> <li>适宜的晨间光照,和空气中适宜的湿度</li> <li>在空空荡荡的地铁上安然看书的舒适</li> <li>...</li> </ul> <h2>早起能做什么</h2> <p>之前发朋友圈晒了一张等首发地铁的图片,有朋友问,“起那么早干什么?”</p> <p><img src="/images/picgo/morning.png" alt="起那么早干什么?" /></p> <p>其实,一切你想做的事情,都可以放在早上完成(除了看星星看月亮这种)。</p> <p>书中举了很多例子,比如</p> <ul> <li>悠闲的享受早餐</li> <li>散步、运动(运动有助于缓解压力)</li> <li>冲热水澡</li> <li>晨间社交</li> <li>看书学习</li> <li>发展副业</li> <li>发展兴趣爱好,做内因驱动的事情</li> <li>...</li> </ul> <h2>找不到自己早起想做的事?</h2> <p>书中还有一个观点令我印象深刻,如果你找不到自己想做的事情呢?</p> <p>就不需要早起,或者陷入迷茫吗?</p> <p>我把作者的答案摘录在这里,希望对找不到追求的人,能有所启发:</p> <blockquote> <p>我究竟想做什么呢?</p> <p>当然,我们可以埋头苦干,让自己没时间胡思乱想。但我建议大家多去受点刺激。 学习、信息、人......这些都是刺激。 接受的刺激越多,自然会产生这样那样的憧憬:“我想成为那样的人!”“我想做那样的工作!” 有些人能找到明确的目标,有些人则会发现目标的模糊轮廓。</p> <p>无论你属于上述哪种情况,都能在不断接受刺激(我把它称为“打击”)的过程中,逐渐将自己的目标具象化,这才是重中之重。</p> </blockquote> <hr /> <p>&lt;small&gt;人的一生也许都在自我探索&lt;/small&gt;</p> 个人成长https://www.scarsu.com/3-8lifestyle/#post-comment/如何学习源码、如何高效学习一个新知识https://www.scarsu.com/how_to_learn_wheels_source_code/https://www.scarsu.com/how_to_learn_wheels_source_code/学习轮子源码是提升自我技术的有效途径,也是高阶程序员的必备技能。这套方法也适用于绝大多数知识体系的学习~Thu, 14 May 2020 00:00:00 GMT<p><img src="/images/learning2.png" alt="" /></p> <h2>什么时候看源码</h2> <p>对于复杂的开源项目,一上来就看源码是不合理的,可能导致效率低下,适得其反。</p> <p>往往看一个开源项目源码前,我们会经历以下几个阶段:</p> <ul> <li>刚接触一个开源项目,跟着官方文档,运行一些demo实例</li> <li>在工作项目中应用、实践、踩坑</li> <li>能够熟练使用,了解它的一些设计思想,但是还不知道设计原理</li> </ul> <p>经历过以上几个阶段后,就是开始看源码的最佳时期</p> <h2>如何看源码</h2> <h3>1. 检索收集信息</h3> <p>如果你不是一个走在行业最前端的人,那么你踩过的坑,一定有前人踩过。你想学的东西,也一定有前辈早已研究透彻。</p> <p>如果一定有人走过我们要走的路,那么我们就应该利用好这个互联网大世界,在踏出征途前,先从无数优秀前辈身上,汲取一些“旅行攻略”。</p> <p>不光是学习源码,对于绝大多数我们即将要做的事情来说,<strong>检索收集信息</strong>都应该是第一步,甚至要放在计划制定之前。</p> <p>学习开源项目源码之前,带着它的名称 + “如何学习” 作为关键词,检索信息,对于我们程序员,甚至可以先搜一搜这个项目相关的面试题。</p> <p>这有助于我们用最短的时间,去了解这个项目最值得我们学习的地方,让我们更加清楚我们想要什么;也有助于我们收集学习资料,提高学习效率。</p> <h3>2. 宏观了解</h3> <p>从全局的视角去了解整个项目,这有助于形成整体的知识结构,上来就从细微处硬啃,效率极低。</p> <p>可以从以下几个方面着手:</p> <ul> <li>项目的背景、项目作者亲述的背后的故事、项目纪录片</li> <li>项目解决的问题</li> <li>浏览代码仓库,了解其Issue报告规则、PR规则、贡献规则、开发环境...</li> <li>源码的目录结构</li> <li>项目的元数据。例如package.json,看看项目的依赖/脚本</li> <li>构建方式,运行环境,入口,构建输出</li> <li>项目的历史版本和当前版本的区别,未来的发展方向</li> <li>项目的技术选型:项目的技术依赖,优化方案,类型控制,格式检查,代码规范,API接口设计,单元测试等</li> </ul> <h3>3. 重点切入</h3> <p>有了你对项目的熟练使用,有了对项目设计思想的了解,有了对项目整体的认知,那么我们就可以开始带着问题细啃源码,去了解这个项目的重点的实现原理。</p> <ul> <li>比如这个项目最重要的核心思想,是如何实现的;</li> <li>比如你在实践中经常踩坑的点,是如何产生的;</li> <li>比如那道最高频的面试题,面试官到底想考我们什么;</li> <li>比如那些你在实践中经常用到的特性,是如何实现的</li> <li>...</li> </ul> <p>带着这些切入点去看源码,逐一击破,最终就可以建立一个完整的知识体系。</p> <h3>4. 模仿实现</h3> <p>当掌握了项目的宏观结构 + 重点特性的实现原理后。就可以开始自己动手,尝试实现一个类似的简单小项目。</p> <p>这个项目不需要完整的重复造轮子,不需要完美的关注细节,只需要把我们所学到的结构应用其中,把关键特性模仿实现即可。</p> <p>这个过程有助于我们查漏补缺,在自己动手踩坑的过程当中,把学到知识融会贯通。</p> <h3>5. 开源贡献</h3> <p>当我们掌握了知识之后,根据<strong>费曼</strong>的<strong>以教为学</strong>的方法,我们最后应该做的就是<code>输出</code>。比如:</p> <ul> <li>输出学习总结</li> <li>反馈项目社区:参与共建,做开源贡献,解决issue,做插件开发</li> </ul> <h2>举一反三</h2> <p><code>这套方法其实适用于绝大多数知识体系的学习</code></p> 前端https://www.scarsu.com/how_to_learn_wheels_source_code/#post-comment/Vue消息插件开发 & npm发布https://www.scarsu.com/vue_message_plugin/https://www.scarsu.com/vue_message_plugin/手写一个基于 Vue.js 的消息插件,按照 ElementUI / message的接口实现Thu, 14 May 2020 00:00:00 GMT<h2>vue-message-plugin</h2> <ul> <li>一个基于 Vue.js 的消息插件,按照 ElementUI / message的接口实现</li> <li><a>插件地址</a></li> <li><a>源码地址</a></li> </ul> <p><img src="/images/picgo/vue-message-plugin.gif" alt="vue-message-plugin预览" /></p> <h2>源码目录结构</h2> <p><img src="/images/vue-message-plugin.png" alt="vue-message-plugin源码目录结构" /></p> <h2>package.json配置</h2> <pre><code>{ "name": "vue-message-plugin", "version": "1.0.0", "description": "A message plugin based on Vue.js which works like ElementUI/Message.", "author": "scarsu &lt;scarsu001@gmail.com&gt;", "private": false,//用于公开发布 "license": "MIT", "main": "dist/vue-message-plugin.js",//npm引用入口 "repository": {//仓库 "type": "git", "url": "https://www.github.com/scarsu/vue-message-plugin" }, "scripts": { "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot", "build": "cross-env NODE_ENV=production webpack --progress --hide-modules" }, "dependencies": { "vue": "^2.5.2" }, "keywords": [ "vue", "toast", "code", "vue plugin", "message", "vue-message-plugin" ], "devDependencies": { "babel-core": "^6.26.0", "babel-loader": "^7.1.2", "babel-preset-env": "^1.6.0", "babel-preset-stage-3": "^6.24.1", "cross-env": "^5.0.5", "css-loader": "^0.28.7", "file-loader": "^1.1.4", "html-webpack-plugin": "^2.30.1", "vue-loader": "^13.0.5", "vue-template-compiler": "^2.4.4", "webpack": "^3.6.0", "webpack-dev-server": "^2.9.1" }, "engines": { "node": "&gt;= 6.0.0", "npm": "&gt;= 3.0.0" }, "browserslist": [ "&gt; 1%", "last 2 versions", "not ie &lt;= 8" ] } </code></pre> <h2>主应用 vue安装插件</h2> <pre><code>import Vue from "vue"; import App from "./App"; import Message from "./lib"; Vue.config.productionTip = false; Vue.use(Message); //Vue.use用于安装插件,插件中必须包含install方法,必须在创建根实例前安装插件 /* eslint-disable no-new */ new Vue({ el: "#app", components: { App }, template: "&lt;App/&gt;", }); </code></pre> <h2>Message/index.js</h2> <pre><code>import Message from "./src/main.js"; export default Message; </code></pre> <h2>Message/src/main.js</h2> <pre><code>/* * 参数 说明 类型 可选值 默认值 * message 消息文字 string / VNode — — * type 主题 string success/warning/info/error info * dangerouslyUseHTMLString 是否将 message 属性作为 HTML 片段处理 boolean — false * customClass 自定义类名 string — — * duration 显示时间, 毫秒。设为 0 则不会自动关闭 number — 3000 * showClose 是否显示关闭按钮 boolean — false * center 文字是否居中 boolean — false * onClose 关闭时的回调函数, 参数为被关闭的 message 实例 function — — * offset Message 距离窗口顶部的偏移量 number — 20 * * 调用 Message 或 this.$msg 会返回当前 Message 的实例。如果需要手动关闭实例,可以调用它的 close 方法。 * * 方法名 说明 * close 关闭当前的 Message */ import message from "./main.vue"; import { isVNode } from "@/utils"; //用于export的对象 const Message = {}; let instances = []; let seed = 0; const types = { success: "success", info: "info", warning: "warning", error: "error", }; //Vue插件必须包含install方法 Message.install = function (Vue) { const Message = Vue.component("message", message); Vue.prototype.$message = function (opt) { // 参数处理 if (typeof opt === "string" || isVNode(opt)) { opt = { message: opt }; } opt.id = "id" + seed++; opt.type = types[opt.type] || types.info; opt.userOnClose = opt.onClose; // message组件实例 let instance = new Message({ data: opt, //将配置选项传入给实例的data }); //处理VNode类型message(使用$slots插槽分发数据 if (isVNode(instance.message)) { instance.$slots.default = [instance.message]; instance.message = ""; } //挂载dom 并 实例的dom加入body中 instance.$mount(); document.body.append(instance.$el); // close方法 instance.close = function () { this.show = false; if (this.userOnClose) this.userOnClose(); }; // 显示 instance.show = true; // 定时隐藏 let duration = opt.duration || 3000; instance.timer = setTimeout(() =&gt; { instance.close(); }, duration); instances.push(instance); // 返回message组件实例 return instance; }; }; export default Message; </code></pre> <h2>isVNode方法</h2> <pre><code>function isVNode(node) { //通过VNode必包含的属性componentOptions来判断 return ( !!node &amp;&amp; typeof node === "object" &amp;&amp; node.hasOwnProperty("componentOptions") ); } </code></pre> <h2>Message/src/main.vue</h2> <pre><code>&lt;!-- * 参数 说明 类型 可选值 默认值 * message 消息文字 string / VNode — — * type 主题 string success/warning/info/error info * dangerouslyUseHTMLString 是否将 message 属性作为 HTML 片段处理 boolean — false * customClass 自定义类名 string — — * duration 显示时间, 毫秒。设为 0 则不会自动关闭 number — 3000 * showClose 是否显示关闭按钮 boolean — false * center 文字是否居中 boolean — false * onClose 关闭时的回调函数, 参数为被关闭的 message 实例 function — — * offset Message 距离窗口顶部的偏移量 number — 20 * * 调用 Message 或 this.$msg 会返回当前 Message 的实例。如果需要手动关闭实例,可以调用它的 close 方法。 * * 方法名 说明 * close 关闭当前的 Message --&gt; &lt;template&gt; &lt;transition name="message-fade"&gt; &lt;div :class="[ 'message', `message-${type}`, center?'is-center':'', customClass]" :style="positionStyle" @mouseenter=stopTimer @mouseleave=startTimer v-if="show"&gt; &lt;slot&gt;//插槽分发v-html数据 &lt;span v-if="message &amp;&amp; !dangerouslyUseHTMLString"&gt;{{message}}&lt;/span&gt; &lt;div v-else v-html="message"&gt;&lt;/div&gt; &lt;/slot&gt; &lt;i v-if="showClose" @click="closeMsg" class="message-close-btn"&gt;x&lt;/i&gt; &lt;/div&gt; &lt;/transition&gt; &lt;/template&gt; &lt;script&gt; export default{ components: {}, data () { //message组件默认数据 return { message: '', type: 'info', dangerouslyUseHTMLString: false, customClass: '', showClose: false, center: false, onClose: null, offset: 20, show: false, timer: null } }, computed: { positionStyle () { return `margin-top:${this.offset}px` } }, watch: {}, created () {}, mounted () {}, methods: { closeMsg () { this.close() }, startTimer () { const _this = this this.timer = setTimeout(() =&gt; { _this.close() }, _this.duration) }, stopTimer () { clearTimeout(this.timer) this.timer = null } } } &lt;/script&gt; &lt;style scoped&gt; .message{ position: relative; margin-top: 15vh; width: 30%; margin: 0 auto; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.3); box-sizing: border-box; min-width: 200px; padding: 20px 40px; border-radius: 10px; } .is-center{ text-align: center; } .message-success{ background-color: #f0f9eb; border-color: #e1f3d8; color: #67c23a; } .message-info{ background-color: #edf2fc; border-color: #909399; color: #909399; } .message-warning{ background-color: #fdf6ec; border-color: #faecd8; color: #e6a23c; } .message-error{ background-color: #fef0f0; border-color: #fde2e2; color: #f56c6c; } .message-fade-enter-active, .message-fade-leave-active { transition: all 0.1s ease-out; } .message-fade-enter-to { opacity: 1; transform: scale(1.2); } .message-fade-leave-to { opacity: 0; transform: scale(0.8); } .message-close-btn{ position: absolute; right: 10px; top: 3px; cursor: pointer; } &lt;/style&gt; </code></pre> <h2>webpack配置</h2> <pre><code>const path = require("path"); const webpack = require("webpack"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const resolve = (dir) =&gt; path.resolve(__dirname, dir); module.exports = { entry: "./src/main.js", //定义webpack的入口文件 output: { //定义webpack的输出 path: path.resolve(__dirname, "./dist"), //输出路径 filename: "vue-message-plugin.js", //输出文件名 libraryTarget: "umd", //把写的library打包成umd文件,把库暴露给当前使用的模块定义系统,同时适用commonJs 模块,AMD模块,也可以导出到 global 下的变量,library指定模块名或变量名 library: "vue-message-plugin", //以库的形式导出入口文件 umdNamedDefine: true, //在 UMD 库中使用命名的 AMD 模块 }, module: { //module选项决定了如何处理项目中的不同类型的模块 rules: [ //array,创建模块时,匹配请求的规则数组。这些规则能够修改模块的创建方式。这些规则能够对模块(module)应用 loader,或者修改解析器(parser)。 { test: /\.css$/, //rule条件:resource,请求文件的绝对路径。它已经根据 resolve 规则解析。(Rule.resource.test 的简写 use: [ //应用于模块的 UseEntries 列表。每个入口(entry)指定使用一个 loader。 "vue-style-loader", "css-loader", ], }, { test: /\.vue$/, loader: "vue-loader", options: { loaders: {}, }, }, { test: /\.js$/, loader: "babel-loader", exclude: /node_modules/, }, { test: /\.(png|jpg|gif|svg)$/, loader: "file-loader", options: { name: "[name].[ext]?[hash]", }, }, ], }, resolve: { //resolve选项能设置模块如何被解析 alias: { //定义 import 或 require 的别名,来确保模块引入变得更简单 vue$: "vue/dist/vue.esm.js", "@": resolve("src"), }, extensions: ["*", ".js", ".vue", ".json"], //自动解析确定的扩展。能够使用户在引入模块时不带扩展 }, devServer: { historyApiFallback: true, //当使用 HTML5 History API 时,任意的 404 响应都可能需要被替代为 index.html noInfo: true, //启用 noInfo 后,「启动时和每次保存之后,那些显示的 webpack 包(bundle)信息」的消息将被隐藏。错误和警告仍然会显示。 overlay: true, //出现编译器错误或警告时,在浏览器中显示全屏覆盖。 open: true, //自动打开浏览器 port: 3100, //设置端口 hot: true, //启用热更新 }, performance: { hints: false, //关闭提示 }, devtool: "#eval-source-map", //原始源代码生成 source map }; if (process.env.NODE_ENV === "production") { module.exports.devtool = "#source-map"; //原始源代码生成 source map module.exports.plugins = (module.exports.plugins || []).concat([ new webpack.DefinePlugin({ "process.env": { NODE_ENV: '"production"', }, }), new webpack.optimize.UglifyJsPlugin({ sourceMap: true, compress: { warnings: false, }, }), new webpack.LoaderOptionsPlugin({ minimize: true, }), ]); } else if (process.env.NODE_ENV === "development") { module.exports.devtool = "#eval-source-map"; module.exports.plugins = (module.exports.plugins || []).concat([ new webpack.DefinePlugin({ //插件:允许在编译时(compile time)配置的全局常量 "process.env": { NODE_ENV: '"development"', }, }), new webpack.optimize.UglifyJsPlugin({ //可以控制项目中 UglifyJS 的版本 sourceMap: true, compress: { warnings: false, }, }), new webpack.LoaderOptionsPlugin({ //用于从 webpack 1 迁移到 webpack 2 minimize: true, }), new HtmlWebpackPlugin({ //简单创建 HTML 文件,用于服务器访问 filename: "index.html", template: "index.html", inject: true, //注入打包的文件 }), ]); } </code></pre> 前端https://www.scarsu.com/vue_message_plugin/#post-comment/函数式编程https://www.scarsu.com/functional_programing/https://www.scarsu.com/functional_programing/改变引发错误,最小化改变Fri, 08 May 2020 00:00:00 GMT<h2>函数式编程</h2> <ul> <li>函数式编程是一种解决方案简单,功能独立,对作用域外没有任何副作用的<strong>编程范式</strong>。</li> <li><code>INPUT -&gt; PROCESS -&gt; OUTPUT</code></li> <li>函数式编程是一种基于函数计算的软件开发方法。</li> <li>像数学一样,函数在编程中通过输入产生输出。</li> <li>可以通过多种方式组合基本功能来构建越来越复杂的程序。</li> <li>函数式编程式将程序分成小的、可测试的部分</li> </ul> <h2>函数式编程原则</h2> <h3>功能独立,显式声明依赖关系</h3> <p>不依赖程序状态或全局变量,<strong>只依赖于传递给它们的参数进行计算</strong></p> <p>如果函数依赖于一个变量或对象,那么将该变量或对象作为参数直接传递到函数中。</p> <ol> <li>不要更改变量或对象——创建新变量和对象,并在需要时从函数返回它们。</li> <li>声明函数参数——<strong>函数内的任何计算仅取决于参数,而不取决于任何全局对象或变量</strong>。</li> </ol> <h3>有限的副作用</h3> <p>可以严格地限制函数外部对状态的更改导致的状态变化</p> <p>在变量,数组或对象上调用一个函数,这个函数可能会改变对象中的变量或其他东西。 函数式编程的核心原则之一是不改变任何东西,<strong>变化会导致错误</strong>。 如果一个函数不改变传入的参数、全局变量等数据,那么它造成问题的可能性就会小很多。</p> <p>在函数式编程中,改变或变更叫做<strong>mutation</strong></p> <p>这种改变的结果叫做“副作用”(<strong>side effect</strong></p> <p>理想情况下,函数应该是不会产生任何副作用的纯函数(<strong>pure function</strong></p> <h3>纯函数</h3> <p>同一个输入永远能得到同一个输出</p> <h3>限制更改程序状态</h3> <p>避免更改保存数据的全局对象</p> <h2>不改变原数组的 数组方法:</h2> <h3>concat 连接数组</h3> <h3>slice 提取数组一部分(代替splice从数组删除元素</h3> <h3>map 迭代数组返回新数组(callback return 新元素</h3> <h3>filter 迭代数组返回新数组(callback return true/false</h3> <h3>reduce 是 JavaScript 所有数组操作中最通用的方法。</h3> <p>几乎可以用reduce方法解决所有数组处理问题。 filter和map方法不支持对数组中两个不同元素的交互。举个例子,如果你想把数组中的元素拿来比较或者相加,用filter和map是做不到的。 reduce方法允许更通用的数组处理方式,而且filter和map方法都可以当作是reduce的特殊实现。 reduce(acc,cur,idx,arr)</p> <h3>sort排序 会改变原数组:利用concat([])返回新数组排序</h3> <pre><code>var globalArray = [5, 6, 3, 2, 9]; function nonMutatingSort(arr) { return arr.concat([]).sort((a, b) =&gt; a - b); } nonMutatingSort(globalArray); </code></pre> <h3>every方法,检查数组每个元素都通过检验,返回boolean</h3> <h3>some方法,检查数组有元素通过检验,返回boolean</h3> <h2>不改变String的方法:</h2> <h3>split</h3> <h3>toUpperCase</h3> <h3>trim</h3> <h3>+-运算</h3> <h2>函数柯里化</h2> <p>arity是函数所需的形参的数量。函数Currying意思是把接受多个arity的函数变换成接受单一arity的函数。</p> <p>重构函数让它接收一个参数,然后返回接收下一个参数的函数,依此类推。</p> <pre><code>//Un-curried function function unCurried(x, y) { return x + y; } // 柯里化函数 function curried(x) { return function (y) { return x + y; }; } curried(1)(2); // 返回 3 </code></pre> <p>柯里化在不能一次为函数提供所有参数情况下很有用。因为它可以将每个函数的调用保存到一个变量中,该变量将保存返回的函数引用,该引用在下一个参数可用时接受该参数。下面是使用curried函数的例子:</p> <pre><code>// Call a curried function in parts: var funcForY = curried(1); console.log(funcForY(2)); // 打印 3 </code></pre> <p><strong>partial application</strong>的意思是一次对一个函数应用几个参数,然后返回另一个应用更多参数的函数。</p> <pre><code>//Impartial function function impartial(x, y, z) { return x + y + z; } var partialFn = impartial.bind(this, 1, 2); partialFn(10); // 返回 13 </code></pre> 前端https://www.scarsu.com/functional_programing/#post-comment/正则自检清单https://www.scarsu.com/dive_into_regular_expression/https://www.scarsu.com/dive_into_regular_expression/正则是程序员必备的效率生产力知识~Wed, 06 May 2020 00:00:00 GMT<h2>资源</h2> <ul> <li><a>正则教程</a></li> <li><a>正则可视化</a></li> <li><a>正则实例</a></li> </ul> <h2>备忘录</h2> <p><img src="/images/regexp.png" alt="alt text" /></p> <h2>正则原型<code>test</code>方法</h2> <pre><code>let myString = "Hello, World!"; let myRegex = /Hello/; let result = myRegex.test(myString); </code></pre> <h2>或操作符<code>|</code></h2> <pre><code>let waldoIsHiding = "Somewhere Waldo is hiding in this text."; let waldoRegex = /Waldo/; let result = waldoRegex.test(waldoIsHiding); </code></pre> <h2>正则标志</h2> <ul> <li>标志<code>i</code>:忽略大小写</li> <li>标志<code>g</code>:全局匹配(多次匹配)</li> </ul> <h2>字符串原型方法:<code>match</code></h2> <ul> <li>在字符串上使用<code>.match()</code>方法将返回一个数组,其中包含它匹配的字符串及其捕获组。</li> </ul> <pre><code>"Hello, World!".match(/Hello/); // Returns ["Hello"] </code></pre> <h2>通配符:<code>.</code>(点)</h2> <h2>字符集匹配:<code>[]</code></h2> <pre><code>let vowelRegex = /[aeiou]/gi; let result = quoteSample.match(vowelRegex); </code></pre> <h2>字符集 连字符:<code>-</code> 字符范围</h2> <pre><code>let quoteSample = "The quick brown fox jumps over the lazy dog."; let alphabetRegex = /[a-z]/gi; let result = quoteSample.match(alphabetRegex); </code></pre> <h2>否定字符集:<code>^</code></h2> <ul> <li>/[^1-9]/g 匹配所有非数字字符</li> </ul> <h2><code>+*?^$</code></h2> <ul> <li>+:一次或多次</li> <li>*:0次或多次</li> <li>?:0次或1次</li> <li>字符串开头:^</li> <li>字符串结尾:$</li> </ul> <h2>贪婪匹配 &amp; 惰性匹配</h2> <ul> <li>贪婪匹配:正则默认贪婪匹配,匹配满足表达式的最长部分</li> <li>惰性匹配:匹配满足表达式的最小部分:加?</li> </ul> <pre><code>let text = "&lt;h1&gt;Winter is coming&lt;/h1&gt;"; let myRegex = /&lt;.*?1&gt;/; let result = text.match(myRegex); console.log(result); </code></pre> <h2>字符集</h2> <ul> <li><code>\w</code> : [A-Za-z0-9_] 数字字母下划线</li> <li><code>\W</code>: [^A-Za-z0-9_] 反匹配模式</li> <li><code>\d</code>: [0-9] 数字</li> <li><code>\D</code>: [^0-9] 非数字</li> <li><code>\s</code>: [\r\t\f\n\v] 空格 回车 制表符 换行 换页</li> <li><code>\S</code>: [^\r\t\f\n\v]</li> </ul> <h2>匹配的数量上下限</h2> <ul> <li><code>{m,n}</code>最少m个,最多n个</li> <li><code>{m}</code>指定m个</li> <li><code>{m,}</code>最少m个</li> <li><code>{,n}</code>最多n个</li> </ul> <h2>先行断言:在字符串中向前查找的匹配模式。</h2> <ul> <li><code>正向先行断言</code>:会查看并确保搜索匹配模式中的元素存在,但实际上并不匹配。</li> <li>用法是(<code>?=</code>...),其中...就是需要存在但不会被匹配的部分。</li> <li><code>负向先行断言</code>:会查看并确保搜索匹配模式中的元素不存在。</li> <li>用法是(<code>?!</code>...),其中...是你希望不存在的匹配模式。如果负向先行断言部分不存在,将返回匹配模式的其余部分。</li> </ul> <p>例子:</p> <ul> <li>3 到 6 个字符且至少包含一个数字:</li> </ul> <pre><code>let password = "abc123"; let checkPass = /(?=\w{3,6})(?=\D*\d)/; checkPass.test(password); // Returns true </code></pre> <ul> <li>至少5个字符且有连续两个数字的密码:</li> </ul> <pre><code>let sampleWord = "astronaut"; let pwRegex = /(?=\w{5,})(?=\D*\d{2}\D*)/; let result = pwRegex.test(sampleWord); </code></pre> <ul> <li>在vscode中正则搜索“未添加scoped属性的<code>&lt;style&gt;</code>标签”</li> </ul> <pre><code>&lt;style(?!.*scoped) </code></pre> <h2>捕获组:重用子字符串</h2> <ul> <li>用<code>()</code>来表示捕获组,匹配第一次出现的子字符串</li> <li>用<code> \n</code>来表示第n个捕获组,n是数字,表示第n个捕获组</li> </ul> <pre><code>let repeatStr = "regex regex"; let repeatRegex = /(\w+)\s\1/; repeatRegex.test(repeatStr); // Returns true repeatStr.match(repeatRegex); // Returns ["regex regex", "regex"] </code></pre> <h2>字符串原型方法replace:捕获组 搜索/替换</h2> <ul> <li> <p><code>.replace()</code>的输入首先是你想要搜索的正则表达式匹配模式,</p> </li> <li> <p>第二个参数是用于替换匹配的字符串或用于执行某些操作的函数。</p> </li> <li> <p>第二个参数中,可以用<code>$n</code>访问替换字符串中的捕获组(即用括号括起来的组)</p> </li> <li> <p>其中n表示<code>第n个捕获组</code></p> </li> <li> <p>例子:</p> </li> </ul> <pre><code>"Code Camp".replace(/(\w+)\s(\w+)/, "$2 $1"); // Returns "Camp Code" </code></pre> <ul> <li>去除字符串两端的空格</li> </ul> <pre><code>let hello = " Hello, World! "; let wsRegex = /^\s+(\S.*\S)\s+$/; let result = hello.replace(wsRegex, "$1"); </code></pre> 前端https://www.scarsu.com/dive_into_regular_expression/#post-comment/ML15 | Python与Js模型互转https://www.scarsu.com/fed_ml_15_py_model/https://www.scarsu.com/fed_ml_15_py_model/Javascript玩转机器学习15Thu, 30 Apr 2020 00:00:00 GMT<h2>Python模型</h2> <ul> <li>通过 Python版 Tensorflow/ Keras生成模型</li> <li>类型包括: Tensorflow Saved Model、 Keras HDF5mode等</li> <li>获取:开源网站下载/算法同事提供</li> </ul> <h2>Javascript模型</h2> <ul> <li>可以在 TensorflowJs中运行的模型</li> <li>类型包括: tijs layers model, tojs graph model等</li> <li>获取:开源网站/通过TFJS生成/由 Python模型转化而来</li> </ul> <h2>为什么要互转</h2> <ul> <li>Python to JavaScript: JavaScript模型可以在浏览器中运行</li> <li>JavaScript to Python:少见,为了在更多平台运行</li> <li>JavaScript to JavaScript:分片/量化/加速</li> </ul> <h2>TensorFlow.js Converter</h2> <ul> <li>命令行转换器</li> <li>依赖Python-3.6.8(可以使用Anaconda工具创建环境</li> <li>在命令行指定输入输出的路径和模型格式即可</li> <li><a>地址</a></li> </ul> <h2>JavaScript:分片/量化/加速</h2> <ul> <li>分片:将模型切分,提升加载速度</li> <li>量化:通过牺牲一部分精度,压缩模型的大小</li> <li>加速:将模型转换为tfjs_graph_model格式可以加速模型</li> </ul> <hr /> <p><a>代码仓库</a></p> 前端https://www.scarsu.com/fed_ml_15_py_model/#post-comment/Vue2状态管理 & Vuex总结https://www.scarsu.com/vue_store_and_vuex/https://www.scarsu.com/vue_store_and_vuex/多组件下 共享状态 的解决方案Thu, 30 Apr 2020 00:00:00 GMT<h1>Vue状态管理 &amp; Vuex</h1> <h3>单向数据流</h3> <ul> <li>**state:**驱动应用的数据源;</li> <li>**view:**以声明方式将 <strong>state</strong> 映射到视图;</li> <li>**actions:**响应在 <strong>view</strong> 上的用户输入导致的state变化。</li> </ul> <p><img src="/images/vuex1.png" alt="" /></p> <h3>多组件共享状态的需求:</h3> <ul> <li>多个视图依赖于同一状态:传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力</li> <li>来自不同视图的行为需要<strong>变更同一状态</strong>:父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码</li> </ul> <p>(共享状态,不仅仅是多组件<strong>读取</strong>同一状态,也包含多组件<strong>变更</strong>同一状态)</p> <h2>基于state的简单状态管理</h2> <ul> <li>在vue实例外的作用域,定义一个state对象,作为共享状态</li> </ul> <pre><code>let publicState = {}; let vm1 = new Vue({ name: "vm1", data: publicState, }); let vm2 = new Vue({ name: "vm2", data: publicState, }); </code></pre> <ul> <li>简单的store模式</li> </ul> <pre><code>let store = { state: { a: "", }, setStateA() {}, clearStateA() {}, }; //把store.state放在vue实例的data里 let vm1 = new Vue({ name: "vm1", data: { privateState: {}, //组件的私有状态 publicState: store.state, //实例外的共有状态 }, }); let vm2 = new Vue({ name: "vm2", data: { privateState: {}, publicState: store.state, }, }); </code></pre> <p>组件们可以共享store中的状态,也可以通过actions变更状态</p> <p>因为共享状态放在组件的data里,store变化也会驱动组件view变更</p> <p><img src="/images/vuex2.png" alt="" /></p> <h2>Vuex基本思想</h2> <p>把组件的共享状态抽取出来,以一个全局单例模式管理</p> <p>在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为</p> <p>通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,我们的代码将会变得更结构化且易维护。</p> <p><img src="/images/vuex3.png" alt="" /></p> <h2>Vuex的使用&amp;子组件注入</h2> <p>src/store/index.js</p> <pre><code>import Vue from "vue"; import Vuex from "vuex"; Vue.use(Vuex); export default new Vuex.Store({ state: { count: 0, }, mutations: { increment(state) { state.count++; }, decrement(state) { state.count--; }, }, }); </code></pre> <p>/src/main.js</p> <pre><code>import Vue from "vue"; import store from "@/store"; import router from "@/router"; import App from "@/App"; // store作为选项传入根组件,是将$store注入所有子组件 // 子组件都可以通过this.$store访问全局store // eslint-disable-next-line no-new new Vue({ el: "#app", store, router, render: (h) =&gt; h(App), }); </code></pre> <h2>Vuex的核心思想一:state</h2> <p>Vuex 使用单一状态树——用一个对象(store)就包含了全部的应用层级状态。</p> <p>至此它便作为一个“唯一数据源 (SSOT)”而存在。</p> <p>这也意味着,每个应用将仅仅包含一个 store 实例。</p> <p>单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。</p> <h3>子组件获取state &amp; mapState辅助函数</h3> <p>/src/page/home.vue</p> <pre><code> &lt;template&gt; &lt;div id="home"&gt; &lt;div&gt;count:{{count}}&lt;/div&gt; &lt;div&gt;count1:{{count1}}&lt;/div&gt; &lt;div&gt;count3:{{count3}}&lt;/div&gt; &lt;div&gt;count4:{{count4}}&lt;/div&gt; &lt;div&gt;count5:{{count5}}&lt;/div&gt; &lt;button @click="increment"&gt;+&lt;/button&gt; &lt;button @click="decrement"&gt;-&lt;/button&gt; &lt;/div&gt; &lt;/template&gt; &lt;script&gt; import { mapState } from 'vuex' export default { name: 'home', data () { return { message: 'hello', localCount: 1 } }, computed: { // 方式1:直接从Vue原型链上获取$store count1 () { return this.$store.state.count }, // 方式2:mapState方法传状态名数组 ...mapState(['count']), ...mapState({ // 方式3:mapState传对象,键为状态别名,值为状态名 count3: 'count', // 方式4:mapState传对象,键为getter函数,参数是state,值为箭头函数 count4: state =&gt; state.count, // 方式5:mapState传对象,键为getter函数,参数是state,值为普通函数(因为要再函数体内用this) count5 (state) { return this.localCount + state.count } }) }, methods: { increment () { this.$store.commit('increment') }, decrement () { this.$store.commit('decrement') } } } &lt;/script&gt; </code></pre> <h2>Vuex核心思想二:getter</h2> <h3>派生状态</h3> <p>类似于vue组件的计算属性,可以从store的state中派生出一些状态</p> <pre><code>export default new Vuex.Store({ state: { todos: [ { id: 1, desc: "test1", done: false }, { id: 2, desc: "test2", done: true }, { id: 3, desc: "test3", done: false }, ], }, getters: { //getter中可以接受其他getter作为参数 maxTodoId(state, getters) { return state.todos.sort((a, b) =&gt; { return b.id - a.id; })[0].id; }, doneTodoCount(state) { return state.todos.filter((todo) =&gt; todo.done === true).length; }, }, }); </code></pre> <h3>通过this.$store.state.getters属性 / mapGetters访问派生状态</h3> <pre><code>computed: { ...mapGetters(['doneTodoCount']), doneTodoCount2 () { return this.$store.getters.doneTodoCount } }, </code></pre> <h3>getter传参:让getter返回函数</h3> <pre><code>getters: { getTodoBySearch: (state) =&gt; (s) =&gt; { return state.todos.filter((todo) =&gt; { return (todo.id + todo.desc).indexOf(s) &gt;= 0; }); }; } </code></pre> <h2>Vuex核心思想三:mutation</h2> <h3>提交mutation</h3> <p>组件不能直接更改Vuex store中的状态,而是要提交(commit)变更(mutations)</p> <pre><code>export default { name: "home", data() { return {}; }, methods: { addTodo(e) { if (e.keyCode === 13 &amp;&amp; this.model.desc) { this.$store.commit("addTodo", this.model.desc); this.model.desc = ""; } }, }, }; </code></pre> <p>其中<strong>addTodo</strong>就是在store的mutation中定义的一种变更:</p> <pre><code>mutations: { addTodo (state, desc) { const maxTodoId = state.todos.sort((a, b) =&gt; { return b.id - a.id })[0].id const todo = { desc, id: maxTodoId + 1, done: false } state.todos.push(todo) } } </code></pre> <h3><strong>提交载荷(Payload)</strong></h3> <p>可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload):</p> <pre><code>// src/store/index.js mutations: { increment (state, payload) { } } // src/page/home.vue let payload={a:1,b:2} store.commit('increment', payload) </code></pre> <h3>Mutation 需遵守 Vue 的响应规则</h3> <p>Vuex 的 store 中的状态是响应式的,</p> <p>当我们变更状态时,</p> <p>监视状态的 Vue 组件也会自动更新,</p> <p>因此 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项</p> <ol> <li> <p>最好提前在你的 store 中初始化好所有所需属性。</p> </li> <li> <p>当需要在对象上添加新属性时,应该</p> <ul> <li>使用 <code>Vue.set(obj, 'newProp', 123)</code></li> <li>以新对象替换老对象。例如,利用**<a>对象展开运算符</a>**:</li> </ul> <pre><code>state.obj = { ...state.obj, newProp: 123 }; </code></pre> </li> </ol> <h3>使用常量替代 Mutation 事件类型</h3> <pre><code>// mutation-types.js export const SOME_MUTATION = 'SOME_MUTATION' // store.js import Vuex from 'vuex' import { SOME_MUTATION } from './mutation-types' const store = new Vuex.Store({ state: { ... }, mutations: { // 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名 [SOME_MUTATION] (state) { // mutate state } } }) </code></pre> <h3>Mutation 必须是同步函数</h3> <p>devtools捕捉会mutations记录,每次记录前一状态+后一状态的快照</p> <p>如果mutation里是异步的函数,很可能快照捕捉时,状态还未更改</p> <p>在回调函数中进行的状态的改变都是不可追踪的</p> <p>因此很<strong>不利于调试</strong></p> <h2>Vuex核心思想四:Action</h2> <h3>Action与Mutation类似,不同点:</h3> <ul> <li>Action 提交(commit)的是 mutation,而<strong>不是直接变更状态</strong>。</li> <li>Action 可以包含任意<strong>异步</strong>操作。</li> </ul> <h3>action函数的定义</h3> <pre><code>//... actions: { addTodo (context) { // 可以通过context参数去调用commit,获取state和getters // context区别于state(module中会讲到 setTimeout(() =&gt; { context.commit('addTodo') // context.state // context.getters }, 1000) }, addTodo2 ({ commit, state, getters }) { // 也可以直接用参数解构的方法获取commit,state,getters setTimeout(() =&gt; { commit('addTodo') }, 1000) } } //... </code></pre> <h3>组件分发action(可以带载荷/参数</h3> <pre><code>methods: { addTodo (e) { this.$store.dispatch('addTodo', payload) this.$store.dispatch({ type: 'addTodo', ...payload }) } } //action接收payload参数 //action内部也可以dispatch其他action actions: { addTodo2 ({ commit, state, getters, dispatch }, payload) { // 也可以直接用参数解构的方法获取commit,state,getters setTimeout(() =&gt; { commit('addTodo') //dispatch }, 1000) } } </code></pre> <h3>组合action</h3> <ul> <li>action可以返回一个promise函数</li> </ul> <pre><code>actions: { actionA ({ commit }) { return new Promise((resolve, reject) =&gt; { setTimeout(() =&gt; { commit('someMutation') resolve() }, 1000) }) } } </code></pre> <ul> <li>dispatch可以处理action返回的promise,并仍然返回promise</li> </ul> <pre><code>store.dispatch("actionA").then(() =&gt; { // ... }); </code></pre> <ul> <li>利用await/async编写组合action更加简洁</li> </ul> <pre><code>// 假设 getData() 和 getOtherData() 返回的是 Promise actions: { async actionA ({ commit }) { commit('gotData', await getData()) }, async actionB ({ commit, dispatch }) { await dispatch('actionA') commit('gotOtherData', await getOtherData()) } } </code></pre> <h2>Vuex核心思想五:Module</h2> <p>当应用较复杂时,应用所有状态集中在一个(store)对象上很臃肿</p> <p>因此Vuex允许将store按模块来划分,</p> <p>每个store拥有自己的state、getter、mutations、actions、子模块</p> <pre><code>// src/store/module/moduleA.js export default { state: {}, getter: {}, mutations: {}, actions: {} } // src/store/index.js import Vue from 'vue' import Vuex from 'vuex' import moduleA from 'module/moduleA' Vue.use(Vuex) export default new Vuex.Store({ modules: { a: moduleA }, ... }) </code></pre> <h3>模块内的局部状态state(getter mutation action获取state</h3> <p><strong>对于模块内的getter、mutation函数</strong>:</p> <p>接收的第一个参数:state,指向的是模块内的局部状态</p> <p>getter函数接收的<strong>第三个</strong>参数是根节点状态:<strong>rootState</strong></p> <p><strong>对于模块内的action函数:</strong></p> <p>context.state指向的也是模块的局部状态,根节点的状态为<strong>context.rootState</strong></p> <h3>全局命名空间(组件获取getter mutation action</h3> <p>默认情况:模块内部的 action、mutation 和 getter 是注册在<strong>全局命名空间</strong>的——这样使得多个模块能够对同一 mutation 或 action 作出响应。</p> <h3>带命名空间的模块</h3> <p>如果希望你的模块具有更高的<strong>封装度和复用性</strong>,你可以通过添加 <strong>namespaced: true</strong> 的方式使其成为带命名空间的模块。</p> <pre><code>const store = new Vuex.Store({ modules: { account: { namespaced: true, // 模块内容(module assets) state: { ... }, // 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响 getters: { isAdmin () { ... } // -&gt; getters['account/isAdmin'] }, actions: { login () { ... } // -&gt; dispatch('account/login') }, mutations: { login () { ... } // -&gt; commit('account/login') }, // 嵌套模块 modules: { // 没加namespaced属性,所以继承父模块的命名空间 myPage: { state: { ... }, getters: { profile () { ... } // -&gt; getters['account/profile'] } }, // 进一步嵌套命名空间 posts: { namespaced: true, state: { ... }, getters: { popular () { ... } // -&gt; getters['account/posts/popular'] } } } } } }) </code></pre> <p>启用了命名空间的 getter 和 action 会<strong>收到局部化的 getter,dispatch 和 commit</strong>。</p> <p>换言之,在使用模块内容(module assets,即指模块内的state、getter、mutation、action)时不需要在同一模块内额外添加空间名前缀。</p> <p>所以:更改 namespaced 属性后不需要修改模块内的代码</p> <h3>带命名空间的模块内访问全局内容(Global Assets)</h3> <p>Global Assets即全局的state,getter,mutation,action</p> <ul> <li>getter的第三、第四参数:rootState、rootGetters</li> <li>action的context参数包含:rootState、rootGetters</li> <li>全局commit、dispatch:传入参数root:true</li> </ul> <h3>带命名空间的模块注册全局 action</h3> <p>传入root选项,值为true</p> <pre><code>... someAction:{ root:true, handler:()=&gt;{} } ... </code></pre> <h3>mapState, mapGetters, mapActions 和 mapMutations操作命名空间:</h3> <pre><code>// 方法一:直接在状态名前加命名空间 computed: { ...mapState({ a: state =&gt; state.some.nested.module.a, b: state =&gt; state.some.nested.module.b }) }, methods: { ...mapActions([ 'some/nested/module/foo', // -&gt; this['some/nested/module/foo']() 'some/nested/module/bar' // -&gt; this['some/nested/module/bar']() ]) } // 方法二:也可以把共有的命名空间传给函数第一个参数 computed: { ...mapState('some/nested/module', { a: state =&gt; state.a, b: state =&gt; state.b }) }, methods: { ...mapActions('some/nested/module', [ 'foo', // -&gt; this.foo() 'bar' // -&gt; this.bar() ]) } //方法三:利用createNamespacedHelpers,传入命名空间,会返回已经绑定命名空间的map方法 import { createNamespacedHelpers } from 'vuex' const { mapState, mapActions } = createNamespacedHelpers('some/nested/module') </code></pre> <h3>动态注册模块</h3> <p>在store已经实例化后,如果想添加模块,可以用registerModule方法</p> <pre><code>import Vuex from "vuex"; const store = new Vuex.Store({ /* 选项 */ }); // 注册模块 `myModule` store.registerModule("myModule", { // ... }); // 注册嵌套模块 `nested/myModule` store.registerModule(["nested", "myModule"], { // ... }); </code></pre> <p>卸载动态模块:unregisterModule(不能卸载静态模块</p> <p>判断模块是否存在:hasModule</p> <h2>纯对象state&amp;函数声明state</h2> <p>纯对象state可以通过引用被访问,造成状态对象被修改时 store 或模块间数据互相污染的问题。</p> <p>因此可以和vue组件内的data一样,使用函数来声明state:</p> <pre><code>const MyReusableModule = { state() { return { foo: "bar", }; }, // mutation, action 和 getter 等等... }; </code></pre> <h2>严格模式</h2> <p>在非生产环境开启严格模式,在任何尝试不通过mutation直接修改state的操作时,都会抛出错误</p> <h2>v-model &amp; Vuex的state</h2> <p>v-model直接绑定Vuex上的state,在严格模式下会报错,因为双向绑定的机制会直接尝试修改state,而不是通过mutation,解决方法是,绑定一个设置了getter和setter的计算属性:</p> <pre><code>... computed:{ attr:{ getter(){ return this.$store.state.attr }, setter(val){ this.$store.commit('updateAttr',val) } } } </code></pre> 前端https://www.scarsu.com/vue_store_and_vuex/#post-comment/ML14 | 声控轮播图 - 语音识别迁移学习https://www.scarsu.com/fed_ml_14_slider/https://www.scarsu.com/fed_ml_14_slider/Javascript玩转机器学习14Wed, 29 Apr 2020 00:00:00 GMT<h2>在浏览器中收集中文语音训练数据</h2> <ul> <li>html</li> </ul> <pre><code>&lt;script src="script.js"&gt;&lt;/script&gt; &lt;button onclick="collect(this)"&gt;上一张&lt;/button&gt; &lt;button onclick="collect(this)"&gt;下一张&lt;/button&gt; &lt;button onclick="collect(this)"&gt;背景噪音&lt;/button&gt; &lt;button onclick="save()"&gt;保存&lt;/button&gt; &lt;pre id="count"&gt;&lt;/pre&gt; &lt;button onclick="train()"&gt;训练&lt;/button&gt; &lt;br /&gt;&lt;br /&gt; 监听开关:&lt;input type="checkbox" onchange="toggle(this.checked)" /&gt; </code></pre> <ul> <li>js</li> </ul> <pre><code>import * as speechCommands from "@tensorflow-models/speech-commands"; import * as tfvis from "@tensorflow/tfjs-vis"; const MODEL_PATH = "http://127.0.0.1:8080"; let transferRecognizer; window.onload = async () =&gt; { const recognizer = speechCommands.create( "BROWSER_FFT", //浏览器的傅里叶变换(将声音转为声谱数据 null, MODEL_PATH + "/speech/model.json", MODEL_PATH + "/speech/metadata.json", ); await recognizer.ensureModelLoaded(); //使用createTransfer接口创建迁移模型 transferRecognizer = recognizer.createTransfer("轮播图"); }; window.collect = async (btn) =&gt; { btn.disabled = true; const label = btn.innerText; //用collectExample接口收集语音数据,传入语音命令名称,背景音名称是固定的_background_noise_ await transferRecognizer.collectExample( label === "背景噪音" ? "_background_noise_" : label, ); btn.disabled = false; //将收集的数据可视化 document.querySelector("#count").innerHTML = JSON.stringify( transferRecognizer.countExamples(), null, 2, ); }; </code></pre> <h2>语音训练数据的保存</h2> <pre><code>window.save = () =&gt; { //用serializeExamples接口将收集的样例数据序列化 const arrayBuffer = transferRecognizer.serializeExamples(); const blob = new Blob([arrayBuffer]); const link = document.createElement("a"); link.href = window.URL.createObjectURL(blob); link.download = "data.bin"; link.click(); }; </code></pre> <h2>加载数据,用speech commands包行迁移学习,训练</h2> <pre><code>window.onload = async () =&gt; { const recognizer = speechCommands.create( "BROWSER_FFT", null, MODEL_PATH + "/speech/model.json", MODEL_PATH + "/speech/metadata.json", ); await recognizer.ensureModelLoaded(); transferRecognizer = recognizer.createTransfer("轮播图"); //用fetch方法从本静态服务器拿到样例数据 const res = await fetch(MODEL_PATH + "/slider/data.bin"); //转为arrayBuffer格式 const arrayBuffer = await res.arrayBuffer(); //模型加载样例数据 transferRecognizer.loadExamples(arrayBuffer); //模型训练 await transferRecognizer.train({ epochs: 30 }); console.log("done"); }; </code></pre> <h2>轮播图html</h2> <ul> <li>html</li> </ul> <pre><code>&lt;script src="script.js"&gt;&lt;/script&gt; 监听开关:&lt;input type="checkbox" onchange="toggle(this.checked)" /&gt; &lt;style&gt; .slider { width: 600px; overflow: hidden; margin: 10px auto; } .slider &gt; div { display: flex; align-items: center; } &lt;/style&gt; &lt;div class="slider"&gt; &lt;div&gt; &lt;img loading="lazy" decoding="async" src="https://cdn.pixabay.com/photo/2019/10/29/15/57/vancouver-4587302__480.jpg" alt="" width="600" /&gt; &lt;img loading="lazy" decoding="async" src="https://cdn.pixabay.com/photo/2019/10/31/07/14/coffee-4591159__480.jpg" alt="" width="600" /&gt; &lt;img loading="lazy" decoding="async" src="https://cdn.pixabay.com/photo/2019/11/01/11/08/landscape-4593909__480.jpg" alt="" width="600" /&gt; &lt;img loading="lazy" decoding="async" src="https://cdn.pixabay.com/photo/2019/11/02/21/45/maple-leaf-4597501__480.jpg" alt="" width="600" /&gt; &lt;img loading="lazy" decoding="async" src="https://cdn.pixabay.com/photo/2019/11/02/03/13/in-xinjiang-4595560__480.jpg" alt="" width="600" /&gt; &lt;img loading="lazy" decoding="async" src="https://cdn.pixabay.com/photo/2019/11/01/22/45/reschensee-4595385__480.jpg" alt="" width="600" /&gt; &lt;/div&gt; &lt;/div&gt; </code></pre> <h2>监听&amp;控制轮播</h2> <pre><code>await transferRecognizer.listen( (result) =&gt; { const { scores } = result; const labels = transferRecognizer.wordLabels(); const index = scores.indexOf(Math.max(...scores)); window.play(labels[index]); }, { overlapFactor: 0, probabilityThreshold: 0.5, }, ); window.play = (label) =&gt; { const div = document.querySelector(".slider&gt;div"); if (label === "上一张") { if (curIndex === 0) { return; } curIndex -= 1; } else { if (curIndex === document.querySelectorAll("img").length - 1) { return; } curIndex += 1; } div.style.transition = "transform 1s"; div.style.transform = `translateX(-${100 * curIndex}%)`; }; </code></pre> <hr /> <p><a>代码仓库</a></p> 前端https://www.scarsu.com/fed_ml_14_slider/#post-comment/高效使用VSCodehttps://www.scarsu.com/customize_vscode/https://www.scarsu.com/customize_vscode/VSCode高效使用,来自创造VSCode的Microsoft的Azure团队的BurkeHolland的分享Tue, 28 Apr 2020 00:00:00 GMT<h2>Links</h2> <ul> <li><a>全文</a></li> <li><a>视频</a></li> <li><a>插件vs-code-can-do-that</a></li> </ul> <h2>记录几个高光点</h2> <ul> <li><strong>Setting Sync插件</strong>:使用gist,同步一切你的个性化配置(user settings,not workspace settings,workspace settings建议存在项目的代码仓库里使团队成员有统一的配置),即使切换环境,也可以在几分钟内得到一个一模一样的完全得心应手的IDE(gist已经被墙</li> <li><strong>Project Manager插件</strong>:在侧边栏一键切换/多开工作区/项目,只需要一个简单的配置文件</li> <li>侧边栏建议放在右侧,放在左侧时,侧边栏的隐藏/显示,会使整个代码区移动</li> </ul> <hr /> <p>&lt;small&gt;视频讲的很细很全,不做赘述。很多有用的tips&lt;/small&gt;</p> 前端https://www.scarsu.com/customize_vscode/#post-comment/ML13 | 用tf官方的预训练模型-语音识别https://www.scarsu.com/fed_ml_13_speech_recognition/https://www.scarsu.com/fed_ml_13_speech_recognition/Javascript玩转机器学习13Tue, 28 Apr 2020 00:00:00 GMT<h2>语音识别</h2> <ul> <li>模型接受声音信息,输出分类信息</li> <li>声音在计算机里是声谱图,因此也可以使用卷积神经网络</li> </ul> <h2>加载预训练语音识别模型(tf官网的模型)</h2> <ul> <li>开本地静态服务器,获取语音识别模型文件</li> <li>使用tfjs-models的speech-commands包加载模型 (tfjs-models是tf官方的模型库)</li> </ul> <h2>进行语音识别</h2> <ul> <li>html</li> </ul> <pre><code>&lt;script src="script.js"&gt;&lt;/script&gt; &lt;style&gt; #result &gt; div { float: left; padding: 20px; } &lt;/style&gt; &lt;div id="result"&gt;&lt;/div&gt; </code></pre> <ul> <li>js</li> </ul> <pre><code>// 引入tf-models库提供的语音命令npm包 import * as speechCommands from "@tensorflow-models/speech-commands"; //本地静态文件服务器地址 const MODEL_PATH = "http://127.0.0.1:8080/speech"; window.onload = async () =&gt; { // speechCommands文档: // https://github.com/tensorflow/tfjs-models/tree/master/speech-commands const recognizer = speechCommands.create( "BROWSER_FFT", //傅里叶变换 null, MODEL_PATH + "/model.json", MODEL_PATH + "/metadata.json", ); //加载模型 await recognizer.ensureModelLoaded(); //显示模型能识别的语音类型 const labels = recognizer.wordLabels().slice(2); const resultEl = document.querySelector("#result"); resultEl.innerHTML = labels .map( (l) =&gt; ` &lt;div&gt;${l}&lt;/div&gt; `, ) .join(""); //浏览器监听语音 recognizer.listen( (result) =&gt; { const { scores } = result; const maxValue = Math.max(...scores); //拿到分类中 可能性最大的单词 const index = scores.indexOf(maxValue) - 2; //突出显示 resultEl.innerHTML = labels .map( (l, i) =&gt; ` &lt;div style="background: ${i === index &amp;&amp; "green"}"&gt;${l}&lt;/div&gt; `, ) .join(""); }, { overlapFactor: 0.3, //识别频率 probabilityThreshold: 0.9, //准确度阈值,超过0.9的准确度 就执行参数一的函数 }, ); }; </code></pre> <h2>效果</h2> <p><img src="/images/ai/003.gif" alt="语音指令识别" /></p> <hr /> <p><a>代码仓库</a></p> 前端https://www.scarsu.com/fed_ml_13_speech_recognition/#post-comment/ML12 | 基于迁移学习的图片分类-商标识别https://www.scarsu.com/fed_ml_12_transfer_learning/https://www.scarsu.com/fed_ml_12_transfer_learning/Javascript玩转机器学习12Mon, 27 Apr 2020 00:00:00 GMT<h2>迁移学习</h2> <ul> <li><strong>是什么</strong>:把已训练好的模型参数迁移到新的模型来帮助新模型训练</li> <li><strong>为什么</strong>:深度学习模型参数多,从头训练成本高</li> <li><strong>怎么做</strong>:删除原始模型的最后一层,基于此截断模型的输出训练一个新的(通常相当浅的)模型</li> </ul> <h2>加载商标训练数据并可视化</h2> <ul> <li> <p>商标训练素材 <img src="/images/ai/63.png" alt="训练素材" /></p> </li> <li> <p>在本地为素材建立静态http服务器</p> </li> </ul> <pre><code>hs data --cors </code></pre> <ul> <li>编写JS脚本加载训练图片及其标签</li> </ul> <pre><code>// index.html &lt;script src="script.js"&gt;&lt;/script&gt; &lt;input type="file" onchange="predict(this.files[0])" /&gt; &lt;button onclick="download()"&gt;下载模型&lt;/button&gt; </code></pre> <pre><code>// data.js const loadImg = (src) =&gt; { return new Promise((resolve) =&gt; { const img = document.createElement("img"); img.crossOrigin = "anonymous"; img.src = src; img.width = 224; //以mobileNet为截断模型,其接收图片尺寸为224 img.height = 224; img.onload = () =&gt; reslove(img); }); }; // 返回Promise export const getInputs = async () =&gt; { const loadImgs = []; const labels = []; for (let i = 0; i &lt; 30; i += 1) { ["android", "apple", "windows"].forEach((label) =&gt; { const imgP = loadImg( `http://127.0.0.1:8080/brand/train/${label}-${index}.jpg`, ); loadImgs.push(imgP); labels.push([ label === "android" ? 1 : 0, label === "apple" ? 1 : 0, label === "windows" ? 1 : 0, ]); }); } const inputs = await Promise.all(loadImgs); return { inputs, labels, }; }; </code></pre> <pre><code>// script.js import * as tf from "@tensorflow/tfjs"; import * as tfvis from "@tensorflow/tfjs-vis"; import { getInputs } from "./data"; import { img2x, file2img } from "./utils"; const MOBILENET_MODEL_PATH = "http://127.0.0.1:8080/mobilenet/web_model/model.json"; const NUM_CLASSES = 3; const BRAND_CLASSES = ["android", "apple", "windows"]; window.onload = async () =&gt; { const { inputs, labels } = await getInputs(); // console.log([inputs,labels]) //将加载的图片素材可视化 const surface = tfvis .visor() .surface({ name: "输入示例", styles: { height: 250 } }); inputs.forEach((img) =&gt; { surface.drawArea.appendChild(img); }); }; </code></pre> <ul> <li>可视化训练图片: <img src="/images/ai/64.png" alt="可视化训练图片" /></li> </ul> <h2>加载预训练好的模型Mobilenet</h2> <pre><code>//加载预训练好的模型Mobilenet const mobilenet = await tf.loadLayersModel(MOBILENET_MODEL_PATH); //mobilenet的方法,给出其神经网络的概览 mobilenet.summary(); </code></pre> <p><img src="/images/ai/65.png" alt="mobilenet模型概览" /></p> <h2>定义截断模型</h2> <pre><code>//获取中间层 const layer = mobilenet.getLayer("conv_pw_13_relu"); //定义一个截断模型truncatedMobilenet const truncatedMobilenet = tf.model({ inputs: mobilenet.inputs, outputs: layer.output, }); </code></pre> <h2>定义双层的迁移模型</h2> <pre><code>//定义一个模型 const model = tf.sequential(); //添加一个flatten层(将截断模型提取的高维特征提取成一维向量,这一层没有参数,起转换作用 model.add( tf.layers.flatten({ inputShape: layer.outputShape.slice(1), }), ); //添加一个全链接层:用于训练我们的商标图片 model.add( tf.layers.dense({ units: 10, activation: "relu", }), ); //添加一个全链接层:用于做多分类 model.add( tf.layers.dense({ units: NUM_CLASSES, activation: "softmax", }), ); //设置损失函数:分类交叉熵损失函数,优化器为adam model.compile({ loss: "categoricalCrossentropy", optimizer: tf.train.adam() }); </code></pre> <h2>先用截断模型训练数据,转为可以用于迁移模型的数据</h2> <pre><code>//训练数据 先经过截断模型,转为可以用于迁移模型的数据 const { xs, ys } = tf.tidy(() =&gt; { const xs = tf.concat( inputs.map((imgEl) =&gt; truncatedMobilenet.predict(img2x(imgEl))), ); const ys = tf.tensor(labels); return { xs, ys }; }); </code></pre> <h2>训练迁移模型</h2> <pre><code>//训练迁移模型 await model.fit(xs, ys, { epochs: 20, callbacks: tfvis.show.fitCallbacks({ name: "训练效果" }, ["loss"], { callbacks: ["onEpochEnd"], }), }); </code></pre> <p><img src="/images/ai/66.png" alt="迁移模型训练效率高" /></p> <h2>预测</h2> <pre><code>window.predict = async (file) =&gt; { const img = await file2img(file); document.body.appendChild(img); const pred = tf.tidy(() =&gt; { const x = img2x(img); const input = truncatedMobilenet.predict(x); return model.predict(input); }); const index = pred.argMax(1).dataSync()[0]; setTimeout(() =&gt; { alert(`预测结果:${BRAND_CLASSES[index]}`); }, 0); }; </code></pre> <p><img src="/images/picgo/002.gif" alt="预测效果" /></p> <h2>模型的保存和加载</h2> <ul> <li>保存:把训练好的模型保存成文件或者 local storage变量</li> </ul> <pre><code>window.download = async () =&gt; { await model.save('downloads://model'); }; </code></pre> <ul> <li>加载:从文件或者 local storage中加载模型</li> <li>原因:无需重复训练,便于复用到其他应用中</li> </ul> <hr /> <p><a>代码仓库</a></p> 前端https://www.scarsu.com/fed_ml_12_transfer_learning/#post-comment/ML11 | 使用预训练模型 图片分类https://www.scarsu.com/fed_ml_11_pre_training_model/https://www.scarsu.com/fed_ml_11_pre_training_model/Javascript玩转机器学习11Sun, 26 Apr 2020 00:00:00 GMT<h2>预训练模型是什么</h2> <ul> <li>预先训练好的模型,无需训练,即可预测</li> <li>在Tensorflow.js中可以调用Web格式的模型文件</li> </ul> <h2>MobileNet模型</h2> <ul> <li>一种卷积神经网络模型,能识别1000种物体图片</li> <li>模型文件小,响应速度块,准确度略低</li> </ul> <h4>引入模型文件</h4> <ul> <li>为资源启动本地静态资源服务器(文件位于本地代码仓库/data下)</li> </ul> <pre><code>hs data --cors </code></pre> <ul> <li>引入资源</li> </ul> <pre><code>const MOBILENET_MODEL_PATH = 'http://127.0.0.1:8080/mobilenet/web_model/model.json'; </code></pre> <ul> <li>引入物体类型</li> </ul> <pre><code>import { IMAGENET_CLASSES } from './imagenet_classes'; </code></pre> <h4>用tfjs加载模型</h4> <pre><code>//用tf的loadLayersModel加载模型 const model = await tf.loadLayersModel(MOBILENET_MODEL_PATH); </code></pre> <h4>前端输入带预测数据</h4> <ul> <li>html</li> </ul> <pre><code>&lt;script src="script.js"&gt;&lt;/script&gt; &lt;input type="file" onchange="predict(this.files[0])" /&gt; </code></pre> <h4>使用模型进行预测</h4> <pre><code>// ./util.js export function file2img(f) { return new Promise((resolve) =&gt; { const reader = new FileReader(); reader.readAsDataURL(f); reader.onload = (e) =&gt; { const img = document.createElement("img"); img.src = e.target.result; img.width = 224; img.height = 224; img.onload = () =&gt; resolve(img); }; }); } // ./script.js window.predict = async (file) =&gt; { //从文件转换为htmlElement const img = await file2img(file); document.body.appendChild(img); const pred = tf.tidy(() =&gt; { //tidy优化webGl内存 const input = tf.browser .fromPixels(img) //转换为tensor .toFloat() //整数转为浮点数 .sub(255 / 2) //归一化 .div(255 / 2) .reshape([1, 224, 224, 3]); //一个图片的格式 return model.predict(input); //预测 }); const index = pred.argMax(1).dataSync()[0]; // setTimeout 0 使ui不被脚本阻塞 setTimeout(() =&gt; { alert(`预测结果:${IMAGENET_CLASSES[index]}`); }, 0); }; </code></pre> <h2><img src="/images/ai/61.png" alt="预测效果" /></h2> <p><a>代码仓库</a></p> 前端https://www.scarsu.com/fed_ml_11_pre_training_model/#post-comment/ML10 | 训练卷积神经网络 识别手写数字https://www.scarsu.com/fed_ml_10_handwriting_number/https://www.scarsu.com/fed_ml_10_handwriting_number/Javascript玩转机器学习10Sat, 25 Apr 2020 00:00:00 GMT<p><img src="/images/picgo/001.gif" alt="先看一下简单训练的预测效果" /></p> <h2>加载MNIST数据集</h2> <ul> <li> <p>MNIST:巨大的训练集雪碧图,以手写数字图片组成</p> </li> <li> <p>资源文件位置</p> </li> </ul> <pre><code>/js-ml-code/data/mnist mnist_images.png mnist_labels_uint8 </code></pre> <ul> <li>给资源文件建立服务器供解析脚本访问</li> </ul> <pre><code>hs data --cors </code></pre> <p>其中--cors表示允许跨域访问</p> <ul> <li>加载20组数据</li> </ul> <pre><code>import * as tf from "@tensorflow/tfjs"; import * as tfvis from "@tensorflow/tfjs-vis"; import { MnistData } from "./data"; window.onload = async () =&gt; { const data = new MnistData(); await data.load(); //加载资源 const examples = data.nextTestBatch(20); //获取20组验证集数据 console.log(examples); }; </code></pre> <ul> <li> <p>打印出的examples: <img src="/images/ai/55.png" alt="" /> <img src="/images/ai/57.png" alt="" /></p> </li> <li> <p>tensorflow的splice api <img src="/images/ai/58.png" alt="" /></p> </li> <li> <p>用tensorflow的api和canvas显示出20组图片</p> </li> </ul> <pre><code>const surface = tfvis.visor().surface({ name: "输入示例" }); for (let i = 0; i &lt; 20; i += 1) { //截取出单个图片:从第1维的第i项+第二维的第1项开始截取,第一维截取长度是1,第二维截取长度是784 //console.log(examples.xs.slice([i, 0], [1, 784])) //tf.tidy:用于优化webGl内存,防止tensor数据量过大导致内存泄漏 //tf.browser.toPixels:转换成浏览器能识别的像素格式,传入二位参数就是黑白图片,三维就是彩色的 //tensor.reshape:tensor格式转换 const imageTensor = tf.tidy(() =&gt; { return examples.xs.slice([i, 0], [1, 784]).reshape([28, 28, 1]); //将一维数组转换成三维黑白图片格式 }); const canvas = document.createElement("canvas"); canvas.width = 28; canvas.height = 28; canvas.style = "margin: 4px"; await tf.browser.toPixels(imageTensor, canvas); surface.drawArea.appendChild(canvas); } </code></pre> <ul> <li>显示效果:</li> </ul> <p><img src="/images/ai/56.png" alt="" /></p> <h2>卷积神经网络</h2> <h4>为什么要用卷积神经网络</h4> <ul> <li>图片数据量大,运算量大,例如一个200*200像素的彩色图片:200*200*3=120,000</li> <li>卷积神经网络能模拟人类的视觉处理流程,高效提取特征</li> </ul> <h4>卷积神经网络的结构</h4> <h5>卷积层</h5> <ul> <li><a>image kernels网站了解图像卷积核</a></li> <li>图像卷积核是一个小的矩阵,用于施加一些效果,例如在Photoshop中可能会看到的效果,例如模糊,锐化,勾勒出轮廓或压花。它们还用于机器学习中的“特征提取”,这是一种确定图像最重要部分的技术。在这种情况下,该过程通常被称为“卷积”</li> <li><img src="/images/ai/59.png" alt="卷积" /></li> <li>图片上的3X3的小矩阵,就是用于卷积以提取图像特征的<strong>图像卷积核</strong></li> <li>使用多个卷积核(filter/kernel)对图像进行卷积操作,提取多种特征并组合</li> <li><strong>卷积层</strong>有权重,需要训练,其权重就是<strong>卷积核</strong></li> </ul> <h5>池化层</h5> <ul> <li>优化层</li> <li>最大池化层用于提取<strong>最强的特征</strong></li> <li>扩大感受视野,减少计算量</li> <li>池化层是固定的,不需要训练</li> </ul> <h5>dense全链接层</h5> <ul> <li>作为输出层</li> <li>作为分类器</li> <li>有权重,需要训练</li> </ul> <h2>构建卷积神经网络代码</h2> <pre><code>const model = tf.sequential(); //添加一个二位卷积层 model.add( tf.layers.conv2d({ inputShape: [28, 28, 1], kernelSize: 5, //卷积核的大小是5X5的矩阵 filters: 8, //应用8种图像卷积核 strides: 1, //移动步长,每一个像素单元都进行卷积操作 activation: "relu", //激活函数,移除掉无用的特征(特征&lt;0就废弃 kernelInitializer: "varianceScaling", //可以不设置,设置了可以加快收敛速度 }), ); //最大池化层 model.add( tf.layers.maxPool2d({ poolSize: [2, 2], //尺寸是2X2 strides: [2, 2], //移动步长,每隔两个像素单元进行一次卷积操作 }), ); // 重复上述两个层 model.add( tf.layers.conv2d({ kernelSize: 5, filters: 16, //需要提取更多特征 strides: 1, activation: "relu", kernelInitializer: "varianceScaling", }), ); model.add( tf.layers.maxPool2d({ poolSize: [2, 2], strides: [2, 2], }), ); //flatten层用于将多维的特征数据,转换为一维的分类数据,传入dense层 model.add(tf.layers.flatten()); model.add( tf.layers.dense({ units: 10, //最终输出0-9十个分类 activation: "softmax", kernelInitializer: "varianceScaling", }), ); </code></pre> <h2>训练模型</h2> <pre><code>//训练参数 model.compile({ loss: "categoricalCrossentropy", //交叉熵损失函数 optimizer: tf.train.adam(), //优化器 metrics: ["accuracy"], //准确度度量 }); //训练集数据 const [trainXs, trainYs] = tf.tidy(() =&gt; { const d = data.nextTrainBatch(1000); return [d.xs.reshape([1000, 28, 28, 1]), d.labels]; }); //验证集数据 const [testXs, testYs] = tf.tidy(() =&gt; { const d = data.nextTestBatch(200); return [d.xs.reshape([200, 28, 28, 1]), d.labels]; }); //训练 await model.fit(trainXs, trainYs, { validationData: [testXs, testYs], batchSize: 500, epochs: 50, callbacks: tfvis.show.fitCallbacks( { name: "训练效果" }, ["loss", "val_loss", "acc", "val_acc"], { callbacks: ["onEpochEnd"] }, ), }); </code></pre> <ul> <li>训练效果: <img src="/images/ai/60.png" alt="卷积训练" /></li> </ul> <h2>使用模型预测识别canvas绘制数字</h2> <ul> <li>html:</li> </ul> <pre><code>&lt;script src="script.js"&gt;&lt;/script&gt; &lt;canvas width="300" height="300" style="border: 2px solid #666;"&gt;&lt;/canvas&gt; &lt;br&gt; &lt;button onclick="window.clear();" style="margin: 4px;"&gt;清除&lt;/button&gt; &lt;button onclick="window.predict();" style="margin: 4px;"&gt;预测&lt;/button&gt; </code></pre> <ul> <li>js:</li> </ul> <pre><code>const canvas = document.querySelector("canvas"); canvas.addEventListener("mousemove", (e) =&gt; { if (e.buttons === 1) { const ctx = canvas.getContext("2d"); ctx.fillStyle = "rgb(255,255,255)"; ctx.fillRect(e.offsetX, e.offsetY, 25, 25); } }); //黑底画板 window.clear = () =&gt; { const ctx = canvas.getContext("2d"); ctx.fillStyle = "rgb(0,0,0)"; ctx.fillRect(0, 0, 300, 300); }; clear(); </code></pre> <ul> <li>进行预测:</li> </ul> <pre><code>window.predict = () =&gt; { const input = tf.tidy(() =&gt; { return tf.image .resizeBilinear( //转换图像tensor尺寸 tf.browser.fromPixels(canvas), //canvas转换为tensor [28, 28], //转换成28*28 true, ) .slice([0, 0, 0], [28, 28, 1]) //canvas图片是彩色图片,通过slice转换为黑白图片 .toFloat() //训练数据进行过归一化,因此预测值也要归一化 .div(255) //归一化 .reshape([1, 28, 28, 1]); //和神经网络第一层的输入格式统一 }); const pred = model.predict(input).argMax(1); alert(`预测结果为 ${pred.dataSync()[0]}`); }; </code></pre> <p><img src="/images/picgo/001.gif" alt="预测效果" /></p> <hr /> <p>&lt;small&gt;总结:这一节有两个难点,一是卷积神经网络的构建,重在理解图像卷积核;二是图像与tensor格式的转换,需要多加练习与斟酌;&lt;br/&gt; 本地训练结果正确率大概70%,可以通过增加训练集数据和训练次数来提升效果&lt;/small&gt;</p> <hr /> <p><a>代码仓库</a></p> 前端https://www.scarsu.com/fed_ml_10_handwriting_number/#post-comment/ML09 | 欠拟合&过拟合https://www.scarsu.com/fed_ml_09_underoverfitting/https://www.scarsu.com/fed_ml_09_underoverfitting/Javascript玩转机器学习09Fri, 24 Apr 2020 00:00:00 GMT<h2>欠拟合</h2> <ul> <li>数据过于复杂,但是神经网络模型过于简单</li> </ul> <p><img src="/images/ai/47.png" alt="underFitting" /></p> <ul> <li>无论训练多久,训练损失始终降不下去</li> </ul> <p><img src="/images/ai/46.png" alt="underFitting" /></p> <h2>过拟合</h2> <ul> <li>模型过于复杂,把训练集噪声数据都拟合进去</li> </ul> <p><img src="/images/ai/48.png" alt="overFitting" /></p> <ul> <li>过拟合损失曲线,红色代表验证集,蓝色代表训练集</li> </ul> <p><img src="/images/ai/49.png" alt="overFitting" /></p> <p><img src="/images/ai/50.png" alt="overFitting" /></p> <h2>实操模拟 欠拟合&amp;过拟合</h2> <ul> <li>加载带有噪音的二分类数据集(训练集与验证集)</li> <li>使用不同神经网络演示 过拟合&amp;欠拟合</li> <li>过拟合应对法:早停法、权重衰减、丢弃法</li> </ul> <h2>加载带有噪音的二分类数据集(训练集与验证集)</h2> <h4>脚本原理</h4> <p>生成正态分布(高斯分布)的样本数据</p> <pre><code>function normalRandom(mean = 0, variance = 1) { let v1, v2, s; do { v1 = 2 * Math.random() - 1; v2 = 2 * Math.random() - 1; s = v1 * v1 + v2 * v2; } while (s &gt; 1); let result = Math.sqrt((-2 * Math.log(s)) / s) * v1; return mean + Math.sqrt(variance) * result; } </code></pre> <p>正态分布两边低的数据看作噪音数据,中间高的数据视为正常数据</p> <p>通过调整方差 调整噪音量</p> <h4>用脚本生成带有噪音的二分类数据集</h4> <pre><code>import * as tf from "@tensorflow/tfjs"; import * as tfvis from "@tensorflow/tfjs-vis"; import { getData } from "./data"; window.onload = async () =&gt; { const data = getData(200, 3); }; </code></pre> <h4>可视化数据集</h4> <pre><code>tfvis.render.scatterplot( { name: "训练数据" }, { values: [ data.filter((p) =&gt; p.label === 1), data.filter((p) =&gt; p.label === 0), ], }, ); </code></pre> <p><img src="/images/ai/51.png" alt="可视化结果" /></p> <h2>使用不同神经网络演示 过拟合</h2> <pre><code>const data = getData(200, 2); tfvis.render.scatterplot( { name: "训练数据" }, { values: [ data.filter((p) =&gt; p.label === 1), data.filter((p) =&gt; p.label === 0), ], }, ); const model = tf.sequential(); //第一层隐藏层 model.add( tf.layers.dense({ units: 10, inputShape: [2], //长度为2的一维数组 activation: "tanh", }), ); //输出层 model.add( tf.layers.dense({ units: 1, activation: "sigmoid", }), ); //设置损失函数&amp;优化器 model.compile({ loss: tf.losses.logLoss, optimizer: tf.train.adam(0.1), }); const inputs = tf.tensor(data.map((p) =&gt; [p.x, p.y])); const labels = tf.tensor(data.map((p) =&gt; p.label)); await model.fit(inputs, labels, { validationSplit: 0.2, epochs: 200, callbacks: tfvis.show.fitCallbacks( { name: "训练效果" }, ["loss", "val_loss"], { callbacks: ["onEpochEnd"] }, ), }); </code></pre> <p><img src="/images/ai/52.png" alt="过拟合训练结果" /></p> <h2>过拟合应对法:早停法</h2> <p>在训练出现过拟合时及时手动停止训练</p> <h2>过拟合应对法:权重衰减法(设置L2正则化</h2> <p>将过于复杂的模型权重降低</p> <pre><code>model.add( tf.layers.dense({ units: 10, inputShape: [2], //长度为2的一维数组 activation: "tanh", kernelRegularizer: tf.regularizers.l2({ l2: 1 }), //设置权重衰减 }), ); </code></pre> <p><img src="/images/ai/54.png" alt="权重衰减法训练结果" /></p> <h2>过拟合应对法:丢弃法</h2> <p>在隐藏层和输出层之间添加一个丢弃层</p> <pre><code>//添加丢弃层,降低训练集复杂度 model.add(tf.layers.dropout({ rate: 0.9 })); </code></pre> <p><img src="/images/ai/53.png" alt="丢弃法训练结果" /></p> <hr /> <p><a>代码仓库</a></p> 前端https://www.scarsu.com/fed_ml_09_underoverfitting/#post-comment/Notion为什么能让我放弃手帐https://www.scarsu.com/e_journal_by_notion/https://www.scarsu.com/e_journal_by_notion/自我管理,记录,自省,用意识控制生活,而非本能Sun, 12 Apr 2020 00:00:00 GMT<p>今天在逛今日热榜的时候,看到了一篇知乎的文章<a>“我的最后一款笔记应用-Notion”</a>,是种草notion的。</p> <p><img src="/images/notion/header.png" alt="Notion/header.png" /></p> <p>一两年前notion刚火的时候,因为被其极简可爱的颜值吸引,我试用过一次,那时候我已经是“有道云笔记”的深度用户了,备份类、笔记类、小应用类、电子书类、代码类全都放在有道云笔记上,开了年会员加持,容量大、网速稳定、体验感功能性都没有缺陷,觉得notion仅仅适合做笔记、做管理,并不适合我从有道云笔记转型,而且刚刚起步的产品,还有这很多细节上体验不好的地方。</p> <p>直到今天,notion这款应用又重新进入我的视野,我被吸引了。</p> <p>原因是,近两年来,我一直在尝试用<a>手帐</a>的方式去做自我管理:每年都要换本子,重新set up年目标、年总结、影单、书单、学习路径、愿望清单、资产、习惯、体重等等的追踪记录,每个月也要做set up的工作,包括月封面、月历、周历、每日记录......</p> <p>即使中间我从普通手帐,转型到了最简洁的Bullet Journal,差别也仅仅是风格变成了极简,不需要花哨的涂涂画画,但也需要耗时耗精力的精心维护,花了很多时间在重复的工作:重复的画track表格、画年历月历、每年新建一些需要长期维护的项目(例如愿望清单、书单影单都不适合以年为维度记录,我更倾向于认为这些是需要以人生为维度去记录积累的),还需要每天带着一堆文具和厚厚的一个本子。</p> <p>低效、冗余、耗精力这些弊端都一直是我的心头草,仅仅是靠着对手帐的兴趣才维持了两年时间。</p> <p>两年后再接触到notion,又有了新的体验,这两年notion团队做出了卓越的努力,不断的优化更新,让当初新露头角毛毛糙糙的notion,在用户体验上有了华丽变身,更细致,更贴近用户,客户端也全端兼容了。</p> <p>当然,对于我来说,notion的亮点不光在于颜值和用户体验,更重要的,是它的“模块化”的思想,设计新颖又实用的“数据库”模式,文档(Notion Page)之间的灵活链接,以及对<strong>markdown</strong>的友好支持。</p> <p>模块化思想,把整个文档拆分成“块”(block),可以随意拖动排版,所有“块”都支持30多种媒体类型,包括文字、标题、多种list、文档链接(Notion Page)、团队成员、日期/提醒、图片视频、地图、Github Gist片段、数据库链接等等,这些特性让Notion既灵活又功能丰富。</p> <p>数据库模式,可以在一张数据表上保留所有数据记录。以表格、看板、画廊、日历等视图展现,一次创建,多处引用。例如创建一张待办事项表,就可以通过简单的引用数据表+新增视图+筛选,展现出“今日待办事项、团队协作看板、待办日历”等视图。例如创建一张财务收支表,可以展现出“年收入支出、月收入支出、支出类别占比”等视图,这些特性让Notion既高效又细致入微。举个栗子:以下的三张表其实都是同一张数据源。</p> <p><img src="/images/notion/ds.png" alt="Notion/数据库模式" /></p> <p>页面之间的灵活链接,使Notion跳出了“以文件夹格式逐层管理“的固定模式,用户完全可以创建一张灵活排布的目录Page,任意设计分类、排版、跳转。例如我的手帐主页:</p> <p><img src="/images/notion/home.png" alt="Notion/页面灵活排版" /></p> <hr /> <p>最后,我的示例和观点,只展示出了星星点点的用法,还有更多有意思的用法,等待开发~</p> <p>这是我的<a>邀请链接</a>,欢迎注册使用Notion</p> <hr /> <p>注:关于手账的意义:</p> <ul> <li>自我管理,自我规划,自律</li> <li>记录、温习回忆</li> <li>自省</li> <li>记录、调节情绪,解压</li> <li>用意识控制生活,而非本能</li> </ul> 个人成长https://www.scarsu.com/e_journal_by_notion/#post-comment/Devtools 老司机养成 - 番外篇 - Devtools中的”VM“https://www.scarsu.com/vm_in_devtools/https://www.scarsu.com/vm_in_devtools/为什么经常有脚本的“文件名”是"[VM](XXXX "??Mon, 06 Apr 2020 00:00:00 GMT<h2>引言</h2> <p>What are those strange and mysterious scripts titled "[VM](XXXX " and where do they come from?</p> <h2>what's vm(xxxx)</h2> <p><a>VM</a> has no special meaning. It's a dummy name to help us to distinguish code which are not directly tied to a file name, such as code created using eval and friends.</p> <p>为了标识不能和具体文件直接关联的脚本的虚拟名称,并不是真正的文件,例如 eval 方法所执行的脚本、匿名函数,脚本会被抛入Chrome调试器虚拟机中</p> 前端https://www.scarsu.com/vm_in_devtools/#post-comment/Devtools 老司机养成 - 第七篇- Memory 内存https://www.scarsu.com/devtools_07_memory/https://www.scarsu.com/devtools_07_memory/你开的网页会卡吗?来Memory面板了解一下内存分析&内存泄漏Sun, 05 Apr 2020 00:00:00 GMT<h2>内存 &amp;&amp; 内存泄露</h2> <p>内存占用:</p> <ol> <li>allocate 分配内存(eg 声明变量</li> <li>使用内存</li> <li>release 释放内存</li> </ol> <p>内存泄漏:</p> <ul> <li><code>内存泄露-Memory Leak</code>:内存被占用后无法被 release,且无法被垃圾回收器回收</li> <li>内存泄漏会引起性能问题,且时间越久越严重,因为被占用且无法回收的内存只会增加不会减少</li> <li><code>垃圾回收-Garbage Collect-GC</code>:浏览器收回内存。 浏览器决定何时进行垃圾回收。 回收期间,所有脚本执行都将暂停。因此,如果浏览器经常进行垃圾回收,脚本执行就会被频繁暂停</li> </ul> <h2>造成内存泄露常见原因</h2> <ul> <li><code>fogotten timer</code>被遗忘的计时器:例如调用 setInterval()方法一定要加结束条件</li> <li><code>Dettached HTMLElement</code>分离的 dom 节点:在 dom 被移除后,dom 变量仍然存在</li> </ul> <h2>内存监控 1-Task manager 任务管理器</h2> <ul> <li>chorme 浏览器 -&gt; task manager 任务管理器工具中,可以监控每个 tab 页的 js 内存占用大小</li> </ul> <p><img src="https://i.loli.net/2019/05/07/5cd194ba3a655.png" alt="" /></p> <ul> <li><code>Memory</code> 列表示原生内存。DOM 节点存储在原生内存中。 如果此值正在增大,则说明正在创建 DOM 节点。</li> <li><code>JavaScript Memory</code>列表示 JS 堆。此列包含两个值。 实际大小表示页面上的对象正在使用的内存量。 如果此数字在增大,要么是正在创建新对象,要么是现有对象正在增长。</li> </ul> <h2>内存监控 2-Devtools Performance 面板</h2> <ul> <li>在<code>Performance</code>面板记录性能时,勾选<code>memory</code>即可在分析结果中看到 memory 占用情况</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccee6f4b968d.png" alt="" /></p> <pre><code>//示例1:正常的内存占用与GC var x = []; function grow() { for (var i = 0; i &lt; 10000; i++) { document.body.appendChild(document.createElement("div")); } x.push(new Array(1000000).join("x")); } setInterval(grow, 100); </code></pre> <p><img src="https://i.loli.net/2019/05/07/5cd19db41fbbc.png" alt="" /></p> <pre><code>//示例2:不可被GC的内存泄漏 function grow() { // for (var i = 0; i &lt; 10000; i++) { // document.body.appendChild(document.createElement("div")); // } // x.push(new Array(1000000).join("x")); var ul = document.createElement("ul"); for (var i = 0; i &lt; 10; i++) { var li = document.createElement("li"); ul.appendChild(li); } detachedTree = ul; } setInterval(grow, 1000); </code></pre> <p><img src="https://i.loli.net/2019/05/07/5cd1a62aa1bfd.png" alt="" /></p> <h2>内存监控 3-Devtools Memory 面板</h2> <p><img src="https://i.loli.net/2019/05/07/5cd18fa5d8489.png" alt="" /></p> <ul> <li>如上图所示,在右侧三种内存分析模式选择一种后,即可点击左上角<code>record</code>开始记录内存</li> </ul> <ol> <li><code>Heap snapshot</code>堆快照,记录当前时间点内存中页面 js 对象和 dom 节点的分配情况</li> <li><code>Allocation instrumentation on timeline</code>按时间轴记录内存,可以选记录内存分配调用栈(可以帮助定位到具体分配内存的源码)</li> <li><code>Allocation sampling</code>使用抽样方法记录内存分配。具有最小的性能开销,可用于长时间运行的操作。提供了由 JavaScript 执行堆栈细分的良好近似分配。</li> </ol> <ul> <li> <p>左上角的垃圾桶图标<code>Collect garbage</code>是强制执行一次垃圾回收,内存监控的最佳实践是在监控内存前执行一次强制垃圾回收</p> </li> <li> <p>利用上述示例 2 代码,执行时间线 Memory 分析:</p> </li> </ul> <p><img src="https://i.loli.net/2019/05/07/5cd1a7db0cfe0.png" alt="" /></p> <h2>扩展</h2> <ul> <li><a>内存相关术语</a></li> <li><a>深入内存分析</a></li> </ul> 前端https://www.scarsu.com/devtools_07_memory/#post-comment/Devtools 老司机养成 - 第六篇 Performance 性能面板https://www.scarsu.com/devtools_06_performance/https://www.scarsu.com/devtools_06_performance/中高级前端都应该懂的性能分析&优化,都在Performance面板Sun, 29 Mar 2020 00:00:00 GMT<h2>Performance面板概览</h2> <ul> <li>performance 面板可以用于分析<code>运行时性能</code>(运行时强调的是与页面加载性能相区分)</li> <li>以隐身模式打开网页 (隐身模式可确保 Chrome 以干净的状态运行。例如,排除扩展对性能测量的影响</li> <li><a>Junky Animation demo :性能测试 demo</a></li> <li>视图 overview:</li> </ul> <p><img src="https://i.loli.net/2019/04/23/5cbf1d586fe21.png" alt="performance.png" /></p> <h2>RAIL 模型</h2> <ul> <li> <p><a>RAIL 模型</a>是一种性能模型,定义了四个维度的性能分析指标</p> </li> <li> <p><code>Response</code>:在<code>100 毫秒</code>以内响应(例如从点按到绘制)</p> </li> <li> <p><code>Animation</code>: 每秒生成 60 帧,每个帧的工作(从 JS 到绘制)完成时间小于 16 毫秒,达到人眼顺滑(例如滚动 拖动都是动画类型)(因为浏览器需要花费时间将新帧绘制到屏幕上,只有 <code>10 毫秒</code>来执行代码)</p> </li> <li> <p><code>Idle</code>:利用空闲时间完成推迟的工作(要实现第一条 response 在 100ms 内响应,Main 主线程 JS 工作应该小于 <code>50ms</code>,剩余的时间将主线程的控制从 js 返回给浏览器执行其像素管道、对用户输入作出反应等,因此最佳实践是将 js 的工作分成不大于 50 毫秒的块,如果用户开始交互,优先级最高的事项是响应用户。</p> </li> <li> <p><code>Load</code>:在 <code>1000 毫秒</code>以内呈现内容(无需完整加载,启用渐进式渲染,将非必需的加载推迟到空闲时间段</p> </li> <li> <p>通过 performance 面板,可以得到这四个维度的分析数据</p> </li> </ul> <h2>控制区</h2> <p><img src="https://i.loli.net/2019/05/01/5cc9642fa35b5.png" alt="" /></p> <ul> <li>点击<code>录制按钮</code>或者<code>开始录制并刷新页面按钮</code>,可以在控制区下方得到全部性能分析结果</li> <li>其中除了最下方的详细信息窗格以外,分析结果都是以时间为轴</li> <li>可以在 overview 窗格拖动鼠标,选择某段时间的分析结果</li> <li>滚动鼠标滚轮,缩放/移动选中事件</li> <li>在火焰图窗格,按住<code>shift</code>,滚动鼠标滚轮,可以上下</li> <li>在火焰图窗格,也可以直接左右拖动图表</li> <li>或者用<code>W A S D</code>按键控制缩放移动</li> <li><code>Disable JavaScript samples</code>默认情况,在<code>Main</code>主线程的火焰图中,会详细记录 js 函数之间的调用栈,可以开启此选项禁用调用栈记录</li> <li><code>Enable advanced paint instrumentation</code>启用高级绘图工具,可以在分析结果的<code>Frames</code>中的每一帧的详细结果中看到<code>Layer</code>选项卡,其中有选中帧的详细图层信息;也可以在<code>Main</code>主线程火焰图中选中绿色的<code>Paint</code>事件,在最底部详细信息的<code>Paint Profile</code>选项卡中,看到详细的页面绘制过程分析</li> <li><code>Collect garbage</code>控制器最右的垃圾桶图标,是强制执行垃圾回收,对于监控内存比较有用</li> </ul> <h2>FPS 图表 - Frames Per Seconds</h2> <p><img src="https://i.loli.net/2019/05/05/5ccee0f3335be.png" alt="" /></p> <ul> <li>FPS 图表中,绿色代表帧率高低,参考<code>RAIL</code>模型,帧率&gt;=60 时,用户能体验的顺滑的网页</li> <li>红色出现 代表有掉帧情况</li> </ul> <h2>CPU 图表</h2> <p><img src="https://i.loli.net/2019/05/05/5ccee13cd4479.png" alt="" /></p> <ul> <li>CPU 图表中,不同的颜色代表不同事件对 CPU 的占用,颜色信息如图</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccee05903554.png" alt="" /></p> <ul> <li>当 CPU 长时间被占满,就是当前网页性能需要优化的信号</li> </ul> <h2>SCREENSHOTS</h2> <ul> <li>鼠标在<code>FPS,CPU,NET</code>图表悬浮时,会展示出鼠标对应时间点的网页截屏,左右移动鼠标可以看到网页变化的重播效果</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccee37b9a4b3.gif" alt="" /></p> <h2>HEAP</h2> <p><img src="https://i.loli.net/2019/05/05/5ccee6f4b968d.png" alt="" /></p> <ul> <li>在 HEAP 图表中可以看到 JS 内存占用情况,与下方的 memory 窗格中的<code>JS Heap</code>相对应</li> <li>在 Memory 窗格还可以看到 Document 文档、Nodes DOM 节点、监听器、GPU 内存的习份内存统计</li> </ul> <h2>Frames</h2> <ul> <li>点击三角箭头展开<code>Frames</code>区域,鼠标悬浮/点击绿色方块,可以看到该特定帧的帧率和渲染耗时,当 FPS 低于 60,表明当前帧的渲染效率较低</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccee92a52b29.png" alt="" /></p> <h2>FPS 仪表工具</h2> <ul> <li>通过<code>more -&gt; more tools -&gt; Rendering</code> 或者 <code>ctrl+shift+p -&gt; rendering</code> 打开<code>Rendering</code>面板</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccee9d226d2e.png" alt="" /></p> <ul> <li>启用<code>FPS meter</code>,即可看到的页面实时帧率</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5cceeb3144e12.gif" alt="" /></p> <h2>Mian</h2> <ul> <li>点击三角箭头展开<code>Main</code>区域,可以看到主线程上事件的<code>火焰图</code></li> <li>x 轴是时间,每一块代表一个事件,y 轴代表堆栈,事件的上下堆叠,代表上层事件引发/调用了下层事件</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5cceec8b11f7f.png" alt="" /></p> <ul> <li>通过调用堆栈,可以找出导致低性能的事件及其源码位置</li> <li>当事件块出现红色三角,可以点击三角查看该事件的性能相关警告信息,并定位到引起警告的代码</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5cceef6801439.png" alt="" /></p> <p><img src="https://i.loli.net/2019/05/05/5ccef1a7c2c2a.gif" alt="" /></p> <ul> <li>点击<code>Animation Frame Fired</code>事件,可以在最下方<code>Summary</code>窗格查看触发动画事件的详细信息,点击<code>Initiator</code>后的<code>reveal</code>链接,会高亮到引起动画事件的事件</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccef012a3dba.gif" alt="" /></p> <h2>性能相关扩展</h2> <ul> <li><a>网页性能-性能模型/加载/渲染/审计/优化</a></li> <li><a>the-anatomy-of-a-frame - 一个帧的剖析</a></li> <li><a>常见的时间线事件参考</a></li> </ul> <h2>浏览器并发请求数</h2> <ul> <li> <p>现象: 同一时间针对同一域名下的请求有一定数量限制。超过限制数目的请求会被阻塞。</p> </li> <li> <p>原因: 基于端口数量和线程切换开销的考虑,浏览器不可能无限量的并发请求。</p> </li> <li> <p>导致: 有大量请求的站点,响应较慢,因为并发请求会被阻塞。</p> </li> <li> <p><img src="https://i.loli.net/2019/07/29/5d3e56236ee0b54748.png" alt="不同浏览器的限制数" /></p> </li> <li> <p>解决方法:</p> <ol> <li> <p>用不同域名(hash domain,cookie free) 例如知乎的图片都是放在zhiimg.com域名下获取的。 cookie free是指,例如知乎主站zhihu.com域名下有很多cookie,换成zhihuimg.com请求图片时,就不会把zhihu上的cookie发过去,减小所需带宽。</p> </li> <li> <p>减少请求数 雪碧图 合并压缩css/js(另一个原因是为了减少重绘) 利用Cache-Control等缓存静态资源,在更新静态资源时使用不同url或文件名带上版本 懒加载,出现再加载</p> </li> </ol> </li> </ul> 前端https://www.scarsu.com/devtools_06_performance/#post-comment/别做正常的傻瓜:让你的每一个行为都得到最优解https://www.scarsu.com/behavior_decision/https://www.scarsu.com/behavior_decision/豆瓣8.1的行为决策学入门书籍,通过心理学原理、一些实验数据,指出了常人的一些决策误区,以及如何达到决策理性,让你的每一个行为都得到最优解。Fri, 27 Mar 2020 00:00:00 GMT<p><img src="//images/picgo/behavior.jpg" alt="题图" /></p> <h2>简介</h2> <p>作者:奚恺元(Christopher K.Hsee)生长于中国上海,后旅美求学,1993年获耶鲁大学博士学位,现为芝加哥大学商学院终身教授(chair professor)。</p> <p>他是当代最有成就的行为决策学研究者之一,其研究涉及心理学、行为经济学,管理学、市场学以及幸福学等诸多领域。</p> <p>他的著作在许多国际期刊上发表,2002年诺贝尔经济学奖得主卡尼曼教授在他的获奖致辞中还特别提到了奚教授的研究贡献。</p> <p>在北美和中国,他被许多一流大学邀请做过演讲。并广受好评,奚教授有十多年的管理教学经验,他在芝加哥大学开设的管理决策课程备受欢迎。</p> <p>这本书是<a>豆瓣8.1</a>的<strong>行为决策学</strong>入门书籍。</p> <p>通过心理学原理、一些实验数据,指出了常人会犯的一些决策错误,以及如何达到决策理性,让你的每一个行为都得到最优解。</p> <h2>TL; DR —— 先看总结</h2> <p>这是我从3月28号开始,用了接近两个月时间看完的一本书。</p> <p>总体来说,这本书并没有很强的系统性,不需要建立知识体系,比较适合<strong>碎片阅读</strong>。</p> <p>书中十几章内容,分别介绍了不同的决策误区,误区产生背后的心理学原理,以及如何应对。</p> <p>书中介绍的一些理论,比如<strong>人类心理账户及其对行为的影响</strong>、<strong>消费决策只应该考虑<code>成本=&gt;价值</code></strong>、<strong>边际递减效应</strong>、<strong>适应性偏见</strong>、<strong>第一印象相关的定位偏见</strong>、<strong>联合评估与单独评估的选择</strong>...都能对实际生活中的决策起到实际性的、可行的理论指导。</p> <p>书中介绍的决策误区,都是<strong>常人会有</strong>的,因为从原理上来看,是人类的<strong>本性使然</strong>。</p> <p>但是如果能了解这些误区,知道自己可能犯的错误,就能及时的检视自己,从而做出更多理性的决策。</p> <p>所以总结来说,这本书还是值得一看的✨。</p> <h2>1. 10元等于两个5元吗? —— <strong>心理账户&amp;决策一致性</strong></h2> <ul> <li> <p>心理账户对行为的影响 在我们的日常生活中,经常需要做各种各样的决策,在做决策的时候,我们总是为求做到理性,以尽可能地使我们的收益最大化。如何成为一名理性的决策者呢?一名理性的决策者究竟需要具备怎样的基本素质呢?</p> </li> <li> <p>由于心理账户的存在,正常人常有一些误区:</p> <ol> <li>将等价的钱,根据来源/时间/用途不同,打上不同标记</li> <li>赌场盈利效应:赢来的钱更倾向于高风险投资</li> <li>把赢来的钱消费掉,把赚来的钱存起来</li> <li>大钱小花,小钱大花</li> </ol> </li> <li> <p>心理账户,导致了行为决策不具有一致性</p> </li> <li> <p>应该:让钱在不同心理账户之间流通</p> </li> <li> <p>应该:等价的钱,不因为来源/时间/用途不同而打上不同标记</p> </li> </ul> <h2>2. 你会买没用的东西吗? —— <strong>消费决策的误区</strong></h2> <ul> <li>消费决策中常见的误区 我们购买一样东西,衡量是该物品给我们带来的效用和它的价格,然后看是不是值得购买,可是在我们做购买决策的时候,往往会受到交易效用偏见、比例偏见和适应偏见的影响,从而做出不理性的消费决策行为。</li> <li>做交易决策的无关参考值: <ul> <li>参考价-实际价格</li> <li>优惠比例</li> <li>历史促销价格</li> </ul> </li> <li>做决策,不应受到<strong>成本-&gt;价值</strong>外的其他任何因素影响</li> <li>不因为成本过高而不买有价值的东西,也不因为成本低而买不需要的东西</li> </ul> <h2>3. 坚持到底一定是胜利吗? —— <strong>沉没成本</strong></h2> <ul> <li><strong>沉没成本</strong>:已经无法收回的支出</li> <li>沉没成本误区 人们在决定是否去做一件事的时候,不仅是看这件事对自己有没有好处,而且也看过去已经在这件事情上面有过投入,很多人去挽回已经发生却无法挽回的所谓的成本而做出很多不理性的行为。</li> <li>应该<strong>及时止损</strong></li> <li>应该根据<strong>将来会不会有好处</strong>做决策</li> <li>不让沉没成本困住前进的步伐</li> <li><strong>保本</strong>是错误观念</li> </ul> <h2>4. 你有自知之明吗? —— <strong>过于自信与自知</strong></h2> <blockquote> <p>知人者智,知己者明</p> </blockquote> <ul> <li>绝大多数人,都有过于自信的问题,很多时候,人们并不如自己想象的那么优秀。</li> <li>做出好的决策,不光要有知识,还要有“知识的知识”,也就是自知:知道自己的知识有哪些局限,哪些是准确的,哪些的需要质疑的</li> <li><strong>证实偏见</strong>:为自己的观点找理由,只关注自己观点一致的证据,不关注不收集与自己决策相对立的证据</li> <li>过于自信的一个例子:<strong>不上相</strong>,潜台词就是“我本人长得很美丽,只是照片没有把这些体现出来”,但是事实上,照片是真实的,你本人就是和照片上一样丑</li> </ul> <p>过于自信的优点:</p> <ul> <li>使人积极开心</li> <li>产生“自我实现预言”效应,即产生良性的心理暗示,引导好的结果</li> <li>过于自信的人,不会太拘泥于细节,善于抓住问题的大方向</li> </ul> <p>过于自信的缺点:</p> <ul> <li>规划误区:过于自信,对问题或任务轻视,导致延期等规划不合理的问题</li> <li>对自己的金融知识与判断过于自信会导致在金融市场过于频繁交易(越频繁交易,损失越大</li> <li>打无准备之仗,松懈,持侥幸心理</li> </ul> <p>应该怎么做:</p> <ul> <li>避免证实偏见,为自己决策的对立面寻找证据,两相比较</li> </ul> <h2>5. 你会习以为常吗?—— <strong>适应性偏见</strong></h2> <ul> <li><strong>适应性</strong>:人类对外界的刺激,会随着时间的推移而减弱。(是普遍存在的现象</li> <li><strong>适应性偏见</strong>:人类<strong>低估</strong>自己的适应性,从而高估某些事情在一段时间后对自己的影响。</li> <li><strong>适应性偏见例子</strong>:人类以为物质条件的提升,会给自己带来长久的快乐,但其实很快就会适应。</li> </ul> <p><strong>三类难以适应的东西</strong>:</p> <ul> <li>极端的东西</li> <li>人际比较</li> <li>变化</li> </ul> <p><strong>如何对待适应性偏见</strong>:</p> <ul> <li>了解自己对物质性东西的适应性</li> <li>不要对物质看得过重,有过高期望</li> <li>多关注精神和心灵层面的东西</li> </ul> <h2>6. 存银行还是买股票? —— <strong>风险决策</strong></h2> <p><strong>数学期望值</strong> = 选项的价值✖选项的概率</p> <p><strong>期望值理论</strong>:做决策时,选期望值最大的选项</p> <ul> <li><strong>风险中性</strong>:期望值相同的情况,对风险大小无所谓</li> <li><strong>风险规避</strong>:期望值相同的情况,偏好于风险小收益小</li> <li><strong>风险喜好</strong>:期望值相同的情况,偏好与风险大收益大</li> </ul> <p><strong>效用</strong>:指消费者从某商品中得到的满足感(主管衡量)</p> <p><strong>边际效用递减</strong>:一种普遍规律,随消费的增多,消费者从每个单位产品的消费中得到的<strong>效用</strong>逐渐递减。(与上一章所讲的适应性有一定关联)</p> <p><strong>风险规避</strong>与<strong>边际效用递减</strong>:边际效用递减是风险规避的理论依据</p> <p><strong>期望效用理论</strong>:</p> <ul> <li>选择效用最大的选项</li> <li>计算方法:某选项的<strong>效用</strong> ✖ 概率</li> <li>效用的计算:由于边际递减规律,其计算可以选择求根函数,把选项的价值作为参数</li> </ul> <p><strong>前景理论</strong>:最贴合现实中人类的选择</p> <ul> <li>在<strong>得到</strong>时,倾向于风险规避</li> <li>在<strong>失去</strong>时,倾向于风险喜好</li> <li>参照点的不同,会影响人类对于<strong>得失</strong>的判断</li> <li>通常遵循:损失规避(下一章会讲到)</li> </ul> <p>三种风险决策的理论依据:</p> <ul> <li>期望值理论(由于边际效用递减而不准确)</li> <li>期望效用理论(最为理性)</li> <li>前景理论(最贴近现实中人类的风险决策的理论)</li> </ul> <h2>7. 损失100元和得到100元,哪个对你影响更大? —— <strong>损失规避</strong></h2> <p><strong>损失规避</strong>:同样的东西,失去它所经历的痛苦程度,大于得到它所经历的高兴程度:|U(-x)|&gt;&gt;|U(x)|(得失不对称性)</p> <p><strong>投资决策的两个心理账户问题</strong>:</p> <ul> <li>短时间内评价一个账户的盈亏(不要频繁查看投资账户)</li> <li>把股票账面上的损失,和股票下跌变现的损失,划分到不同的心理账户</li> </ul> <p><strong>赋予效应</strong>: 同样的东西,得到时觉得不值钱,拥有了再放弃时就会感到其重要性(eg.无条件退款的营销策略就是利用了这个效应)</p> <p><strong>安于现状</strong>: 由于赋予效应,人们把现在拥有的东西加上了很高的价值,不愿意做决策去改变现状</p> <p><strong>语义效应</strong>: 用不同语义描述同一件事时,就会做出不同的决策,把一件事描述成“得”或“失”,可以有效的改变人们的选择</p> <h2>8. 损失100元和没有得到100元,那个让你更心痛? —— <strong>未得收益</strong></h2> <ul> <li>未得收益和直接损失,从理性的角度来看是一样的,未得收益应该得到重视</li> <li>盗版知识产品=&gt;也是对知识产权所有者未得收益的损害</li> </ul> <h2>9. 谈判中应该让对方先开价吗? —— <strong>定位调整偏见</strong></h2> <ul> <li><strong>定位效应</strong>:你对某人某事的<strong>第一印象</strong>就是一种可以定位的 <strong>“锚”(anchor)</strong>,一旦定下来,后面接受的信息通常会受到这个锚的影响,这种影响很多情况下是不被察觉的。即使你会根据新的信息来调整自己的判断,但这种调整往往是不充分的,最后你的判断仍然很难逃出第一印象的圈子。</li> <li><strong>定位调整</strong>:大部分判断和决策都建立在不完整的信息基础上,通常我们会先找到一个相关联的信息,再根据这个信息去对决策进行调整。这个过程就是定位调整。通常由于受到定位效应的影响,定位调整是不充分的。</li> <li>怎么避免:首先意识到自己可能会受到<strong>定位效应</strong>的影响,再去判断我们的定位调整够不够充分。</li> <li><strong>“先入为主”的营销策略</strong>:商家将单品单价开的很高,再给出所谓的优惠。这个很高的价格就是一个锚,被定很高的位置,商家知道消费者会把这个价格往下调整,但是这个调整通常是不充分的,因此给了商家盈利的空间。</li> <li>谈判中利用定位效应: <ol> <li>争取先开价</li> <li>开价越极端越好</li> <li>在开价之前先提醒对方所开的价是荒唐的,给对方谈价空间</li> </ol> </li> </ul> <h2>10. 你的孩子会长多高? —— <strong>违背概率规律</strong></h2> <ul> <li> <p>集合规律:条件越多,交集越小</p> </li> <li> <p>先验概率:不因为眼前的信息而忽视客观分布</p> </li> <li> <p>赌徒谬论:好运和坏运不是交替发生的,是依照概率发生的</p> </li> <li> <p>中值回归规律:极端事物随时间发展都有往中值回归的趋势</p> </li> <li> <p><strong>可获得性误区</strong>:人们总是对易获得的、突出的信息印象深刻,所以认为其是普遍现象</p> </li> <li> <p><strong>反向调整法</strong>:做判断前,检视自身的可获得性误区,了解自己的局限性,扩展信息获取渠道,尝试做出调整</p> </li> </ul> <h2>11. 多一定比少号码? —— 联合评估 &amp; 单独评估</h2> <ul> <li><strong>联合评估</strong>:有参照物,特征被发现、对比、评估,容易找到有价值的、真正值得对比的特征</li> <li><strong>单独评估</strong>:无参照物;易受到一些容易评价&amp;不重要的因素影响;易受极端案例影响而忽视统计数据</li> <li>不要过度追求联合评:很多东西在我们的生活中的使用场景,都是单独评估</li> <li><strong>奚式相亲原则</strong>: <ul> <li>优势在联合评估时更突出</li> <li>敌强我弱;敌强我强 =&gt; 单独评估</li> <li>敌弱我弱;敌若弱我强 =&gt; 联合评估</li> </ul> </li> </ul> <h2>12. 抓住老鼠的一定是好猫吗? —— 结果偏见</h2> <ul> <li>通常情况,过程是难以衡量的,过程的信息不一定可靠,而结果是鲜明可靠的。我们应该尽量基于可靠的信息来做决策</li> <li>但结果并不是最好的评价因素,因为通常情况,过程是可控的,结果往往有很多不确定因素</li> <li>如何解决:给过程添加更多记录和监督机制</li> </ul> <h2>13. 钱越多越幸福吗? —— 财富与幸福</h2> <blockquote> <p>财富的多少和幸福的程度并不成正比</p> </blockquote> <p><strong>不增加财富却可以增加幸福感的一些原则</strong>:</p> <ul> <li>好事一起享受不如分开享受(依据边际递减效应</li> <li>坏事分开忍受不如一起忍受(依据边际递减效应</li> <li>大好事小坏事分开经历不如一起经历(负面效应会被正面效应所冲淡</li> <li>大坏事小好事一起经历不如分开经历(正面效应才不会被负面效应的痛苦所淹没</li> <li>好事晚说不如早说(等待好事的过程是多巴胺活跃的过程</li> <li>坏事早说不如晚说(等待坏事的过程是最消磨人意志的</li> <li>静止的好事不如变动的好事(依据人的适应性规律,并不能为相同的物质方面的东西快乐很久</li> <li>变动的坏事不如静止的坏事(原理同上</li> </ul> <hr /> <p>完结撒花✨🎉🎈🎈</p> 个人成长https://www.scarsu.com/behavior_decision/#post-comment/Devtools 老司机养成 - 第五篇- Network 面板https://www.scarsu.com/devtools_05_network/https://www.scarsu.com/devtools_05_network/chrome最重要之二的Network面板,给后端小哥甩锅?实锤都在这里...Sun, 22 Mar 2020 00:00:00 GMT<h2>概览</h2> <p><img src="https://i.loli.net/2019/04/22/5cbd4f884b14c.png" alt="network.png" /></p> <ul> <li>默认情况下,只要 DevTools 处于打开状态,DevTools 就会在 Network 面板中记录所有网络请求。</li> <li>左上红点按钮:停止记录网络请求</li> <li>第二个按钮:清空请求记录</li> <li>录像按钮:页面加载时捕获屏幕截图</li> <li>过滤按钮:显示/隐藏 过滤条件行</li> <li>View 中的两个按钮:第一个是切换请求列表中每行的显示样式(大小请求行),第二个是显示/隐藏瀑布图</li> <li>Group By Frame:是否根据不同的 frame 分类显示请求</li> <li>Preserve Log:保存显示跨页面的加载请求</li> <li>Disable Cache:禁用浏览器缓存,模拟新用户打开页面的体验</li> <li>Offline 是模拟断网离线的状态,其后的下拉框可以选择模拟其他网络状况,比如 2G,3G</li> </ul> <h2>筛选请求</h2> <ul> <li>filter 文本框中可输入请求的属性 对 请求进行过滤,多个属性用空格分隔</li> <li>支持过滤的属性: <ul> <li>domain。 仅显示来自指定域的资源。 可以使用通配符字符 (<code>*</code>) 纳入多个域。 例如,*.com 将显示来自以 .com 结尾的所有域名的资源。 DevTools 会使用其遇到的所有域填充自动填充下拉菜单。</li> <li>has-response-header。 显示包含指定 HTTP 响应标头的资源。 DevTools 会使用其遇到的所有响应标头填充自动填充下拉菜单。</li> <li>is。 使用 is:running 可以查找 WebSocket 资源。</li> <li>larger-than。 显示大于指定大小的资源(以字节为单位)。 将值设为 1000 等同于设置为 1k。</li> <li>method。 显示通过指定 HTTP 方法类型检索的资源。 DevTools 会使用其遇到的所有 HTTP 方法填充下拉菜单。</li> <li>mime-type。 显示指定 MIME 类型的资源。 DevTools 会使用其遇到的所有 MIME 类型填充下拉菜单。</li> <li>mixed-content。 显示所有混合内容资源 (mixed-content:all),或者仅显示当前显示的资源 (mixed-content:displayed)。</li> <li>scheme。 显示通过未保护 HTTP (scheme:http) 或受保护 HTTPS (scheme:https) 检索的资源。</li> <li>set-cookie-domain。 显示具有 Set-Cookie 标头并且 Domain 属性与指定值匹配的资源。 DevTools 会使用其遇到的所有 Cookie 域填充自动填充下拉菜单。</li> <li>set-cookie-name。 显示具有 Set-Cookie 标头并且名称与指定值匹配的资源。 DevTools 会使用其遇到的所有 Cookie 名称填充自动填充下拉菜单。</li> <li>set-cookie-value。 显示具有 Set-Cookie 标头并且值与指定值匹配的资源。 DevTools 会使用其遇到的所有 Cookie 值填充自动填充下拉菜单。</li> <li>status-code。 仅显示 HTTP 状态代码与指定代码匹配的资源。 DevTools 会使用其遇到的所有状态代码填充自动填充下拉菜单。</li> </ul> </li> <li>例如:mime-type:image/gif larger-than:1K 显示大于一千字节的所有 GIF</li> <li><code>Hide Data URLs</code>:隐藏 <a>data 类型的 url</a></li> </ul> <h2>瀑布图</h2> <ul> <li>瀑布图按时间线展示所有请求</li> <li>可以用鼠标拖动选中一段时间,只查看改时间线内的请求</li> <li>瀑布图中有两条竖线,一条蓝色,代表<a>DOMContentLoaded</a>事件发生的事件,一条红色代表<a>load</a>事件发生的时间点</li> </ul> <h2>分析请求/请求列表</h2> <ul> <li>重播请求:右键点击 Requests 表格中的请求 -&gt; <code>Replay XHR</code></li> <li>讲请求复制为 Fetch 代码 -&gt; <code>Copy As Fetch</code></li> <li>手动清除浏览器缓存:右键点击 Requests 表格中的任意位置 -&gt; 选择 <code>Clear Browser Cache</code></li> <li>手动清除浏览器 Cookie:右键点击 Requests 表格中的任意位置 -&gt; 选择 <code>Clear Browser Cookies</code></li> <li>自定义列表中展示的列</li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbd553d024cc.png" alt="network2.png" /></p> <ul> <li>请求行排序,默认按照瀑布图 start time 升序排序,即请求发起的时间点:</li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbd63427ece0.png" alt="networkOrder.png" /></p> <ul> <li> <p>每条请求,可以看到网络请求以及被清华求资源的全部信息:</p> <ul> <li>请求的一般信息:url、HTTP 方法(GET POST 等)、状态码、ip 地址</li> <li>请求相关:请求头、Initiator、Priority</li> <li>响应相关:响应头、响应内容</li> </ul> </li> <li> <p>Initiator:请求的来源/发起者。parser:一般来自解析器解析到的 html 页面内的请求;script:来自脚本文件的请求。鼠标悬浮到 Initiator 列中的文件名上,可以看到发起当前请求的堆栈轨迹,点击文件名,可以定位到直接发起请求的代码</p> </li> <li> <p>两个 size:在 size 列中,有两个数值,上面的较小值代表下载到的资源的大小,下面的较大值是资源解压后的大小。(例如 在 Content-Encoding 中可以看到的 gzip 和 br)</p> </li> <li> <p>按住<code>shift</code>鼠标悬浮在请求行上,变绿色的行是当前行的发起者,红色的行是当前行的依赖项。</p> </li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbd9945dd05b.png" alt="initiator.png" /></p> <ul> <li>Priority:High,Highest,Low。根据时间线中的蓝线和红线(DOMContentLoaded 和 load),以及请求的优先级,可以从结果的角度观察浏览器的加载流程。</li> </ul> <h2>Websocket</h2> <ul> <li>在 network 的 filter 条件后,选择<code>ws</code>类型的请求,即可看到所有 Websocket 请求</li> <li>在请求详情的 Message 栏中,可以看到 wensocket 全双工通信中客户端接收和发送的信息</li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbdbe96a4597.png" alt="networkWebsocket.png" /></p> <h2>Color Code:瀑布图中的几种颜色与代码</h2> <p><img src="https://i.loli.net/2019/04/22/5cbdc5acaff77.png" alt="colorCode.png" /></p> <ul> <li>Queueing 排队,请求未发出,正在等待。 浏览器在以下情况下对请求排队: <ul> <li>存在更高优先级的请求。</li> <li>此源已打开六个 TCP 连接,达到限值。 仅适用于 HTTP/1.0 和 HTTP/1.1(在 HTTP1 下浏览器一次最允许 6 个 TCP 连接,超出 6 个,就要 queue 排队)(优化 web 性能-&gt;避免 queue-&gt;合并资源请求)</li> <li>浏览器正在短暂分配磁盘缓存中的空间</li> </ul> </li> <li>Stalled/Blocking 停滞/阻塞,请求仍未发出。请求可能会因 Queueing 中描述的任何原因而停止。</li> <li>DNS Lookup dns 查找,浏览器正在解析请求的 IP 地址,每次有指向新 domian 的请求时,会有 dns 查找的时间消耗。</li> <li>Proxy negotiation 代理协商。 浏览器正在与代理服务器协商请求。</li> <li>initial connection/connecting 正在初始化连接 或 正在连接,包含 tcp 的三次握手的时间</li> <li>SSL 完成 SLL 握手所需要的时间</li> <li>Request sent/senting 正在发送请求,发请求所占的时间,通常只有几分之一毫秒。</li> <li>ServiceWorker Preparation。 浏览器正在启动 Service Worker。</li> <li>Request to ServiceWorker。 正在将请求发送到 Service Worker。</li> <li>Waiting (TTFB)。 浏览器正在等待响应的第一个字节。 TTFB 表示 Time To First Byte(至第一字节的时间)。 此时间包括 1 次往返延迟时间及服务器准备响应所用的时间。</li> <li>Content Download。 浏览器正在接收响应。</li> <li>Receiving Push。 浏览器正在通过 HTTP/2 服务器推送接收此响应的数据。</li> <li>Reading Push。 浏览器正在读取之前收到的本地数据。</li> </ul> <h2>相关附注</h2> <h3>DOMContentLoaded 和 load 事件</h3> <ul> <li>DOMContentLoaded — 浏览器已经完全加载了 HTML,DOM 树已经构建完毕,但是像是 <code>&lt;img loading="lazy" decoding="async"&gt;</code> 和样式表等外部资源可能并没有下载完毕。</li> <li>load — 浏览器已经加载了所有的资源(图像,样式表等)。</li> <li>beforeunload/unload -- 当用户离开页面的时候触发。</li> <li><a>更多</a></li> </ul> <h3>data URLs</h3> <ul> <li>即前缀为 data: 协议的的 URL,其允许内容创建者向文档中嵌入小文件,例如浏览器 API canvas 支持的 base64 编码格式图片,<a>更多相关</a></li> </ul> 前端https://www.scarsu.com/devtools_05_network/#post-comment/Devtools 老司机养成 - 第四篇Sources源文件面板https://www.scarsu.com/devtools_04_sources/https://www.scarsu.com/devtools_04_sources/chrome重要的sources面板,可以做IDE?文件变更,覆盖调试...Sun, 15 Mar 2020 00:00:00 GMT<h2>概览</h2> <ul> <li>Debug : 在源代码面板中可以设置<strong>断点</strong>来调试 JavaScript ,比 console.log()调试更快速高效</li> <li>Devtools as IDE : 通过 Workspaces(工作区)连接本地文件来使用开发者工具的<strong>实时编辑器</strong></li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e54ad6595d17473.png" alt="0" /></p> <h2>七种断点类型</h2> <ol> <li> <p>行断点:代码运行到当前行之前暂停执行</p> <pre><code>在源代码添加debugger关键字 或者 点击Sources面板中的源代码的行号 </code></pre> </li> <li> <p>条件行断点:当满足条件时才会触发该断点</p> <pre><code>右击Sources面板中的源代码的行号 选择“Add conditional breakpoint” </code></pre> <p><img src="https://i.loli.net/2019/07/29/5d3e54bc1e26c94874.gif" alt="0" /></p> </li> <li> <p>DOM 断点</p> <pre><code>即Elements面板提及过的三种DOM断点: - 节点属性断点 - 节点删除断点 - 子树变更断点 </code></pre> <p><img src="https://i.loli.net/2019/07/29/5d3e54c7ee26f77001.gif" alt="0" /></p> </li> <li> <p>XHR/Fetch 断点</p> <pre><code>在页面发出XHR或Fetch请求前加断点 </code></pre> <p><img src="https://i.loli.net/2019/07/29/5d3e54d8de3ba68180.png" alt="0" /></p> </li> <li> <p>Event Listener 事件监听断点</p> <pre><code>可以在所有类型的事件函数被出发前加断点 </code></pre> <p><img src="https://i.loli.net/2019/07/29/5d3e54d8f005d73515.png" alt="0" /></p> </li> <li> <p>Exception 异常断点</p> <p><img src="https://i.loli.net/2019/07/29/5d3e54d90b04490413.gif" alt="0" /></p> </li> <li> <p>Function 函数断点</p> <pre><code>把想调试的函数名作为参数,调用debug()函数,可以在每次执行该函数前暂停执行代码 </code></pre> <p><img src="https://i.loli.net/2019/07/29/5d3e54db0062099787.gif" alt="0" /></p> </li> </ol> <h2>Debug</h2> <ul> <li>函数调用栈 Call Stack:Call Stack 是 time traveling 的,即点击栈中的任一节点,当前的作用域和局部变量等信息,都会模拟至该节点执行时的状态</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e556a3d2ff51804.png" alt="0" /></p> <ul> <li>全局作用域 Global ,局部作用域 Local ,闭包作用域 Closure</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e5579edff848268.png" alt="0" /></p> <ul> <li>step over next function</li> <li>step into next function</li> <li>step out current function</li> <li>step (与 step over/into 的区别就是,step 会优先尝试 step into,当没有可步入的代码时,就会执行 step over)</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e558950aa668631.png" alt="0" /></p> <ul> <li>long resume:恢复执行,并将断点停用 500ms</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e55951dbb174461.gif" alt="0" /></p> <ul> <li>Continue to here:继续执行至此行</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e55b1cbe1030881.gif" alt="0" /></p> <ul> <li>Restart Frame:重新执行函数调用堆栈中的某一帧</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e55be02afb66581.gif" alt="0" /></p> <ul> <li>行断点内的多个箭头:行内断点(行内的,可 step into 的 执行点</li> </ul> <p><img src="https://i.loli.net/2019/05/13/5cd969192e3cf64417.png" alt="" /></p> <h2>Devtools Nodejs debug</h2> <ul> <li>node 执行 js 文件,文件名前加--inspect 标志,启用浏览器 nodejs 调试</li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbd33c700aed.png" alt="nodeDebug.png" /></p> <ul> <li>点击 devtools 中,左上角的 devices mode 右侧的绿色按钮,即可启用 node 服务端中的脚本调试</li> <li><a>更多相关</a></li> </ul> <h2>BlackBox</h2> <ul> <li> <p>BlackBox 的用途:</p> <p>“BlackBox Script”可以在调试中忽略某些脚本(此处的 BlackBox 为动词),在 Call Stack 堆栈中会将该脚本隐藏,单步调试时也不会步入脚本中的任何函数</p> <pre><code>function animate() { prepare(); lib.doFancyStuff(); // A render(); } </code></pre> <p>例如以上代码的 A 行,调用的是第三方库的 doFancyStuff 函数</p> <p>如果我确认该第三方库没有 bug</p> <p>就可以 BlackBox 整个第三方库的 js 脚本,在调试中跳过这些代码的执行</p> </li> <li> <p>三种添加 BlackBox 的方法:</p> </li> </ul> <ol> <li> <p>在源代码窗格右键,选择"BlackBox Script" <img src="https://i.loli.net/2019/07/29/5d3e55d52054637081.gif" alt="0" /></p> </li> <li> <p>在 Call Stack 中右键某一帧,选择"BlackBox Script" <img src="https://i.loli.net/2019/07/29/5d3e55d3bd9da13494.gif" alt="0" /></p> </li> <li> <p>在设置中的 Blackboxing 面板添加<strong>正则表达式</strong>匹配<strong>文件名</strong></p> <p><img src="https://i.loli.net/2019/07/29/5d3e55d9e574935159.gif" alt="0" /></p> </li> </ol> <h2>Workspace:Devtools as IDE 将更改持久化</h2> <ul> <li>在 sources 左侧的面板中选择<code>Filesystem</code>,点击<code>Add folder to workspace</code>,将你本地运行的站点的相关源文件添加到 Devtools 的工作区,会自动识别 Page 下和工作区下相对应的文件,在 devtools 更改文件并保存,即持久化保存(目前只支持自动识别,不支持添加映射)</li> <li>绿标文件:成功的映射到本地的文件,在 Styles 和 Sources 中的文件名前,都会添加绿色圆点作为标识 <img src="https://i.loli.net/2019/04/22/5cbd0771e5e31.png" alt="workspace.png" /> <img src="https://i.loli.net/2019/04/22/5cbd07bf14dc8.png" alt="workspace2.png" /></li> <li>目前 Devtools 已经支持 sass/scss、UglifyJS、Grunt、Coffescript、Closure 等等,暂时还不支持 webpack,和其他现代的复杂框架,如 react</li> <li>所有sources面板的文件,都可以右键选择<code>local modifications</code>,查看所有更改</li> <li>对 DOM 树的更改不会持久化至 html 文件:因为 dom 的最终表现,受到 html、css、javascript 的共同影响,DOM 树 !== HTML,因此可以在 sources 中直接更改 html 文件并保存</li> </ul> <h2>Source Map</h2> <ul> <li>组合/压缩 css,js 文件是常见的性能优化方案,但是会对开发调试造成困扰</li> <li>Source Map 用于将生产代码映射至源代码,Chrome 和 firefox 都内置了对 Source Map 的支持</li> <li>在 Chorme devtools 中,settings -&gt; preferen -&gt; sources 中,选中<code>Enable Javascript source maps</code>和<code>Enable CSS source maps</code></li> <li>source map 映射信息存在 json 对象中,保存在 .map 文件中,可以由编译程序添加注释<code>//# sourceMappingURL=/path/to/script.js.map</code>至生产文件末尾,也可以由服务端在响应头中添加<code>X-SourceMap: /path/to/script.js.map</code>,将 map 文件与生产文件对应。<a>更多关于 source map 的介绍</a></li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbd10f324e07.png" alt="sourceMap.png" /></p> <h2>Local Overrides</h2> <ul> <li>用于覆盖网络请求: 在source/page右键save for override或直接edit,保存的文件都被存储到overrides 指定目录(按照域名建立文件夹). 这种改写是临时的</li> <li>在 Sources 面板左侧选择 Overrides,指定 DevTools 应保存更改的目录,当在 DevTools 中进行更改时,DevTools 会将修改后的文件的副本保存到所选的本地目录中,重新加载页面时,DevTools 提供本地修改的文件,而不是请求的网络资源。</li> <li>与 Workspace 相似的,不支持保存对 DOM 树的更改,需要直接更改 html 源文件。</li> <li>只能指定一个目录</li> <li>断点debug 时,实时修改文件,然后保存后会恢复到第一个断点,不用重新刷新</li> </ul> <h2>Snippets 代码片段</h2> <ul> <li>在 Sources 面板左侧选择 Snippets,或<code>crlt shift p</code>输入 snippet 打开 Snippets 面板,可以创建并保存常用的代码片段,和用 gist 类似</li> <li>snippets 中,选中代码并<code>ctrl enter</code>,或点击右下角的执行按钮,即可执行代码片段</li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbd147145955.png" alt="snippet.png" /></p> <h2>Content scripts</h2> <ul> <li>这部分脚本是浏览器插件的脚本,在特定网页的上下文中运行。(与插件运行在服务端的脚本,页面上引用的脚本,页面上 script 中的内嵌脚本都不同</li> <li>插件在服务端的脚本可以访问所有 WebExtension JavaScript API,但它们无法直接访问网页内容。</li> <li>Content scripts 只能访问 WebExtension API 的一小部分,但它们可以使用消息传递系统与后台脚本进行通信,从而间接访问 WebExtension API。</li> <li>如果有浏览器插件相关的工作,可以更深入<a>研究</a>,不赘述。</li> </ul> 前端https://www.scarsu.com/devtools_04_sources/#post-comment/Devtools 老司机养成 - 第三篇-Console 面板https://www.scarsu.com/devtools_03_console/https://www.scarsu.com/devtools_03_console/Console 面板是浏览器的控制台,也是 Devtools 的灵魂,只会console.log就过分啦~Sun, 08 Mar 2020 00:00:00 GMT<h2>概览</h2> <p>Console 面板是浏览器的控制台,也是 Devtools 的灵魂。</p> <p>可以通过<strong>设置-&gt;Show Console drawer</strong>或者<strong>Esc 快捷键</strong>让 Console 在每个面板都能显示。 <img src="https://i.loli.net/2019/07/29/5d3e5381c290f84642.png" alt="0" /></p> <h2>message</h2> <ul> <li>在 console 中,可以看到来自<strong>浏览器</strong>/<strong>代码</strong>的五种类型的信息: <ul> <li>user message</li> <li>error</li> <li>warning</li> <li>info</li> <li>verbose</li> </ul> </li> <li>相同的消息默认是堆叠的,可以通过 ctrl+shift+p 输入 time 命令或者设置中找到<strong>timestamps</strong>命令,给消息加上时间戳</li> <li>通过选项<strong>Log XMLHttpRequest</strong>选择是否输出所有 XMLHttp 请求日志(可以监控页面所有 ajax 请求 定位其代码调用栈)</li> <li>通过<strong>Hide network</strong>选择显示/隐藏网络请求的错误信息(例如 GET xxx 404)</li> <li>通过<strong>Preserve log</strong>选择保留历史记录,即刷新页面后是否还显示先前的消息</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e53989dba574108.png" alt="0" /></p> <h2>javascript 实时执行环境</h2> <ul> <li>console 除了能输出调试信息,也是一个 javascript 实时执行环境。</li> <li>可以直接在这里输入任何<strong>全局变量名</strong>/内置对象名/函数名,会得到相应的值输出;在调试环境下的断点内,可以获取<strong>局部变量</strong>值</li> <li>右键选<strong>Store as global variable</strong>,可以将输出值存储为一个临时的全局变量</li> <li>双击对象的属性值,可以直接更改这个对象(持久化的更改,因为 console 存储下来的是对象的引用)</li> <li>console 中输出的 dom 元素 -&gt; 右键 -&gt; reveal in elements:快速定位到元素面板中的当前元素</li> </ul> <h2>选择执行环境</h2> <p>可以通过左上的下拉列表,选择不同的<strong>执行环境</strong></p> <p><img src="https://i.loli.net/2019/07/29/5d3e53a7d369f73554.png" alt="0" /></p> <p>top 是最外层的顶级页面,其他的是 iframe 子页面</p> <p>默认情况下</p> <ul> <li>子 frame 中:</li> </ul> <pre><code>(window === self) === self.window; //top.window是顶级页面top的全局变量window </code></pre> <ul> <li>top frame 中:</li> </ul> <pre><code>(((window === self) === self.window) === top) === top.window; </code></pre> <h2>console 中的<code>$</code>符号:</h2> <ul> <li>可以通过<code>$0</code>,获取当前在 Elements 面板所选中的元素节点</li> <li>如果 <code>$</code> 在当前页面没被占用,可以用来替代 document.querySlector 方法使用</li> <li><code>$$</code> 是 document.querySelectorAll 方法的更佳替代,因为 document.querySelectorAll 返回的是 nodeList(NodeList),而<code>$$</code>能直接返回数组(Array) <img src="https://i.loli.net/2019/07/29/5d3e53c18483c36428.png" alt="0" /></li> <li><code>$_</code>可以引用上一次执行的结果 <img src="https://i.loli.net/2019/07/29/5d3e53c198cdf46610.png" alt="0" /></li> <li>如果需要使用 npm 的包,可以安装 Console Importer 插件,用<code>$i</code>方法引入 npm 中的库 <img src="https://i.loli.net/2019/07/29/5d3e53c1ae52088165.gif" alt="0" /></li> </ul> <h2>console 下的方法:</h2> <ul> <li>除了被用烂了的<code>console.log()</code>(当然 console.log 也有特别一点的用法) <img src="https://i.loli.net/2019/07/29/5d3e53ec0c9c777415.png" alt="0" /></li> <li>console 对象还有 console.error/clear/debug/count/time/table/tarce 等等方法</li> <li>直接在 console 中输入 console,可以看到 console 对象下的所有方法 <img src="https://i.loli.net/2019/07/29/5d3e54117f36b48748.png" alt="0" /></li> <li>例如 console.table(obj)可以把你的对象以可视化的表格形式进行输出 <img src="https://i.loli.net/2019/07/29/5d3e541ed227433392.gif" alt="0" /></li> <li>例如可以使用 console.time()和 console.timeEnd()方法来测量时间差 <img src="https://i.loli.net/2019/07/29/5d3e542c27e8b99508.png" alt="0" /></li> <li>另:console 命令行还内置了一些 API 方法,例如 queryObjects(),可以返回指定类型的对象下所有的实例化的对象 <img src="https://i.loli.net/2019/07/29/5d3e5480317cd69237.png" alt="0" /></li> </ul> <pre><code>queryObjects(Object); //返回所有object对象 queryObjects(Function); //返回所有函数 queryObjects(Array); //返回所有数组 </code></pre> <ul> <li>monitor(function)方法来追踪函数调用信息,当函数被执行,会输出追踪信息 <img src="https://i.loli.net/2019/07/29/5d3e548f62a6723531.png" alt="0" /></li> <li>monitorEvents(el,eventType)方法来追踪事件 <img src="https://i.loli.net/2019/07/29/5d3e5494878e638089.png" alt="0" /></li> </ul> 前端https://www.scarsu.com/devtools_03_console/#post-comment/Devtools 老司机养成 - 第二篇-Elements 面板https://www.scarsu.com/devtools_02_elements/https://www.scarsu.com/devtools_02_elements/样式顺手调,DOM实时改~Sun, 01 Mar 2020 00:00:00 GMT<h2>界面概览</h2> <p>使用 Chrome DevTools 的 Elements 面板检查和实时编辑页面的 HTML 与 CSS</p> <p><img src="https://i.loli.net/2019/07/29/5d3e521d6fbde79541.png" alt="Elements 面板" /></p> <h2>Inspect Mode</h2> <p>快捷键 ctrl shift c/点击面板左上角的按钮,进入元素选择模式 <img src="https://i.loli.net/2019/04/19/5cb9cb351d6a2.png" alt="inspect" /></p> <p>在新版本 chrome 中,选择元素时会显示更多元素信息 <img src="https://i.loli.net/2019/04/19/5cb9ca97739bb.png" alt="inspect" /></p> <h2>Device Mode 设备模式</h2> <ul> <li>模拟不同尺寸移动端设备下,网页的表现。</li> <li>是自适应网页调试利器。</li> <li>内置/可配置既有设备属性,例如 iphone/ipad</li> <li>支持调试媒体查询 media-query。</li> </ul> <p><img src="https://i.loli.net/2019/04/19/5cb9cc03d400a.png" alt="deviceMode" /></p> <h2>DOM 树</h2> <p>在元素面板左侧是当前页的 DOM 树 <img src="https://i.loli.net/2019/07/29/5d3e52339265738563.png" alt="0" /></p> <p>在 DOM 树中你可以:</p> <ul> <li> <p>直接增/删/改/复制/拖放移动 DOM 元素,查看实时效果(非持久化)</p> </li> <li> <p>添加元素断点(节点移除断点,属性变更断点,子树变更断点)</p> </li> <li> <p>模拟元素 focus/hover/actice 等状态</p> </li> <li> <p>选中元素后通过右键“Scroll into view”突出显示当前元素在页面的位置</p> </li> <li> <p>按快捷键<strong>h</strong>来快速隐藏/显示元素当前元素及其后代元素(原理是 visibility 设为 hidden,不影响其他元素,不引起重绘)</p> </li> <li> <p>按住 alt 键 点击 dom 元素前的箭头:全部折叠/展开当前元素及其后代元素</p> <p><img src="https://i.loli.net/2019/07/29/5d3e52c51ed0570682.png" alt="0" /></p> </li> </ul> <h2>Styles</h2> <p>在面板右侧 Styles 窗格中:</p> <ul> <li>会显示节点的各级样式</li> <li>每级样式的来源</li> <li>每条样式属性是否命中</li> <li>可以直接增/删/改元素样式,查看实时效果(非持久化)</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e524d5a48a76988.png" alt="0" /></p> <h2>color picker</h2> <p><img src="https://i.loli.net/2019/05/13/5cd95d7a5c09c98927.png" alt="" /></p> <ul> <li>在样式窗格中,devtools 给所有颜色属性值前添加了 color picker 工具</li> <li>按住 shift 点击色块,快速切换颜色格式 rgb/hsl/hex</li> </ul> <p><img src="https://i.loli.net/2019/05/13/5cd95e1abea2793787.png" alt="" /></p> <ul> <li>page colors:color picker 中会列出页面所有的颜色</li> <li>material colors:color picker 中会列出 google 设计推荐色系</li> </ul> <h2>Computed</h2> <p>在 Styles 右侧的 Computed 窗格中可以查看:</p> <ul> <li>元素的盒模型(双击值可编辑)</li> <li>元素所有样式的<strong>计算后最终值</strong>(即最终实际应用到元素的值)</li> <li>点开每一条最终值,可以看到所有该条样式的规则,以及代码来源</li> <li>勾选<strong>show all</strong>选项,会同时列出元素<strong>继承 / 默认</strong>样式</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e525f4f2a311954.png" alt="0" /></p> <h2>Event Listeners</h2> <ul> <li>在 Event Listeners 窗格中,可以看到元素的事件监听器</li> <li>例如"load","DOMContentLoaded","click"等,以及每个事件对应的事件处理函数</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e52728065d88131.png" alt="0" /></p> <p>在源代码中加 <strong>行 debugger 断点</strong>,或者<strong>debug(函数)断点</strong>(Sources 面板会提及这两种断点),是需要代码维护成本的,有时候还会忘记删除;</p> <p>或者你想调试别人开发的 你不拥有源码的 网页;</p> <p>这些时候可以利用 Event Listeners 窗格快速定位当前元素被绑定的所有的<strong>事件函数代码</strong>并调试。</p> <h2>DOM Breakpoints</h2> <p>在面板右侧 DOM Breakpoints 中,可以查看<strong>元素断点</strong></p> <p><img src="https://i.loli.net/2019/07/29/5d3e5282c491d43866.png" alt="0" /></p> <p>相应的在左侧 DOM 树右键点击元素,可以给元素添加断点</p> <p>元素断点有三种类型:属性变更,子树变更,节点删除</p> <p>例如添加“node removal”断点,就会在 有代码移除当前节点时,在当前行代码执行前暂停执行,并自动转换到 Sources 面板,以便做进一步调试 <img src="https://i.loli.net/2019/07/29/5d3e529117f6c69468.png" alt="0" /></p> <h2>Properties</h2> <p>Properties 面板会列出元素 DOM 底层相关属性 <img src="https://i.loli.net/2019/07/29/5d3e52b143cc424671.png" alt="0" /></p> <h2>Accessibility(可访问性)</h2> <ul> <li>在辅助功能树中查看元素的位置(可访问性树/无障碍树是 DOM 树的子集。它只包含来自 DOM 树的元素,这些元素可以展示在屏幕阅读器中页面的内容。</li> <li>查看元素的 ARIA 属性(ARIA 属性确保屏幕阅读器具有所需的所有信息,以便正确表示页面的内容。</li> <li>查看元素的计算辅助功能属性(某些辅助功能属性由浏览器动态计算。可以在“ 辅助功能”窗格的“ 计算属性”部分中查看这些属性</li> </ul> <p><img src="https://i.loli.net/2019/04/21/5cbc83e1561e4.png" alt="accessibility.png" /></p> 前端https://www.scarsu.com/devtools_02_elements/#post-comment/Devtools 老司机养成 - 第一篇Devtools介绍https://www.scarsu.com/devtools_01_intro/https://www.scarsu.com/devtools_01_intro/前端开发调试第一利器,关于devtools的信息,都在这里Sun, 23 Feb 2020 00:00:00 GMT<h2>相关</h2> <ul> <li>本文作者:<a>ScarSu</a></li> <li>本文基于 chrome 浏览器版本 73.0.3683.103(正式版本)总结</li> <li>本文目的:关于【devtools 能做什么】建立完善的知识结构,至于怎么做,请查阅官方文档;工具类知识需要实践,建议阅读本文时打开 <a>sample</a>和 devtools 操作一遍</li> <li>参考 1:<a>google developers 官方文档</a></li> <li>参考 2:来自作者 Jon Kuoerman 在 FrontEndMaster 的 <a>Mastering Chrome Developer Tools v2 课程</a></li> <li>参考 3:来自 作者 Tomek Sułkowski 在 medium 的<a>系列文章</a></li> <li><a>Devtools脑图.png</a></li> </ul> <h2>web devtool 历史</h2> <ul> <li>view-source + alert 调试法</li> <li><a>Live DOM Viewer</a></li> <li><a>Firebug</a></li> </ul> <h2>Chrome相关介绍</h2> <h4>Chromium</h4> <pre><code>是谷歌的开源项目,由开源社区维护。 国产的所有 “双核浏览器”,都是基于 Chromium 开发的,甚至 Chrome 也是基于它。 我们下载的 Chromium 浏览器都是其源码未经修改的直接编译版本。 Chromium 的内核版本比 Chrome 明显领先,新的技术都是先在 Chromium 上应用。 几乎每天都在进行更新; </code></pre> <h4>Chrome</h4> <pre><code>基于 Chromium,但是它是闭源的! 所以有这样的一种说法:谷歌把核心技术都保留在了之家的 Chrome 中。 支持了一些商业的收费插件,这些是不会出现在开源软件中的: H.264编码、mp3编码 Chrome 内置了 Flash,Chromium 需要额外安装 据说?在网页渲染方面 Chrome 也悄悄有一些特别的优化。 集成了更多的谷歌服务(RanBinNuan),同时也有更多的限制,比如目前使用 Chrome 需要一定手段才能安装非商店的扩展,一旦被发现还会永远禁用,但 Chromium 就没有这些限制! </code></pre> <h4>Dev Canary Stable Beta</h4> <p>是Chrome的四个版本:</p> <ul> <li>Stable 稳定版(几月一次更新)</li> <li>Beta 测试版(1 月一次更新)</li> <li>Dev 开发者版(1 星期一次更新)</li> <li>Canary 金丝雀版(脚步几乎同步 Chromium,天天更新)图标采用了特别的土豪金版神奇宝贝球。</li> </ul> <p>新版发布速度递增 新功能数量递增 稳定性递减</p> <h2>Chrome Devtools 界面概览</h2> <p><img src="https://i.loli.net/2019/04/19/5cb955bed88ce.png" alt="000devtoolsAll.png" /></p> <h2>Tips and Tricks</h2> <ul> <li>快捷键:ctrl shift p:执行命令</li> <li>快捷键:ctrl p:打开文件</li> <li>快捷键:esc:显示/隐藏 drawer(第二行面板</li> <li>快捷键:ctrl shift c:选择元素</li> <li>more -&gt; focus debugee:切换至正在被调试的页面</li> <li>more -&gt; more tools:全部面板</li> <li>无痕模式打开网页 —&gt; 更纯净的调试环境,无扩展代码干扰</li> <li>实验性功能:</li> </ul> <pre><code> 打开url chrome://flags/ 搜索dev 打开Experimental Extension APIs开关 在settings中找到experiments可以找到相关实验性功能 shift按七次,显示隐藏的实验性功能(比如terminal </code></pre> <ul> <li>金丝雀版 chrome - <a>Canary - 开发者专用的每日更新版</a></li> <li>开发者版 chrome - <a>Dev - 开发者专用的每周更新版</a></li> </ul> 前端https://www.scarsu.com/devtools_01_intro/#post-comment/Devtools 入门https://www.scarsu.com/devtools_rookie_intro/https://www.scarsu.com/devtools_rookie_intro/Devtools新手请看这篇,入门大全~Sun, 16 Feb 2020 00:00:00 GMT<h1></h1> <h2>相关</h2> <ul> <li>本文作者:<a>ScarSu</a></li> <li><a>进阶系列文链接</a></li> <li>本文基于 chrome 浏览器版本 73.0.3683.103(正式版本)总结</li> <li>参考 :<a>google developers 官方文档</a></li> </ul> <h2>web devtool 历史</h2> <ul> <li>view-source + alert 调试法</li> <li><a>Live DOM Viewer</a></li> <li><a>Firebug</a></li> </ul> <h2>Chrome相关介绍</h2> <h4>Chromium</h4> <pre><code>是谷歌的开源项目,由开源社区维护。 国产的所有 “双核浏览器”,都是基于 Chromium 开发的,甚至 Chrome 也是基于它。 我们下载的 Chromium 浏览器都是其源码未经修改的直接编译版本。 Chromium 的内核版本比 Chrome 明显领先,新的技术都是先在 Chromium 上应用。 几乎每天都在进行更新; </code></pre> <h4>Chrome</h4> <pre><code>基于 Chromium,但是它是闭源的! 所以有这样的一种说法:谷歌把核心技术都保留在了之家的 Chrome 中。 支持了一些商业的收费插件,这些是不会出现在开源软件中的: H.264编码、mp3编码 Chrome 内置了 Flash,Chromium 需要额外安装 据说?在网页渲染方面 Chrome 也悄悄有一些特别的优化。 集成了更多的谷歌服务(RanBinNuan),同时也有更多的限制,比如目前使用 Chrome 需要一定手段才能安装非商店的扩展,一旦被发现还会永远禁用,但 Chromium 就没有这些限制! </code></pre> <h4>Dev Canary Stable Beta</h4> <pre><code>是Chrome的四个版本 Stable 稳定版(几月一次更新) Beta 测试版(1 月一次更新) Dev 开发者版(1 星期一次更新) Canary 金丝雀版(脚步几乎同步 Chromium,天天更新)图标采用了特别的土豪金版神奇宝贝球。 新版发布速度递增 新功能数量递增 稳定性递减 </code></pre> <h2>Chrome Devtools 界面概览</h2> <p><img src="https://i.loli.net/2019/04/19/5cb955bed88ce.png" alt="000devtoolsAll.png" />;</p> <h2>Tips and Tricks</h2> <ul> <li>快捷键:ctrl shift p:执行命令</li> <li>快捷键:ctrl p:打开文件</li> <li>快捷键:esc:显示/隐藏 drawer(第二行面板</li> <li>快捷键:ctrl shift c:选择元素</li> <li>more -&gt; focus debugee:切换至正在被调试的页面</li> <li>more -&gt; more tools:全部面板</li> <li>无痕模式打开网页 —&gt; 更纯净的调试环境,无扩展代码干扰</li> <li>实验性功能:</li> </ul> <pre><code> 打开url chrome://flags/ 搜索dev 打开Experimental Extension APIs开关 在settings中找到experiments可以找到相关实验性功能 shift按七次,显示隐藏的实验性功能(比如terminal </code></pre> <ul> <li>金丝雀版 chrome - <a>Canary - 开发者专用的每日更新版</a></li> <li>开发者版 chrome - <a>Canary - 开发者专用的每周更新版</a></li> </ul> <h2>Elements 面板</h2> <p>使用 Chrome DevTools 的 Elements 面板检查和实时编辑页面的 HTML 与 CSS</p> <p><img src="https://i.loli.net/2019/06/03/5cf4a9da59be527769.png" alt="Elements 面板" /></p> <h3>Inspect Mode</h3> <p>快捷键 ctrl shift c/点击面板左上角的按钮,进入元素选择模式 <img src="https://i.loli.net/2019/04/19/5cb9cb351d6a2.png" alt="inspect" /></p> <p>在新版本 chrome 中,选择元素时会显示更多元素信息 <img src="https://i.loli.net/2019/04/19/5cb9ca97739bb.png" alt="inspect" /></p> <h3>Device Mode 设备模式</h3> <ul> <li>模拟不同尺寸移动端设备下,网页的表现。</li> <li>是自适应网页调试利器。</li> <li>内置/可配置既有设备属性,例如 iphone/ipad</li> <li>支持调试媒体查询 media-query。</li> </ul> <p><img src="https://i.loli.net/2019/04/19/5cb9cc03d400a.png" alt="deviceMode" /></p> <h3>DOM 树</h3> <p>在元素面板左侧是当前页的 DOM 树 <img src="https://i.loli.net/2019/06/03/5cf4aa13906d615289.png" alt="0" /></p> <p>在 DOM 树中可以:</p> <ul> <li> <p>直接增/删/改/复制/拖放移动 DOM 元素,查看实时效果(非持久化)</p> </li> <li> <p>添加元素断点(节点移除断点,属性变更断点,子树变更断点)</p> </li> <li> <p>模拟元素 focus/hover/actice 等状态</p> </li> <li> <p>选中元素后通过右键“Scroll into view”突出显示当前元素在页面的位置</p> </li> <li> <p>按快捷键<strong>h</strong>来快速隐藏/显示元素当前元素及其后代元素(原理是 visibility 设为 hidden,不影响其他元素,不引起重绘)</p> </li> <li> <p>按住 alt 键 点击 dom 元素前的箭头:全部折叠/展开当前元素及其后代元素</p> <p><img src="https://i.loli.net/2019/06/03/5cf4aa2c66c6183499.png" alt="0" /></p> </li> </ul> <h3>Styles</h3> <p>在面板右侧 Styles 窗格中:</p> <ul> <li>会显示节点的各级样式</li> <li>每级样式的来源</li> <li>每条样式属性是否命中</li> <li>可以直接增/删/改元素样式,查看实时效果(非持久化)</li> </ul> <p><img src="https://i.loli.net/2019/06/03/5cf4aa3edd33430557.png" alt="0" /></p> <h3>color picker</h3> <p><img src="https://i.loli.net/2019/05/13/5cd95d7a5c09c98927.png" alt="" /></p> <ul> <li>在样式窗格中,devtools 给所有颜色属性值前添加了 color picker 工具</li> <li>按住 shift 点击色块,快速切换颜色格式 rgb/hsl/hex</li> </ul> <p><img src="https://i.loli.net/2019/05/13/5cd95e1abea2793787.png" alt="" /></p> <ul> <li>page colors:color picker 中会列出页面所有的颜色</li> <li>material colors:color picker 中会列出 google 设计推荐色系</li> </ul> <h3>Computed</h3> <p>在 Styles 右侧的 Computed 窗格中可以查看:</p> <ul> <li>元素的盒模型(双击值可编辑)</li> <li>元素所有样式的<strong>计算后最终值</strong>(即最终实际应用到元素的值)</li> <li>点开每一条最终值,可以看到所有该条样式的规则,以及代码来源</li> <li>勾选<strong>show all</strong>选项,会同时列出元素<strong>继承 / 默认</strong>样式</li> </ul> <p><img src="https://i.loli.net/2019/06/03/5cf4aa5b8838377487.png" alt="0" /></p> <h3>Event Listeners</h3> <ul> <li>在 Event Listeners 窗格中,可以看到元素的事件监听器</li> <li>例如"load","DOMContentLoaded","click"等,以及每个事件对应的事件处理函数</li> </ul> <p><img src="https://i.loli.net/2019/06/13/5d01e076e584425630.png" alt="0" /></p> <p>在源代码中加 <strong>行 debugger 断点</strong>,或者<strong>debug(函数)断点</strong>(Sources 面板会提及这两种断点),是需要代码维护成本的,有时候还会忘记删除;</p> <p>或者你想调试别人开发的 你不拥有源码的 网页;</p> <p>这些时候可以利用 Event Listeners 窗格快速定位当前元素被绑定的所有的<strong>事件函数代码</strong>并调试。</p> <h3>DOM Breakpoints</h3> <p>在面板右侧 DOM Breakpoints 中,可以查看<strong>元素断点</strong></p> <p><img src="https://i.loli.net/2019/06/03/5cf4aa7a33a2334307.png" alt="0" /></p> <p>相应的在左侧 DOM 树右键点击元素,可以给元素添加断点</p> <p>元素断点有三种类型:属性变更,子树变更,节点删除</p> <p>例如添加“node removal”断点,就会在 有代码移除当前节点时,在当前行代码执行前暂停执行,并自动转换到 Sources 面板,以便做进一步调试 <img src="https://i.loli.net/2019/06/03/5cf4aa879865e17312.png" alt="0" /></p> <h2>Console 面板</h2> <p>Console 面板是浏览器的控制台,也是 Devtools 的灵魂。</p> <p>可以通过<strong>设置-&gt;Show Console drawer</strong>或者<strong>Esc 快捷键</strong>让 Console 在每个面板都能显示。 <img src="https://i.loli.net/2019/06/03/5cf4aaa5f1e3422250.png" alt="0" /></p> <h3>message</h3> <ul> <li>在 console 中,可以看到来自<strong>浏览器</strong>/<strong>代码</strong>的五种类型的信息: <ul> <li>user message</li> <li>error</li> <li>warning</li> <li>info</li> <li>verbose</li> </ul> </li> <li>相同的消息默认是堆叠的,可以通过 ctrl+shift+p 输入 time 命令或者设置中找到<strong>timestamps</strong>命令,给消息加上时间戳</li> <li>通过选项<strong>Log XMLHttpRequest</strong>选择是否输出所有 XMLHttp 请求日志(可以监控页面所有 ajax 请求 定位其代码调用栈)</li> <li>通过<strong>Hide network</strong>选择显示/隐藏网络请求的错误信息(例如 GET xxx 404)</li> <li>通过<strong>Preserve log</strong>选择保留历史记录,即刷新页面后是否还显示先前的消息</li> </ul> <p><img src="https://i.loli.net/2019/06/03/5cf4aab869c8a85783.png" alt="0" /></p> <h3>javascript 实时执行环境</h3> <ul> <li>console 除了能输出调试信息,也是一个 javascript 实时执行环境。</li> <li>可以直接在这里输入任何<strong>全局变量名</strong>/内置对象名/函数名,会得到相应的值输出;在调试环境下的断点内,可以获取<strong>局部变量</strong>值</li> <li>右键选<strong>Store as global variable</strong>,可以将输出值存储为一个临时的全局变量</li> <li>双击对象的属性值,可以直接更改这个对象(持久化的更改,因为 console 存储下来的是对象的引用)</li> <li>console 中输出的 dom 元素 -&gt; 右键 -&gt; reveal in elements:快速定位到元素面板中的当前元素</li> </ul> <h3>选择执行环境</h3> <p>可以通过左上的下拉列表,选择不同的<strong>执行环境</strong></p> <p><img src="https://i.loli.net/2019/06/03/5cf4aac95398455074.png" alt="0" /></p> <p>top 是最外层的顶级页面,其他的是 iframe 子页面</p> <h3>console 中的<code>$</code>符号:</h3> <ul> <li>可以通过<code>$0</code>,获取当前在 Elements 面板所选中的元素节点</li> <li>如果 <code>$</code> 在当前页面没被占用,可以用来替代 document.querySlector 方法使用</li> <li><code>$$</code> 是 document.querySelectorAll 方法的更佳替代,因为 document.querySelectorAll 返回的是 nodeList(NodeList),而<code>$$</code>能直接返回数组(Array) <img src="https://i.loli.net/2019/06/03/5cf4aadf0381221831.png" alt="0" /></li> <li><code>$_</code>可以引用上一次执行的结果 <img src="https://i.loli.net/2019/06/03/5cf4aae17ead896661.png" alt="0" /></li> <li>如果需要使用 npm 的包,可以安装 Console Importer 插件,用<code>$i</code>方法引入 npm 中的库 <img src="https://i.loli.net/2019/06/03/5cf4aae3f1a0221583.gif" alt="0" /></li> </ul> <h3>console 下的方法:</h3> <ul> <li>除了被用烂了的<code>console.log()</code>(当然 console.log 也有特别一点的用法) <img src="https://i.loli.net/2019/06/03/5cf4ab4d3e91911373.png" alt="0" /></li> <li>console 对象还有 console.error/clear/debug/count/time/table/tarce 等等方法</li> <li>直接在 console 中输入 console,可以看到 console 对象下的所有方法 <img src="https://i.loli.net/2019/06/03/5cf4ab5e5d30e65867.png" alt="0" /></li> <li>例如 console.table(obj)可以把你的对象以可视化的表格形式进行输出 <img src="https://i.loli.net/2019/06/03/5cf4ab71e90e874049.gif" alt="0" /></li> <li>例如可以使用 console.time()和 console.timeEnd()方法来测量时间差 <img src="https://i.loli.net/2019/06/03/5cf4ab744d6a089649.png" alt="0" /></li> <li>另:console 命令行还内置了一些 API 方法,例如 queryObjects(),可以返回指定类型的对象下所有的实例化的对象 <img src="https://i.loli.net/2019/06/03/5cf4ab8a6b20972501.png" alt="0" /></li> </ul> <pre><code>queryObjects(Object); //返回所有object对象 queryObjects(Function); //返回所有函数 queryObjects(Array); //返回所有数组 </code></pre> <ul> <li>monitor(function)方法来追踪函数调用信息,当函数被执行,会输出追踪信息 <img src="https://i.loli.net/2019/06/03/5cf4ab9c55a3f55468.png" alt="0" /></li> <li>monitorEvents(el,eventType)方法来追踪事件 <img src="https://i.loli.net/2019/06/03/5cf4ab9eaba5f43869.png" alt="0" /></li> </ul> <h2>Sources 源文件面板</h2> <p>在 Sources 面板你可以:</p> <ul> <li>Debug : 在源代码面板中可以设置<strong>断点</strong>来调试 JavaScript ,比 console.log()调试更快速高效</li> <li>Devtools as IDE : 通过 Workspaces(工作区)连接本地文件来使用开发者工具的<strong>实时编辑器</strong></li> </ul> <h3>七种断点类型</h3> <ol> <li> <p>行断点:代码运行到当前行之前暂停执行</p> <pre><code>在源代码添加debugger关键字 或者 点击Sources面板中的源代码的行号 </code></pre> </li> <li> <p>条件行断点:当满足条件时才会触发该断点</p> <pre><code>右击Sources面板中的源代码的行号 选择“Add conditional breakpoint” </code></pre> <p><img src="https://i.loli.net/2019/06/03/5cf4eeebeb78835989.gif" alt="0" /></p> </li> <li> <p>DOM 断点</p> <pre><code>即Elements面板提及过的三种DOM断点: - 节点属性断点 - 节点删除断点 - 子树变更断点 </code></pre> <p><img src="https://i.loli.net/2019/06/03/5cf4abbb04c6c25181.gif" alt="0" /></p> </li> <li> <p>XHR/Fetch 断点</p> <pre><code>在页面发出XHR或Fetch请求前加断点 </code></pre> <p><img src="https://i.loli.net/2019/06/03/5cf4abc790a6244461.gif" alt="0" /></p> </li> <li> <p>Event Listener 事件监听断点</p> <pre><code>可以在所有类型的事件函数被出发前加断点 </code></pre> <p><img src="https://i.loli.net/2019/06/03/5cf4abc8c9efb50152.png" alt="0" /></p> </li> <li> <p>Exception 异常断点</p> <p><img src="https://i.loli.net/2019/06/03/5cf4abca96ac072660.png" alt="0" /></p> </li> <li> <p>Function 函数断点</p> <pre><code>把想调试的函数名作为参数,调用debug()函数,可以在每次执行该函数前暂停执行代码 </code></pre> <p><img src="https://i.loli.net/2019/06/03/5cf4abeb2a86948381.gif" alt="0" /></p> </li> </ol> <h3>Debug</h3> <ul> <li>函数调用栈 Call Stack:Call Stack 是 time traveling 的,即点击栈中的任一节点,当前的作用域和局部变量等信息,都会模拟至该节点执行时的状态</li> </ul> <p><img src="https://i.loli.net/2019/06/03/5cf4abfcc126341109.png" alt="0" /></p> <ul> <li>全局作用域 Global ,局部作用域 Local ,闭包作用域 Closure</li> </ul> <p><img src="https://i.loli.net/2019/06/03/5cf4ac0980d1016641.png" alt="0" /></p> <ul> <li>step over next function</li> <li>step into next function</li> <li>step out current function</li> <li>step (与 step over/into 的区别就是,step 会优先尝试 step into,当没有可步入的代码时,就会执行 step over)</li> </ul> <p><img src="https://i.loli.net/2019/06/03/5cf4ac1b7a4e440822.png" alt="0" /></p> <ul> <li>long resume:恢复执行,并将断点停用 500ms</li> </ul> <p><img src="https://i.loli.net/2019/06/03/5cf4ac3a7458f65851.png" alt="0" /></p> <ul> <li>Continue to here:继续执行至此行</li> </ul> <p><img src="https://i.loli.net/2019/06/03/5cf4ac4622fe745522.gif" alt="0" /></p> <ul> <li>Restart Frame:重新执行函数调用堆栈中的某一帧</li> </ul> <p><img src="https://i.loli.net/2019/06/03/5cf4ac556cc2358478.gif" alt="0" /></p> <ul> <li>行断点内的多个箭头:行内断点(行内的,可 step into 的 执行点</li> </ul> <p><img src="https://i.loli.net/2019/05/13/5cd969192e3cf64417.png" alt="" /></p> <h3>Workspace:Devtools as IDE 将更改持久化</h3> <ul> <li>在 sources 左侧的面板中选择<code>Filesystem</code>,点击<code>Add folder to workspace</code>,将你本地运行的站点的相关源文件添加到 Devtools 的工作区,会自动识别 Page 下和工作区下相对应的文件,在 devtools 更改文件并保存,即持久化保存(目前只支持自动识别,不支持添加映射)</li> <li>绿标文件:成功的映射到本地的文件,在 Styles 和 Sources 中的文件名前,都会添加绿色圆点作为标识 <img src="https://i.loli.net/2019/04/22/5cbd0771e5e31.png" alt="workspace.png" /> <img src="https://i.loli.net/2019/04/22/5cbd07bf14dc8.png" alt="workspace2.png" /></li> <li>目前 Devtools 已经支持 sass/scss、UglifyJS、Grunt、Coffescript、Closure 等等,暂时还不支持 webpack,和其他现代的复杂框架,如 react</li> <li>所有 sources 面板的文件,都可以右键选择<code>local modifications</code>,查看所有更改</li> <li>对 DOM 树的更改不会持久化至 html 文件:因为 dom 的最终表现,受到 html、css、javascript 的共同影响,DOM 树 !== HTML,因此可以在 sources 中直接更改 html 文件并保存</li> </ul> <h2>Network 面板</h2> <p><img src="https://i.loli.net/2019/04/22/5cbd4f884b14c.png" alt="network.png" /></p> <ul> <li>默认情况下,只要 DevTools 处于打开状态,DevTools 就会在 Network 面板中记录所有网络请求。</li> <li>左上红点按钮:停止记录网络请求</li> <li>第二个按钮:清空请求记录</li> <li>录像按钮:页面加载时捕获屏幕截图</li> <li>过滤按钮:显示/隐藏 过滤条件行</li> <li>View 中的两个按钮:第一个是切换请求列表中每行的显示样式(大小请求行),第二个是显示/隐藏瀑布图</li> <li>Group By Frame:是否根据不同的 frame 分类显示请求</li> <li>Preserve Log:保存显示跨页面的加载请求</li> <li>Disable Cache:禁用浏览器缓存,模拟新用户打开页面的体验</li> <li>Offline 是模拟断网离线的状态,其后的下拉框可以选择模拟其他网络状况,比如 2G,3G</li> </ul> <h3>筛选请求</h3> <ul> <li>filter 文本框中可输入请求的属性 对 请求进行过滤,多个属性用空格分隔</li> <li>支持过滤的属性: <ul> <li>domain。 仅显示来自指定域的资源。 可以使用通配符字符 (<code>*</code>) 纳入多个域。 例如,*.com 将显示来自以 .com 结尾的所有域名的资源。 DevTools 会使用其遇到的所有域填充自动填充下拉菜单。</li> <li>has-response-header。 显示包含指定 HTTP 响应标头的资源。 DevTools 会使用其遇到的所有响应标头填充自动填充下拉菜单。</li> <li>is。 使用 is:running 可以查找 WebSocket 资源。</li> <li>larger-than。 显示大于指定大小的资源(以字节为单位)。 将值设为 1000 等同于设置为 1k。</li> <li>method。 显示通过指定 HTTP 方法类型检索的资源。 DevTools 会使用其遇到的所有 HTTP 方法填充下拉菜单。</li> <li>mime-type。 显示指定 MIME 类型的资源。 DevTools 会使用其遇到的所有 MIME 类型填充下拉菜单。</li> <li>mixed-content。 显示所有混合内容资源 (mixed-content:all),或者仅显示当前显示的资源 (mixed-content:displayed)。</li> <li>scheme。 显示通过未保护 HTTP (scheme:http) 或受保护 HTTPS (scheme:https) 检索的资源。</li> <li>set-cookie-domain。 显示具有 Set-Cookie 标头并且 Domain 属性与指定值匹配的资源。 DevTools 会使用其遇到的所有 Cookie 域填充自动填充下拉菜单。</li> <li>set-cookie-name。 显示具有 Set-Cookie 标头并且名称与指定值匹配的资源。 DevTools 会使用其遇到的所有 Cookie 名称填充自动填充下拉菜单。</li> <li>set-cookie-value。 显示具有 Set-Cookie 标头并且值与指定值匹配的资源。 DevTools 会使用其遇到的所有 Cookie 值填充自动填充下拉菜单。</li> <li>status-code。 仅显示 HTTP 状态代码与指定代码匹配的资源。 DevTools 会使用其遇到的所有状态代码填充自动填充下拉菜单。</li> </ul> </li> <li>例如:mime-type:image/gif larger-than:1K 显示大于一千字节的所有 GIF</li> <li><code>Hide Data URLs</code>:隐藏 <a>data 类型的 url</a></li> </ul> <h3>瀑布图</h3> <ul> <li>瀑布图按时间线展示所有请求</li> <li>可以用鼠标拖动选中一段时间,只查看改时间线内的请求</li> <li>瀑布图中有两条竖线,一条蓝色,代表<a>DOMContentLoaded</a>事件发生的事件,一条红色代表<a>load</a>事件发生的时间点</li> </ul> <h3>分析请求/请求列表</h3> <ul> <li>重播请求:右键点击 Requests 表格中的请求 -&gt; <code>Replay XHR</code></li> <li>手动清除浏览器缓存:右键点击 Requests 表格中的任意位置 -&gt; 选择 <code>Clear Browser Cache</code></li> <li>手动清除浏览器 Cookie:右键点击 Requests 表格中的任意位置 -&gt; 选择 <code>Clear Browser Cookies</code></li> <li>自定义列表中展示的列</li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbd553d024cc.png" alt="network2.png" /></p> <ul> <li>请求行排序,默认按照瀑布图 start time 升序排序,即请求发起的时间点:</li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbd63427ece0.png" alt="networkOrder.png" /></p> <ul> <li> <p>每条请求,可以看到网络请求以及被清华求资源的全部信息:</p> <ul> <li>请求的一般信息:url、HTTP 方法(GET POST 等)、状态码、ip 地址</li> <li>请求相关:请求头、Initiator、Priority</li> <li>响应相关:响应头、响应内容</li> </ul> </li> <li> <p>Initiator:请求的来源/发起者。parser:一般来自解析器解析到的 html 页面内的请求;script:来自脚本文件的请求。鼠标悬浮到 Initiator 列中的文件名上,可以看到发起当前请求的堆栈轨迹,点击文件名,可以定位到直接发起请求的代码</p> </li> <li> <p>两个 size:在 size 列中,有两个数值,上面的较小值代表下载到的资源的大小,下面的较大值是资源解压后的大小。(例如 在 Content-Encoding 中可以看到的 gzip 和 br)</p> </li> <li> <p>按住<code>shift</code>鼠标悬浮在请求行上,变绿色的行是当前行的发起者,红色的行是当前行的依赖项。</p> </li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbd9945dd05b.png" alt="initiator.png" /></p> <ul> <li>Priority:High,Highest,Low。根据时间线中的蓝线和红线(DOMContentLoaded 和 load),以及请求的优先级,可以从结果的角度观察浏览器的加载流程。</li> </ul> <h3>Color Code:瀑布图中的几种颜色与代码</h3> <p><img src="https://i.loli.net/2019/04/22/5cbdc5acaff77.png" alt="colorCode.png" /></p> <ul> <li>Queueing 排队,请求未发出,正在等待。 浏览器在以下情况下对请求排队: <ul> <li>存在更高优先级的请求。</li> <li>此源已打开六个 TCP 连接,达到限值。 仅适用于 HTTP/1.0 和 HTTP/1.1(在 HTTP1 下浏览器一次最允许 6 个 TCP 连接,超出 6 个,就要 queue 排队)(优化 web 性能-&gt;避免 queue-&gt;合并资源请求)</li> <li>浏览器正在短暂分配磁盘缓存中的空间</li> </ul> </li> <li>Stalled/Blocking 停滞/阻塞,请求仍未发出。请求可能会因 Queueing 中描述的任何原因而停止。</li> <li>DNS Lookup dns 查找,浏览器正在解析请求的 IP 地址,每次有指向新 domian 的请求时,会有 dns 查找的时间消耗。</li> <li>Proxy negotiation 代理协商。 浏览器正在与代理服务器协商请求。</li> <li>initial connection/connecting 正在初始化连接 或 正在连接,包含 tcp 的三次握手的时间</li> <li>SSL 完成 SLL 握手所需要的时间</li> <li>Request sent/senting 正在发送请求,发请求所占的时间,通常只有几分之一毫秒。</li> <li>ServiceWorker Preparation。 浏览器正在启动 Service Worker。</li> <li>Request to ServiceWorker。 正在将请求发送到 Service Worker。</li> <li>Waiting (TTFB)。 浏览器正在等待响应的第一个字节。 TTFB 表示 Time To First Byte(至第一字节的时间)。 此时间包括 1 次往返延迟时间及服务器准备响应所用的时间。</li> <li>Content Download。 浏览器正在接收响应。</li> <li>Receiving Push。 浏览器正在通过 HTTP/2 服务器推送接收此响应的数据。</li> <li>Reading Push。 浏览器正在读取之前收到的本地数据。</li> </ul> <h3>DOMContentLoaded 和 load 事件</h3> <ul> <li>DOMContentLoaded — 浏览器已经完全加载了 HTML,DOM 树已经构建完毕,但是像是 <code>&lt;img loading="lazy" decoding="async"&gt;</code> 和样式表等外部资源可能并没有下载完毕。</li> <li>load — 浏览器已经加载了所有的资源(图像,样式表等)。</li> <li>beforeunload/unload -- 当用户离开页面的时候触发。</li> <li><a>更多</a></li> </ul> <h2>Performance 性能面板</h2> <ul> <li>performance 面板可以用于分析<code>运行时性能</code>(运行时强调的是与页面加载性能相区分)</li> <li>以隐身模式打开网页 (隐身模式可确保 Chrome 以干净的状态运行。例如,排除扩展对性能测量的影响</li> <li><a>Janky Animation demo :性能测试 demo</a></li> <li>视图 overview:</li> </ul> <p><img src="https://i.loli.net/2019/04/23/5cbf1d586fe21.png" alt="performance.png" /></p> <h3>RAIL 模型</h3> <ul> <li> <p><a>RAIL 模型</a>是一种性能模型,定义了四个维度的性能分析指标</p> </li> <li> <p><code>Response</code>:在<code>100 毫秒</code>以内响应(例如从点按到绘制)</p> </li> <li> <p><code>Animation</code>: 每秒生成 60 帧,每个帧的工作(从 JS 到绘制)完成时间小于 16 毫秒,达到人眼顺滑(例如滚动 拖动都是动画类型)(因为浏览器需要花费时间将新帧绘制到屏幕上,只有 <code>10 毫秒</code>来执行代码)</p> </li> <li> <p><code>Idle</code>:利用空闲时间完成推迟的工作(要实现第一条 response 在 100ms 内响应,Main 主线程 JS 工作应该小于 <code>50ms</code>,剩余的时间将主线程的控制从 js 返回给浏览器执行其像素管道、对用户输入作出反应等,因此最佳实践是将 js 的工作分成不大于 50 毫秒的块,如果用户开始交互,优先级最高的事项是响应用户。</p> </li> <li> <p><code>Load</code>:在 <code>1000 毫秒</code>以内呈现内容(无需完整加载,启用渐进式渲染,将非必需的加载推迟到空闲时间段</p> </li> <li> <p>通过 performance 面板,可以得到这四个维度的分析数据</p> </li> </ul> <h3>控制区</h3> <p><img src="https://i.loli.net/2019/05/01/5cc9642fa35b5.png" alt="" /></p> <ul> <li>点击<code>录制按钮</code>或者<code>开始录制并刷新页面按钮</code>,可以在控制区下方得到全部性能分析结果</li> <li>其中除了最下方的详细信息窗格以外,分析结果都是以时间为轴</li> <li>可以在 overview 窗格拖动鼠标,选择某段时间的分析结果</li> <li>滚动鼠标滚轮,缩放/移动选中事件</li> <li>在火焰图窗格,按住<code>shift</code>,滚动鼠标滚轮,可以上下</li> <li>在火焰图窗格,也可以直接左右拖动图表</li> <li>或者用<code>W A S D</code>按键控制缩放移动</li> <li><code>Disable JavaScript samples</code>默认情况,在<code>Main</code>主线程的火焰图中,会详细记录 js 函数之间的调用栈,可以开启此选项禁用调用栈记录</li> <li><code>Enable advanced paint instrumentation</code>启用高级绘图工具,可以在分析结果的<code>Frames</code>中的每一帧的详细结果中看到<code>Layer</code>选项卡,其中有选中帧的详细图层信息;也可以在<code>Main</code>主线程火焰图中选中绿色的<code>Paint</code>事件,在最底部详细信息的<code>Paint Profile</code>选项卡中,看到详细的页面绘制过程分析</li> <li><code>Collect garbage</code>控制器最右的垃圾桶图标,是强制执行垃圾回收,对于监控内存比较有用</li> </ul> <h3>FPS 图表 - Frames Per Seconds</h3> <p><img src="https://i.loli.net/2019/05/05/5ccee0f3335be.png" alt="" /></p> <ul> <li>FPS 图表中,绿色代表帧率高低,参考<code>RAIL</code>模型,帧率&gt;=60 时,用户能体验的顺滑的网页</li> <li>红色出现 代表有掉帧情况</li> </ul> <h3>CPU 图表</h3> <p><img src="https://i.loli.net/2019/05/05/5ccee13cd4479.png" alt="" /></p> <ul> <li>CPU 图表中,不同的颜色代表不同事件对 CPU 的占用,颜色信息如图</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccee05903554.png" alt="" /></p> <ul> <li>当 CPU 长时间被占满,就是当前网页性能需要优化的信号</li> </ul> <h3>SCREENSHOTS</h3> <ul> <li>鼠标在<code>FPS,CPU,NET</code>图表悬浮时,会展示出鼠标对应时间点的网页截屏,左右移动鼠标可以看到网页变化的重播效果</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccee37b9a4b3.gif" alt="" /></p> <h3>HEAP</h3> <p><img src="https://i.loli.net/2019/05/05/5ccee6f4b968d.png" alt="" /></p> <ul> <li>在 HEAP 图表中可以看到 JS 内存占用情况,与下方的 memory 窗格中的<code>JS Heap</code>相对应</li> <li>在 Memory 窗格还可以看到 Document 文档、Nodes DOM 节点、监听器、GPU 内存的习份内存统计</li> </ul> <h3>Frames</h3> <ul> <li>点击三角箭头展开<code>Frames</code>区域,鼠标悬浮/点击绿色方块,可以看到该特定帧的帧率和渲染耗时,当 FPS 低于 60,表明当前帧的渲染效率较低</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccee92a52b29.png" alt="" /></p> <h3>Main</h3> <ul> <li>点击三角箭头展开<code>Main</code>区域,可以看到主线程上事件的<code>火焰图</code></li> <li>x 轴是时间,每一块代表一个事件,y 轴代表堆栈,事件的上下堆叠,代表上层事件引发/调用了下层事件</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5cceec8b11f7f.png" alt="" /></p> <ul> <li>通过调用堆栈,可以找出导致低性能的事件及其源码位置</li> <li>当事件块出现红色三角,可以点击三角查看该事件的性能相关警告信息,并定位到引起警告的代码</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5cceef6801439.png" alt="" /></p> <p><img src="https://i.loli.net/2019/05/05/5ccef1a7c2c2a.gif" alt="" /></p> <ul> <li>点击<code>Animation Frame Fired</code>事件,可以在最下方<code>Summary</code>窗格查看触发动画事件的详细信息,点击<code>Initiator</code>后的<code>reveal</code>链接,会高亮到引起动画事件的事件</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccef012a3dba.gif" alt="" /></p> <h3>性能相关扩展</h3> <ul> <li><a>网页性能-性能模型/加载/渲染/审计/优化</a></li> <li><a>the-anatomy-of-a-frame - 一个帧的剖析</a></li> <li><a>常见的时间线事件参考</a></li> </ul> 前端https://www.scarsu.com/devtools_rookie_intro/#post-comment/给UI看的WEB字体指南https://www.scarsu.com/web_fonts/https://www.scarsu.com/web_fonts/UI小姐姐动不动就丢给你奇奇怪怪的字体和各种尺寸的图标?快把这些文章丢改她看Sun, 02 Feb 2020 00:00:00 GMT<h1>WEB中的字体</h1> <h3>前言</h3> <pre><code>某天,隔壁新来的漂亮UI小妹妹又优雅的丢给你一个压缩包,你满心欢喜的解压 才发现又是新页面的需求 然后你摸了摸光亮的脑门,捋了捋稀疏的鬓角,吭哧吭哧开始画页面... 咦?pingfangsc medium,pingfangsc bold,pingfangsc light...?? (同理可换成 sans serif,microsoft yahei) 常用windows的你傻傻分不清楚小妹妹选定的mac字体 这是同一个字体吗?font-weight还要写吗?不写的话win上显示就不一样了呀... 于是你只能再打开小妹妹的聊天面板,码下一大段话“不同系统默认字体不一样...巴拉巴拉...web安全字体...备选字体集...字体文件包” 然后在你的小本本上,画上第1025个圈圈,记录并预测下,到底还要跟多少UI做好字体交易... 虽然你会为跟小妹妹进行了一次深入性的技术沟通 而心情大好,但是 终将有一天,你的耐心会消耗殆尽,然后把这篇文章,丢到部门UI群 从那以后,UI小妹妹们... ... 给你授予了“最矫情的技术没有之一”的称号 并 丢了更多pingfangsc给你🐶 </code></pre> <h3>WEB 安全字体</h3> <p>不同操作系统内置的字体是不同的,甚至差异很大,例如: <img src="/images/picgo/web_font01.png" alt="OS字体差异图" /></p> <p><img src="/images/picgo/20230708232300.png" alt="WEB中文安全字体" /></p> <p>win7和mac下,只有十种字体重合,Windows XP中甚至没有其中的Palatino 和Trebuchet MS字体.....</p> <p>因此为了兼容性考虑,最安全的字体有:</p> <ul> <li>Arial</li> <li>Courier New</li> <li>Georgia</li> <li>Times New Roman</li> <li>Verdana</li> <li>...</li> <li>随着操作系统的发展更新,这个数据也不是最准确的,可选的可能比上面五个多一些,请以实际测试为准</li> </ul> <h3>备选字体组合</h3> <p>当不确定网页用户电脑上是否有某种字体时,可以使用字体组合,提供备选的字体:</p> <pre><code>font-family: "Times New Roman", Times, serif; </code></pre> <p>备选的意思可以参考备胎,就是:</p> <p>当浏览器在系统中找不到第一种字体时,会自动去使用第二种,依次类推...</p> <h3>自定义字体</h3> <p>如果对某种不通用字体有刚需,可以使用自定义字体。</p> <ol> <li>UI需要提供字体的woff和eot格式源文件(需要考虑文件太大会影响网页加载)</li> <li>前端需要在css中自定义@font-face(不用担心浏览器兼容性)</li> </ol> <p>至于为什么是woff和eot:</p> <pre><code>TureTpe(.ttf)格式: .ttf字体是Windows和Mac系统的最常见的字体,是一种RAW格式,不为网站优化 OpenType(.otf)格式: .otf字体被认为是一种原始的字体格式,其内置在TureType的基础上,所以也提供了更多的功能 Web Open Font Format(.woff)格式: .woff字体是Web字体中最佳格式,他是一个开放的TrueType/OpenType的压缩版本,同时也支持元数据包的分离 Embedded Open Type(.eot)格式: .eot字体是IE专用字体,可以从TrueType创建此格式字体 SVG(.svg)格式: .svg字体是基于SVG字体渲染的一种格式 这就意味着在@font-face中我们至少需要.woff,.eot两种格式字体,甚至还需要.svg等字体达到更多种浏览版本的支持。 </code></pre> <p>不同浏览器对不同字体文件格式的兼容性也不同:</p> <p><img src="https://www.scarsu.com/images/gitbook/web_font02.png" alt="OS字体文件兼容性图" /></p> <p><strong>总结来说:eot(供ie使用) + woff(供其他现代浏览器使用)是最佳组合,如果要兼容更多老版本浏览器/移动端浏览器可以加上ttf或svg)</strong></p> <p>定义font-face语法:</p> <pre><code>@font-face { font-family: &lt;YourWebFontName自定义的字体名&gt;; src: &lt;source&gt; [&lt;format&gt;][,&lt;source&gt; [&lt;format&gt;]]*; [font-weight: &lt;weight&gt;]; [font-style: &lt;style&gt;]; } /*source:字体文件路径*/ /*format:字体文件格式 eg. ttf,otf,woff,eot,svg...*/ /*示例*/ @font-face { font-family: 'YourWebFontName'; src: url('YourWebFontName.eot'); /* IE9兼容模式 */ src: url('YourWebFontName.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ url('YourWebFontName.woff') format('woff'), /* 现代浏览器 */ url('YourWebFontName.ttf') format('truetype'), /* Safari, Android, iOS */ url('YourWebFontName.svg#YourWebFontName') format('svg'); /* 老版本 iOS */ } </code></pre> <h3>总结</h3> <ol> <li>UI最好就用最安全的几种通用字体</li> <li>如果想用不通用的字体 <ul> <li>要么:提供备选字体</li> <li>要么:提供字体文件(eot+woff+[svg/ttf]),且要考虑选择字体源文件体积较小的字体</li> </ul> </li> </ol> 前端https://www.scarsu.com/web_fonts/#post-comment/ML08 | 多分类问题训练:IRIS鸢尾花分类问题https://www.scarsu.com/fed_ml_08_iris/https://www.scarsu.com/fed_ml_08_iris/Javascript玩转机器学习08Thu, 09 Jan 2020 00:00:00 GMT<h2>多分类问题</h2> <ul> <li> <p>手写数字分类:10种分类</p> </li> <li> <p>图片分类:成千上万种分类</p> </li> <li> <p>多种特征:需要多层神经网络</p> </li> <li> <p>多种分类输出:需要在输出层加softMax函数</p> </li> </ul> <h2>鸢尾花(iris)分类问题</h2> <ul> <li>著名的数据集,诞生了很久,被无数科学家用来验证自己的算法</li> <li>三种分类(输出):山鸢尾,变色鸢尾,Virginica鸢尾</li> <li>四种特征(输入):花瓣长、宽、花萼长、宽</li> </ul> <h2>加载IRIS数据集(训练集与验证集)</h2> <ul> <li>用脚本生成IRIS数据集:训练集+验证集</li> </ul> <pre><code>//生成:训练集特征,训练集标签,验证集特征,验证集标签(数据类型为tensor) const [xTrain,yTrain,xTest,yTest] = getIrisData(0.15); xTrain.print(); yTrain.print(); xTest.print(); yTest.print(); console.log(IRIS_CLASSES); </code></pre> <ul> <li>打印结果:</li> </ul> <p><img src="/images/ai/42.png" alt="image" /></p> <h2>定义模型结构:带有softMax激活函数的多层神经网络</h2> <ul> <li>初始化一个神经网络模型</li> </ul> <pre><code>//初始化模型 const model = tf.sequential(); </code></pre> <ul> <li>为模型添加两个层</li> <li>设计层的神经元个数、inputShape、激活函数</li> </ul> <pre><code>//添加隐藏层:全链接层 model.add(tf.layers.dense({ units:10, //10个神经元,超参数 inputShape:[xTrain.shape[1]], activation:'sigmoid', })); //添加输出层:全链接层 model.add(tf.layers.dense({ units:3, //必须是输出类别的个数 // inputShape:[yTrain.shape], //除了第一层以外 都不需要设计inputShape,会根据上一层的输出自动设计 activation:'softmax', //softmax 激活函数 适用于多种分类输出层 })); </code></pre> <h2>交叉熵损失函数</h2> <ul> <li>交叉熵损失函数 <strong>Cross-Entropy</strong>:是LogLoss对数损失函数的多分类版本,都用于度量分类神经网络模型的性能。</li> <li>当分类数为2时,交叉熵损失=对数损失。</li> </ul> <p><img src="/images/ai/43.png" alt="image" /></p> <h2>定义损失函数、优化器、准确度度量</h2> <pre><code> //设置损失函数,增加训练过程中的“准确度”度量 model.compile({ loss:'categoricalCrossentropy', optimizer: tf.train.adam(0.1), metrics: ['accuracy'] }); </code></pre> <h2>训练模型并可视化</h2> <pre><code>//训练并可视化 await model.fit(xTrain,yTrain,{ epochs:100, validationData:[xTest,yTest], callbacks:tfvis.show.fitCallbacks( {name:''}, ['loss','val_loss','acc','val_acc'], {callbacks:['onEpochEnd']}, ), }) </code></pre> <ul> <li>训练过程:</li> </ul> <p><img src="/images/ai/44.png" alt="image" /></p> <h2>模型多分类预测</h2> <pre><code>window.predict = (form)=&gt;{ const input = tf.tensor([[ form.a.value * 1, form.b.value * 1, form.c.value * 1, form.d.value * 1, ]]); debugger; const pred = model.predict(input); pred.print(); alert(`预测结果${IRIS_CLASSES[pred.argMax(1).dataSync(0)]}`); } </code></pre> <p><img src="/images/ai/45.png" alt="image" /></p> <hr /> <p><a>代码仓库</a></p> 前端https://www.scarsu.com/fed_ml_08_iris/#post-comment/ML07 | XOR回归训练:多层神经网络https://www.scarsu.com/fed_ml_07_xor_regression/https://www.scarsu.com/fed_ml_07_xor_regression/Javascript玩转机器学习07Tue, 07 Jan 2020 00:00:00 GMT<h2>XOR 异或逻辑回归</h2> <ul> <li>不是线性问题</li> <li>需要多层神经网络+激活函数来解决</li> </ul> <p><img src="/images/ai/36.png" alt="image" /></p> <h2><a>Google Playground网站</a></h2> <ul> <li>用TFJS写的 可视化学习机器学习的网站</li> </ul> <p><img src="/images/ai/37.png" alt="image" /></p> <h2>加载XOR数据集</h2> <pre><code>//调脚本接口生成模拟数据 const data = getData(400); console.log(data); </code></pre> <ul> <li>模拟数据 数据结构: <img src="/images/ai/38.png" alt="image" /></li> </ul> <pre><code>//可视化 tfvis.render.scatterplot( { name: "XOR训练数据" }, { values: [ data.filter(p =&gt; p.label === 1), data.filter(p =&gt; p.label === 0) ] } ); </code></pre> <ul> <li>可视化结果</li> </ul> <p><img src="/images/ai/39.png" alt="image" /></p> <h2>定义模型结构:多层神经网络</h2> <ul> <li>初始化一个神经网络模型</li> <li>为模型添加两个层:隐藏层+输出层</li> <li>设计层的激活函数、inputShape、神经元个数</li> </ul> <pre><code>//初始化一个 sequential model const mdoel = tf.sequential(); //添加一个隐藏层(全连接层) mdoel.add( tf.layers.dense({ units: 4, inputShape: [2], //只有第一层需要设置inputShape activition: "relu" }) ); //添加一个输出层(全连接层) model.add( tf.layers.dense({ units: 1, activition: "sigmoid" //需要输出[0,1]之间的概率所以选sigmoid }) ); </code></pre> <ul> <li>定义模型的损失函数和优化器</li> </ul> <pre><code>//定义模型的损失函数和优化器 model.compile({ loss: tf.losses.logLoss, optimizer: tf.train.adam(0.1) }); </code></pre> <h2>训练模型并预测</h2> <ul> <li>训练数据转换为tensor</li> </ul> <pre><code>//训练数据转换为tensor const inputs = tf.tensor(data.map(p =&gt; [p.x, p.y])); const labels = tf.tensor(data.map(p =&gt; p.label)); </code></pre> <ul> <li>训练模型并可视化训练过程</li> </ul> <pre><code>//训练 await model.fit(inputs, labels, { epochs: 10, callbacks: tfvis.show.fitCallbacks({ name: "XOR训练过程" }, ["loss"]) }); </code></pre> <ul> <li> <p>训练过程 <img src="/images/ai/40.png" alt="image" /></p> </li> <li> <p>进行预测</p> </li> </ul> <pre><code>//预测 window.predict = form =&gt; { const pred = model.predict( tf.tensor([[form.x.value * 1, form.y.value * 1]]) ); alert(`预测结果:${pred.dataSync()[0]}`); }; </code></pre> <ul> <li>预测结果</li> </ul> <p><img src="/images/ai/41.png" alt="image" /></p> <hr /> <p><a>代码仓库</a></p> 前端https://www.scarsu.com/fed_ml_07_xor_regression/#post-comment/ML06 | 逻辑回归训练https://www.scarsu.com/fed_ml_06_logistic_regression/https://www.scarsu.com/fed_ml_06_logistic_regression/Javascript玩转机器学习06Mon, 06 Jan 2020 00:00:00 GMT<h2>逻辑回归简介</h2> <ul> <li>解决分类问题,输出一个概率[0,1]</li> </ul> <p><img src="/images/ai/30.png" alt="image" /></p> <h2>加载二分类数据集</h2> <ul> <li>使用脚本生成二分类数据集</li> </ul> <pre><code>//利用脚本生成400组二分类数据 const data = getData(400); console.log(data); </code></pre> <ul> <li>数据结构如图:</li> </ul> <p><img src="/images/ai/31.png" alt="image" /></p> <ul> <li>可视化二分类数据集(散点图)</li> </ul> <pre><code>//可视化为散点图 tfvis.render.scatterplot( {name:'二分类逻辑回归 训练数据'}, { values:[ data.filter(p=&gt;p.label === 1), data.filter(p=&gt;p.label === 0), ] } ) </code></pre> <ul> <li>可视化效果:</li> </ul> <p><img src="/images/ai/32.png" alt="image" /></p> <h2>定义模型结构:带有激活函数的单个神经元</h2> <ul> <li>初始化一个sequential神经网络模型</li> </ul> <pre><code>//添加一个sequential神经网络模型 const model = tf.sequential(); </code></pre> <ul> <li>为模型添加层,设计层的神经元个数、inputShape、激活函数(<code>model.add</code>)</li> </ul> <pre><code>//为模型添加一个 dense全链接层(点乘 偏置 激活函数 适合用于二分类回归) model.add(tf.layers.dense({ units:1, //神经元个数 inputShape:[2], //输入的tensor的shape:长度为2的一维数组 activation:'sigmoid', //sigmoid这种激活函数的曲线y值范围始终在[0,1] })); </code></pre> <h2>对数损失函数 Log Loss</h2> <ul> <li>利用<code>wiki.fast.ai</code>人工智能教学网站,理解<a>对数损失函数</a></li> <li>对数损失函数:用于测量预测值在[0,1]的分类模型的性能</li> <li>如下图为:标签为1的预测值的对数损失函数曲线,预测越接近真实值1,损失越小,越接近0 ,损失越大:</li> </ul> <p><img src="/images/ai/33.png" alt="image" /></p> <h2>用TFJS API设置损失函数为:LogLoss(<code>model.compile</code>)</h2> <pre><code>//设置损失函数为:LogLoss 对数损失函数 model.compile({loss:tf.losses.logLoss}); </code></pre> <h2>设置超参数,训练模型(<code>model.fit</code>)</h2> <pre><code>//设置超参数 训练模型 await model.fit(inputs, labels,{ batchSize:40, epochs:50, callbacks:tfvis.show.fitCallbacks( {name:'训练过程'}, ['loss'] ) }) </code></pre> <ul> <li>训练过程截图:</li> </ul> <p><img src="/images/ai/34.png" alt="image" /></p> <h2>预测</h2> <ul> <li>编写前端界面输入待预测数据</li> <li>使用训练好的模型进行预测(<code>model.predict</code>)</li> </ul> <pre><code>&lt;form action="" onsubmit="predict(this);return false;"&gt; x: &lt;input type="text" name="x" /&gt; y: &lt;input type="text" name="y" /&gt; &lt;button type="submit"&gt;预测&lt;/button&gt; &lt;/form&gt; </code></pre> <pre><code>window.predict = (form) =&gt; { const pred = model.predict(tf.tensor([[form.x.value * 1, form.y.value * 1]])); alert(`预测结果:${pred.dataSync()[0]}`); }; </code></pre> <ul> <li>输入2,2 预测结果:</li> </ul> <p><img src="/images/ai/35.png" alt="image" /></p> <hr /> <p><a>代码仓库</a></p> 前端https://www.scarsu.com/fed_ml_06_logistic_regression/#post-comment/ML05 | 归一化https://www.scarsu.com/fed_ml_05_normalize/https://www.scarsu.com/fed_ml_05_normalize/Javascript玩转机器学习05Sun, 05 Jan 2020 00:00:00 GMT<h2>归一化:</h2> <ul> <li>将大数量级<code>特征</code>转化到较小的数量级下,通常是[0,1]或[-1,1]</li> </ul> <h2>为什么要归一化:</h2> <ul> <li>绝大多数TensorFlow.js的模型都不是给特别大的数设计的</li> <li>将不同数量级的<code>特征</code>转换到统一数量级,避免某个特征影响过大</li> </ul> <h2>归一化任务实例-身高体重预测:</h2> <ul> <li>准备身高体重数据,可视化</li> </ul> <pre><code>//模拟标签和特征 const heights=[150,160,170,180]; const weights=[40,50,60,70]; //可视化数据 tfvis.render.scatterplot( {name:'身高体重预测'}, {values:heights.map((x,i)=&gt;({x,y:weights[i]}))}, { xAxisDomain:[140,190], yAxisDomain:[30,80], } ) </code></pre> <ul> <li>用TFJS的API<code>归一化</code>数据</li> </ul> <pre><code>//将数据转换为tensor 并归一化 const inputs = tf.tensor(heights).sub(150).div(30); const labels = tf.tensor(weights).sub(40).div(30); inputs.print(); labels.print(); </code></pre> <ul> <li>归一化后数据:</li> </ul> <p><img src="/images/ai/28.png" alt="image" /></p> <ul> <li>训练模型并预测</li> </ul> <pre><code>//创造一个连续模型 const model = tf.sequential(); model.add(tf.layers.dense({units:1,inputShape:[1]})); //添加一个全连接层(点乘权重+偏置) model.compile({loss:tf.losses.meanSquaredError,optimizer:tf.train.sgd(0.1)}); //设置:损失函数为均方误差MSE,优化器为随机梯度下降SGD,学习速率为0.1,学习率是一个需要调整优化的超参数 await model.fit(inputs, labels, { batchSize: 4, //批量训练的数据集大小(超参数,需要不断调整试验) epochs: 100, //迭代实验次数(超参数,需要不断调整试验) callbacks: tfvis.show.fitCallbacks({ name: "训练过程" }, ["loss"]) }); //将待预测数据190转为Tensor,用训练好的模型进行预测 const output = model.predict(tf.tensor([190]).sub(150).div(30)); output.print(); </code></pre> <ul> <li>将结果反归一化为正常数据</li> </ul> <pre><code>//将输出的Tensor反归一化并转为普通数据并显示 alert(`如果身高是190cm,预测体重为${output.mul(30).add(40).dataSync()}kg`); </code></pre> <ul> <li>预测结果:</li> </ul> <p><img src="/images/ai/29.png" alt="image" /></p> <ul> <li>上述例子中,归一化的关键步骤就是:</li> </ul> <pre><code>减去 min(最小值) 除以 diff(最大值最小值的差) </code></pre> <ul> <li>反归一化的关键步骤就是归一化的反操作:</li> </ul> <pre><code>乘以 diff 加上 min </code></pre> <hr /> <p><a>代码仓库</a></p> 前端https://www.scarsu.com/fed_ml_05_normalize/#post-comment/ML04 | 线性回归训练https://www.scarsu.com/fed_ml_04_linear_regression/https://www.scarsu.com/fed_ml_04_linear_regression/Javascript玩转机器学习04Thu, 02 Jan 2020 00:00:00 GMT<h2>线性回归是什么</h2> <ul> <li>一种统计分析方法</li> <li>用于确定两种(或以上)变量间相互依赖的<strong>定量关系</strong></li> <li>eg.身高体重预测(两种变量)、房价预测(多变量)</li> </ul> <h2>操作步骤</h2> <ul> <li>准备、可视化:训练数据</li> <li>用TensorFlow.js的API构建一个简单的神经网络</li> <li>训练模型 并 预测</li> </ul> <h2>前置条件</h2> <ul> <li>最新版本chrome</li> <li>代码编辑器(eg.VSCODE</li> <li>基础的前端、神经网络知识</li> </ul> <h2>准备、可视化:训练数据(实操)</h2> <ul> <li>准备线性回归训练数据(特征、标签)</li> <li>使用tfvis可视化训练数据(tfvis是一个神经网络可视化库)</li> </ul> <pre><code>&lt;!-- linear-regression/index.html--&gt; &lt;script src="script.js"&gt;&lt;/script&gt; </code></pre> <pre><code>// linear-regression/script.js import * as tfvis from "@tensorflow/tfjs-vis"; window.onload = () =&gt; { const xs = [1, 2, 3, 4]; //input const ys = [1, 3, 5, 7]; //output tfvis.render.scatterplot( { name: "线性回归训练数据" }, { values: xs.map((x, i) =&gt; ({ x, y: ys[i] })) }, { xAxisDomain: [0, 5], yAxisDomain: [0, 9] }, ); }; </code></pre> <pre><code>-- bash parcel li*/*.html </code></pre> <h2>可视化效果</h2> <p><img src="/images/ai/17.png" alt="可视化效果" /></p> <h2>定义单个神经元的神经网络模型</h2> <ul> <li>初始化一个神经网络模型(model)</li> <li>为模型添加<strong>层</strong>(layer)</li> <li>设计<strong>层</strong>的神经元个数和<strong>inputShape</strong></li> </ul> <pre><code>import * as tfjs from "@tensorflow/tfjs"; import * as tfvis from "@tensorflow/tfjs-vis"; window.onload = () =&gt; { const xs = [1, 2, 3, 4]; //input const ys = [1, 3, 5, 7]; //output tfvis.render.scatterplot( { name: "线性回归训练数据" }, { values: xs.map((x, i) =&gt; ({x, y:ys[i]})) }, {xAxisDomain:[0,5],yAxisDomain:[0,9]} ); const model = sf.sequential(); //创造一个连续模型 model.add(tf.layers.dense({units:1,inputShape:[1]})); //添加一个全连接层(点乘权重+偏置) }; </code></pre> <h2>损失函数:均方误差(MSE-MeanSquaredError)</h2> <ul> <li> <p>利用<a>google ML playground</a> 理解<strong>损失函数</strong>与<strong>均方误差</strong>:</p> </li> <li> <p><strong>损失函数</strong>用于计算预测值与实际值差距</p> </li> </ul> <p><img src="/images/ai/18.png" alt="预测值、实际值、损失" /></p> <ul> <li><strong>均方误差</strong>(meanSquaredError)是一种损失函数</li> </ul> <p><img src="/images/ai/19.png" alt="MSE" /></p> <ul> <li>在TensorFlow.js中设置损失函数</li> </ul> <pre><code>import * as tfjs from "@tensorflow/tfjs"; import * as tfvis from "@tensorflow/tfjs-vis"; window.onload = () =&gt; { const xs = [1, 2, 3, 4]; //input const ys = [1, 3, 5, 7]; //output tfvis.render.scatterplot( { name: "线性回归训练数据" }, { values: xs.map((x, i) =&gt; ({x, y:ys[i]})) }, {xAxisDomain:[0,5],yAxisDomain:[0,9]} ); const model = sf.sequential(); //创造一个连续模型 model.add(tf.layers.dense({units:1,inputShape:[1]})); //添加一个全连接层(点乘权重+偏置) model.compile({loss:tf.losses.meanSquaredError}) //设置损失函数为均方误差MSE }; </code></pre> <h2>优化器:随即梯度下降(SGD)</h2> <ul> <li> <p>利用<a>google ML playground</a> 理解<strong>优化器</strong>与<strong>随机梯度下降</strong>:</p> </li> <li> <p>迭代试错:</p> </li> </ul> <p><img src="/images/ai/20.png" alt="迭代试错" /></p> <ul> <li>梯度下降法:</li> </ul> <p><img src="/images/ai/21.png" alt="梯度下降法" /></p> <ul> <li>SGD</li> </ul> <p><img src="/images/ai/22.png" alt="SGD" /></p> <ul> <li>在TensorFlow.js中设置<strong>优化器</strong></li> </ul> <pre><code>import * as tfjs from "@tensorflow/tfjs"; import * as tfvis from "@tensorflow/tfjs-vis"; window.onload = () =&gt; { const xs = [1, 2, 3, 4]; //input const ys = [1, 3, 5, 7]; //output tfvis.render.scatterplot( { name: "线性回归训练数据" }, { values: xs.map((x, i) =&gt; ({x, y:ys[i]})) }, {xAxisDomain:[0,5],yAxisDomain:[0,9]} ); const model = sf.sequential(); //创造一个连续模型 model.add(tf.layers.dense({units:1,inputShape:[1]})); //添加一个全连接层(点乘权重+偏置) model.compile({loss:tf.losses.meanSquaredError,optimizer:tf.train.sgd}); //设置:损失函数为均方误差MSE,优化器为随机梯度下降SGD }; </code></pre> <h2>训练模型并可视化训练过程</h2> <ul> <li>将训练数据转为tensor</li> <li>训练模型</li> <li>用<strong>tfvis</strong>可视化训练过程</li> </ul> <pre><code>import * as tf from "@tensorflow/tfjs"; import * as tfvis from "@tensorflow/tfjs-vis"; window.onload = async () =&gt; { const xs = [1, 2, 3, 4]; //input const ys = [1, 3, 5, 7]; //output tfvis.render.scatterplot( { name: "线性回归训练数据" }, { values: xs.map((x, i) =&gt; ({x, y:ys[i]})) }, {xAxisDomain:[0,5],yAxisDomain:[0,9]} ); const model = tf.sequential(); //创造一个连续模型 model.add(tf.layers.dense({units:1,inputShape:[1]})); //添加一个全连接层(点乘权重+偏置) model.compile({loss:tf.losses.meanSquaredError,optimizer:tf.train.sgd(0.1)}); //设置:损失函数为均方误差MSE,优化器为随机梯度下降SGD,学习速率为0.1,学习率是一个需要调整优化的超参数 const inputs = tf.tensor(xs); const labels = tf.tensor(ys); await model.fit(inputs, labels,{ batchSize: 4, //批量训练的数据集大小(超参数,需要不断调整试验) epochs:100, //迭代实验次数(超参数,需要不断调整试验) callbacks:tfvis.show.fitCallbacks( {name:'训练过程'}, ['loss'], ) }); }; </code></pre> <ul> <li>批量处理size设置为1,训练初期会有明显抖动</li> </ul> <p><img src="/images/ai/23.png" alt="" /></p> <p><img src="/images/ai/24.png" alt="" /></p> <ul> <li>批量处理size设置为4,训练曲线比较平滑</li> </ul> <p><img src="/images/ai/25.png" alt="" /></p> <p><img src="/images/ai/26.png" alt="" /></p> <h2>进行预测</h2> <ul> <li>将待预测数据转为Tensor</li> <li>用训练好的模型进行预测</li> <li>将输出的Tensor转为普通数据并显示(模型的输入输出都是模型)</li> </ul> <pre><code> const output = model.predict(tf.tensor([5])); //将待预测数据5转为Tensor,用训练好的模型进行预测 output.print(); console.log(output.dataSync()); //将输出的Tensor转为普通数据并显示 </code></pre> <p><img src="/images/ai/27.png" alt="预测结果" /></p> <hr /> <p><a>代码仓库</a></p> 前端https://www.scarsu.com/fed_ml_04_linear_regression/#post-comment/贫穷的本质:我们为什么摆脱不了贫穷读书输出https://www.scarsu.com/poor_economics/https://www.scarsu.com/poor_economics/2019诺贝尔经济学家获奖作品、贫穷的本质&如何逃离贫穷陷阱Thu, 02 Jan 2020 00:00:00 GMT<h2>简介</h2> <ul> <li> <p>作者[印度]阿比吉特·班纳吉(Abhijit V.Banerjee)、[法]埃斯特·迪弗洛 (Esther Duflo)</p> </li> <li> <p>两位作者深入五大洲多个国家的穷人世界,调查贫困人群最集中的18个国家和地区,从穷人生活的多个方面,探寻贫穷真正的根源</p> </li> <li> <p>该书用九章大篇幅,从<strong>营养、健康、教育、生育、风险管理、贷款、存款、创业、政治参与</strong>等九个方面探讨穷人的生存、选择和突围,以及援助、制度对穷人的意义。</p> </li> <li> <p>为什么穷人吃不饱饭还要买电视?</p> </li> <li> <p>为什么他们的孩子即使上了学也不爱学习?</p> </li> <li> <p>为什么他们放着免费的健康生活不去享受,却要自己花钱买药?</p> </li> <li> <p>为什么他们能创业却难以守业?</p> </li> <li> <p>为什么大多数人认为小额信贷、穷人银行没什么效用?</p> </li> </ul> <hr /> <p>这本书太难啃了,未完待续</p> 个人成长https://www.scarsu.com/poor_economics/#post-comment/State of JS | 2019年度javascript行业报告https://www.scarsu.com/2019_javascript_report/https://www.scarsu.com/2019_javascript_report/stateofjs团队曾以为Javascript生态圈已经趋于稳定,2018是他们的最后一次行业调查,但事实是,Javascript仍没有停下变化的脚步Tue, 31 Dec 2019 00:00:00 GMT<h2>作者前言</h2> <ul> <li><a>stateofjs网址</a></li> <li>2018年,我第一次关注stateofjs调查,目的是通过真实数据,更真实广泛的了解Javascript生态圈的变化,便于自己对于主流技术的了解和<strong>自检</strong>。</li> <li>2018的调查,20,268参与者中,只有75位中国地区开发者,比例是0.37%。</li> <li>今年,我也参与到了调查当中,提供了一份我的数据。</li> <li>今年总共有21,717位开发者参与调查,其中有247位中国地区的开发者,比例是1.3%。</li> <li>中国地区开发者比例,说明这个调查并不能反映中国地区的Javascript真实发展状况,但是比例的增加从侧面说明了中国开发者正在向国际靠拢,希望有越来越多的中国开发者能跨越国界,走向世界技术圈</li> <li>⭐今年的报告,有一项新增的数据,引起了我的关注,就是<strong>Javascript开发者信息源</strong>,这是我根据报告数据整理出来的<a>Javascript开发者信息源聚合链接</a>,这项数据有助于我们时刻关注Javascript社区的主流信息</li> </ul> <h2>数据来源</h2> <p><strong>今年增加了一项参与调查途径的分布图</strong> 个人认为,这一项数据,对于我们了解前端主流信息源和社交渠道有一定的参考价值 <img src="/images/stateofjs/201908.png" alt="" /></p> <p><strong>调查参与者 国家分布图:</strong></p> <p><img src="/images/stateofjs/201903.png" alt="" /></p> <p><strong>调查参与者 薪资分布图:</strong></p> <p><img src="/images/stateofjs/201904.png" alt="" /></p> <p><strong>调查参与者 开发经验分布图:</strong></p> <p><img src="/images/stateofjs/201905.png" alt="" /></p> <p><strong>调查参与者 所属公司体量分布图:</strong></p> <p><img src="/images/stateofjs/201906.png" alt="" /></p> <p><strong>调查参与者 性别分布图:</strong></p> <p><img src="/images/stateofjs/201907.png" alt="" /></p> <h2>概览</h2> <p><img src="/images/stateofjs/201901.png" alt="" /></p> <p><img src="/images/stateofjs/201902.png" alt="" /></p> <h2>JavaScript 特性</h2> <ul> <li>这是今年新增的一项数据</li> <li>Javascript是一个不停更新的语言,每年都有新的Ecmascript版本发布,从箭头函数到解构,过去几年中添加的新特性现在已成为我们编写JavaScript不可或缺的一部分。</li> <li>因此,从今年开始,除了开发Javascript使用的工具外,增加了这项数据:JavaScript编写方式:所使用的模式,语法和特性</li> </ul> <h3>语法</h3> <p><img src="/images/stateofjs/201909.png" alt="箭头函数、解构、扩展运算符" /></p> <h3>语言</h3> <p><img src="/images/stateofjs/201911.png" alt="代理、异步promise、修饰器" /></p> <h3>数据结构</h3> <p><img src="/images/stateofjs/201912.png" alt="" /></p> <h3>浏览器API</h3> <p><img src="/images/stateofjs/201910.png" alt="fetch、i18n、websocket、localstorage..." /></p> <h3>其他特性</h3> <p><img src="/images/stateofjs/201913.png" alt="PWA、WASM" /></p> <h2>JavaScript Flavors</h2> <p>可以编译成 javasript 代码 的 各种语言/语法规范/javascript 超集</p> <p><img src="/images/stateofjs/201914.png" alt="" /></p> <h2>前端框架 Front-end Frameworks</h2> <p><img src="/images/stateofjs/201915.png" alt="" /></p> <h2>数据层 Data Layer</h2> <p><img src="/images/stateofjs/201916.png" alt="" /></p> <h2>后端框架 Back-end Frameworks</h2> <p><img src="/images/stateofjs/201917.png" alt="" /></p> <h2>测试 Testing</h2> <p><img src="/images/stateofjs/201918.png" alt="" /></p> <h2>移动端/客户端 Mobile &amp; Desktop</h2> <p><img src="/images/stateofjs/201919.png" alt="" /></p> <h2>函数库 Utility Libraries</h2> <p><img src="/images/stateofjs/201920.png" alt="" /></p> <p><img src="/images/stateofjs/201921.png" alt="" /></p> <h2>编辑器 Text Editors</h2> <p><img src="/images/stateofjs/201922.png" alt="" /></p> <p><img src="/images/stateofjs/201923.png" alt="" /></p> <h2>js 开发者使用的浏览器</h2> <p><img src="/images/stateofjs/201924.png" alt="" /></p> <p><img src="/images/stateofjs/201925.png" alt="" /></p> <h2>构建工具 Build Tools</h2> <p><img src="/images/stateofjs/201926.png" alt="" /></p> <p><img src="/images/stateofjs/201927.png" alt="" /></p> <h2>js 开发者使用的其他语言 Other Languages</h2> <p><img src="/images/stateofjs/201928.png" alt="" /></p> <p><img src="/images/stateofjs/201929.png" alt="" /></p> <h2>信息源(NEW*)</h2> <ul> <li>这是新年调查新增的一项数据</li> <li>这项数据显示了调查者依赖的信息源,包括博客和杂志、网站和课程、播客</li> <li><a>点击此处查看这些信息源的链接</a></li> </ul> <p><img src="/images/stateofjs/201930.png" alt="" /> <img src="/images/stateofjs/201931.png" alt="" /> <img src="/images/stateofjs/201932.png" alt="" /> <img src="/images/stateofjs/201933.png" alt="" /> <img src="/images/stateofjs/201934.png" alt="" /> <img src="/images/stateofjs/201935.png" alt="" /></p> <h2>开发者的感受</h2> <p><strong>“Javascript 正在往正确的方向发展”</strong></p> <p><img src="/images/stateofjs/201936.png" alt="" /></p> <p><strong>“当下构建 Javascript app 过于复杂惹”</strong></p> <p><img src="/images/stateofjs/201937.png" alt="" /></p> <p><strong>“Javascript 被过度使用”</strong></p> <p><img src="/images/stateofjs/201938.png" alt="" /></p> <p><strong>“我喜欢构建 JavaScript 应用程序”</strong></p> <p><img src="/images/stateofjs/201939.png" alt="" /></p> <p><strong>“我希望 JavaScript 成为我的主要编程语言”</strong></p> <p><img src="/images/stateofjs/201940.png" alt="" /></p> <p><strong>“JavaScript 生态系统变化太快”</strong></p> <p><img src="/images/stateofjs/201941.png" alt="" /></p> <h2>年度之最</h2> <ul> <li><strong>被采用最多的特性: Arrow Function</strong></li> </ul> <blockquote> <p>箭头函数是本年度使用最多的JavaScript功能,拥有97.8%的用户使用它。 &gt; promise &gt; 扩展运算符</p> </blockquote> <ul> <li><strong>使用最多的技术: React</strong></li> </ul> <blockquote> <p>React是今年使用最多的技术,拥有16099个用户。 &gt; Express &gt; Redux</p> </blockquote> <ul> <li><strong>满意度最高: Jest</strong></li> </ul> <blockquote> <p>有96.4%的用户愿意再次使用它,Jest再次证明了它不是在开玩笑。 &gt; GraphQL &gt; Cypress</p> </blockquote> <ul> <li><strong>最感兴趣: GraphQL</strong></li> </ul> <blockquote> <p>听说过GraphQL的开发人员中有89.6%希望学习它。 那是很重要的兴趣! &gt; Jest &gt; Apollo</p> </blockquote> <ul> <li><strong>最广泛的信息源: Stack Overflow</strong></li> </ul> <blockquote> <p>拥有17942个用户的Stack Overflow是今年使用最多的资源。 &gt; MDN &gt; CSS Tricks</p> </blockquote> <ul> <li><strong>黑马奖: Svelte</strong></li> </ul> <blockquote> <p>斯维尔特(Svelte)在今年的调查中首次亮相,我们迫不及待想知道它的去向 &gt; Next.js &gt; Stencil</p> </blockquote> <h2>总结</h2> <p>stateofjs团队在总结中说:</p> <blockquote> <p>You know how you sometimes start tweaking a few lines of code here and there, then realize a couple functions could use some refactoring, and then one things leading to another you find yourself a few days later in the process of setting up a brand new stack complete with a database and GraphQL API?</p> <p>This is what happened to us this year. And while it resulted in quite a few stressful evenings as we tried to wrap this up and release the State of JavaScript 2019 results in, well, 2019; it also means we now have a much more powerful and flexible stack to collect and analyze data going forward.</p> </blockquote> <p>“你有时候会在这里那里调整几行代码,然后发现有几个函数可以重构,然后一个变更引发另一个变更,几天后你发现重构的过程中,用上了数据库和GraphQL API,建立了一个全新的技术栈...”</p> <p>这是今年发生在他们身上的故事,使用数据库和GraphQL重构,使得整个stateofjs项目的开发、数据收集、数据分析等工作,更加灵活、更加强大。 他们的重构将有助于分析所有那些掀起波澜的新工具的发展历程,例如 Svelte,Stencil,Nest 或 Flutter...</p> <p>无论前端社区不断向你扔出多少奇怪名字的库,跟紧stateofjs的调查,及时自检,总归不会掉队😘😆</p> 前端https://www.scarsu.com/2019_javascript_report/#post-comment/信息源聚合 | 2019年度Javascript社区https://www.scarsu.com/2019_javascript_sources/https://www.scarsu.com/2019_javascript_sources/根据stateOfJs2019调查中,20000余名JS开发者的数据整理而来Mon, 30 Dec 2019 00:00:00 GMT<h1>2019年度Javascript社区-信息源聚合</h1> <ul> <li><strong>排名有先后,依据是<a>StateOfJs调查</a></strong></li> <li>整理了一份可以在浏览器直接导入的👉&lt;a href="/assets/js_sources_bookmark.html" download="js_sources_bookmark.html"&gt;书签文件&lt;/a&gt;</li> </ul> <h2>Blogs &amp; Magazines</h2> <ul> <li><a>CSS Tricks</a></li> <li><a>Dev.to</a></li> <li><a>JavaScript Weekly</a></li> <li><a>Smashing Magazine</a></li> <li><a>David Walsh Blog</a></li> <li><a>SitePoint</a></li> <li><a>CoDrops</a></li> <li><a>Daily JS</a></li> <li><a>Best Of JS</a></li> <li><a>Echo JS</a></li> <li><a>Medium</a></li> <li><a>Kent C. Dodds</a></li> <li><a>Twitter</a></li> <li><a>Overreacted</a></li> <li><a>Reddit</a></li> <li><a>Hacker News</a></li> <li><a>Alligator.io</a></li> <li><a>Habr</a></li> <li><a>freeCodeCamp</a></li> <li><a>2ality</a></li> <li><a>Scotch</a></li> <li><a>Node Weekly</a></li> <li><a>Hackernoon</a></li> <li><a>The Ember Times</a></li> <li><a>React Status</a></li> <li><a>Frontend Focus</a></li> <li><a>Angular In Depth</a></li> <li><a>Web.dev</a></li> <li><a>Web Development Reading List</a></li> <li><a>ESNext News</a></li> <li><a>The Changelog</a></li> <li><a>Pony Foo</a></li> <li><a>Robin Wieruch</a></li> <li><a>Wes Bos</a></li> </ul> <h2>Sites &amp; Courses</h2> <ul> <li><a>Stack Overflow</a></li> <li><a>MDN</a></li> <li><a>W3Schools</a></li> <li><a>freeCodeCamp</a></li> <li><a>Wes Bos</a></li> <li><a>Codecademy</a></li> <li><a>Level Up Tutorials</a></li> <li><a>Design+Code</a></li> <li><a>Udemy</a></li> <li><a>Egghead.io</a></li> <li><a>Frontend Masters</a></li> <li><a>YouTube</a></li> <li><a>Vue Mastery</a></li> <li><a>Platzi</a></li> <li><a>Vue School</a></li> <li><a>Laracasts</a></li> <li><a>Traversy Media</a></li> <li><a>Medium</a></li> <li><a>Udacity</a></li> <li><a>Kent C. Dodds</a></li> <li><a>Testing JavaScript</a></li> <li><a>Lynda</a></li> <li><a>Academind</a></li> <li><a>LinkedIn Learning</a></li> <li><a>Treehouse</a></li> <li><a>Scrimba</a></li> <li><a>JavaScript.info</a></li> <li><a>Tyle McGinnis</a></li> <li><a>Reddit</a></li> <li><a>Ultimate Courses</a></li> <li><a>caniuse</a></li> <li><a>Overreacted</a></li> <li><a>devdocs.io</a></li> </ul> <h2>Podcasts</h2> <ul> <li><a>Syntax</a></li> <li><a>The Changelog</a></li> <li><a>Front End Happy Hour</a></li> <li><a>JavaScript Jabber</a></li> <li><a>Full Stack Radio</a></li> <li><a>Shop Talk Show</a></li> <li><a>JS Party</a></li> <li><a>CodePen Radio</a></li> <li><a>JAMStack Radio</a></li> <li><a>Modern Web</a></li> <li><a>The Web Platform Podcast</a></li> <li><a>CodePen</a></li> <li><a>React Podcast</a></li> <li><a>Software Engineering Daily</a></li> <li><a>Ladybug Podcast</a></li> <li><a>Real Talk JavaScript</a></li> <li><a>The Undefined Podcast</a></li> <li><a>Веб-стандарты</a></li> <li><a>Elm Slack</a></li> <li><a>Soft Skills Engineering Podcast</a></li> <li><a>Frontend Weekend</a></li> <li><a>Elm Town</a></li> <li><a>The Odin Project</a></li> <li><a>Developer Tea</a></li> <li><a>Command Line Heroes</a></li> <li><a>Adventures in Angular</a></li> <li><a>Toolsday</a></li> <li><a>Coding Blocks</a></li> <li><a>Egghead.io</a></li> <li><a>Kent C. Dodds</a></li> <li><a>EmberMap</a></li> <li><a>.NET Rocks</a></li> <li><a>Views on Vue</a></li> <li><a>Reason Town</a></li> <li><a>Hipsters Ponto Tech</a></li> <li><a>DevMode.fm</a></li> <li><a>Fun Fun Function</a></li> </ul> 前端https://www.scarsu.com/2019_javascript_sources/#post-comment/ML03 | Tensor-张量简介https://www.scarsu.com/fed_ml_03_tensor/https://www.scarsu.com/fed_ml_03_tensor/Javascript玩转机器学习03Sun, 29 Dec 2019 00:00:00 GMT<h2>什么是Tensor</h2> <ul> <li><strong>张量</strong></li> <li>是向量和矩阵向更高维度的推广</li> <li>相当于多维数组</li> </ul> <h3>0维张量</h3> <p><img src="/images/ai/05.png" alt="0维张量" /></p> <p><img src="/images/ai/06.png" alt="rankType描述维度" /></p> <h3>1维张量</h3> <p><img src="/images/ai/07.png" alt="1维张量" /></p> <p><img src="/images/ai/08.png" alt="shape描述每个维度上数组长度" /></p> <h3>2维张量</h3> <p><img src="/images/ai/09.png" alt="每一维度数组长度均为2的2维张量" /></p> <p><img src="/images/ai/10.png" alt="size描述张量的元素数量" /></p> <h3>2 维张量</h3> <p><img src="/images/ai/11.png" alt="2维张量" /></p> <p><img src="/images/ai/12.png" alt="每一维度数组长度均为1的2维张量" /></p> <h3>3维张量</h3> <p><img src="/images/ai/13.png" alt="3维张量" /></p> <p><img src="/images/ai/14.png" alt="shape描述了三个维度的数组长度均为1" /></p> <h2>Tensor和机器学习有什么关系?</h2> <ul> <li>Tensor符合神经网络的数据结构</li> <li>神经网络每一层要存N维数据</li> <li>N层的For循环运算</li> </ul> <h2>Tensor的运算 十分符合 神经网络的运算</h2> <ul> <li>eg.用TensorFlow.js提供的<strong>点乘dotAPI</strong>能够简化复杂的for循环运算:</li> </ul> <p><img src="/images/ai/15.png" alt="传统for循环运算张量 vs dot运算张量" /></p> <p><img src="/images/ai/16.png" alt="点乘结果与for循环结果一致" /></p> <hr /> <p><a>代码仓库</a></p> 前端https://www.scarsu.com/fed_ml_03_tensor/#post-comment/ML02 | TensorFlow.js简介https://www.scarsu.com/fed_ml_02_tensorflow/https://www.scarsu.com/fed_ml_02_tensorflow/Javascript玩转机器学习02Thu, 26 Dec 2019 00:00:00 GMT<h2>TensorFlow.js是什么</h2> <ul> <li>js实现的机器学库</li> <li>可以在node.js/浏览器环境中使用机器学习技术,这意味着有更好的实时性和交互性</li> <li>著名的TensorFlow是用Python实现的</li> </ul> <h2>TensorFlow.js能干什么</h2> <ul> <li>运行现有的模型(算法工程师已经训练好的模型)</li> <li>重新训练现有模型</li> <li>使用javascript开发机器学习模型</li> </ul> <h2>demo</h2> <ul> <li><a>tfjs的各种例子</a></li> </ul> <h2>在浏览器安装tfjs</h2> <ul> <li>新建一个html,script标签引入</li> </ul> <p><code>&lt;script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.0.0/dist/tf.min.js"&gt;&lt;/script&gt;</code></p> <ul> <li>npm包安装,用import引入,用parcel/webpack构建</li> </ul> <p><code>npm i @tensorflow/tfjs</code></p> <h2>在Node.JS安装tfjs</h2> <ul> <li> <p>安装带有原生C++绑定的TensorFlow.js(推荐,底层是C++,速度快,但是安装麻烦)</p> </li> <li> <p>安装纯Javascript版本,性能较差</p> </li> <li> <p>使用require方式引用之前npm安装的<code>@tensorflow/tfjs</code>,直接用node运行当前js,一样可以在node中使用到tfjs,但是会提示:</p> </li> </ul> <pre><code>============================ Hi there. Looks like you are running TensorFlow.js in Node.js. To speed things up dramatically, install our node backend, whi ch binds to TensorFlow C++, by running npm i @tensorflow/tfjs-node, or npm i @tensorflow/tfjs-node-gpu if you have CUDA. Then call require('@tensorflow/tfjs-node'); (-gpu suffix for CUDA) at the start of your program. Visit https://github.com/tensorflow/tfjs-node for more details. ============================ </code></pre> <ul> <li> <p>因此要使用<code>npm i @tensorflow/tfjs-node</code>命令来安装后端版本tfjs,但是直接安装会报错,要先安装以下依赖:<code>npm i node-gyp windows-build-tools@4.0.0 -g</code></p> </li> <li> <p><code>node-gyp</code>是node和计算机底层交互时经常要用到的包,在windows直接安装这个包也需要一些依赖,例如安装visual studio、python,因此<code>windows-build-tools@4.0.0</code>这个包就是用来解决其依赖问题的。</p> </li> <li> <p>安装完后端版本tfjs<code>@tensorflow/tfjs-node</code>后,即可直接通过require引入使用</p> </li> </ul> <hr /> <p><a>代码仓库</a></p> 前端https://www.scarsu.com/fed_ml_02_tensorflow/#post-comment/ML01 | 机器学习&神经网络简介https://www.scarsu.com/fed_ml_01/https://www.scarsu.com/fed_ml_01/Javascript玩转机器学习01Wed, 25 Dec 2019 00:00:00 GMT<h2>大纲</h2> <ul> <li>理论知识:机器学习、神经网络、 Tensorflow. js</li> <li>经典案例:线性回归、逻辑回归、XOR、IRS、手写数字识 别、商标识别、语音识别</li> <li>神经网络模型:从单个神经元到深度神经网络</li> <li>神经网络模型算法:MSE/Log/ Cross Entropy Sigmoid/Relu/Softmax, SGD/Adam</li> <li>炼丹最佳实践:归化、欠(过)拟合、可视化、度量</li> <li>模型的迁移学习、保存、加载、转换</li> </ul> <h2>为什么要学机器学习</h2> <p>可以做一些很酷的事情,tensorflow.js官网列出了一些已经训练好的,开箱即用的<a>模型</a></p> <p>例如,<a>BodyPix</a>:实时分割人的身体和身体部位</p> <p><img src="/images/picgo/000.gif" alt="body-pix" /></p> <p><a>图像分类</a>, <a>文本恶意检测</a>, <a>语音指令识别</a>, <a>...</a></p> <h2>机器学习是什么</h2> <pre><code>数据 + 经验 -&gt; 优化算法 </code></pre> <ul> <li>对能<strong>通过经验自动改进算法</strong>的研究</li> <li>用<strong>数据</strong>或者以往的<strong>经验</strong>,来优化计算机程序的性能标准</li> </ul> <h2>机器学习例子:线性回归</h2> <ul> <li>只包括一个自变量和一个因变量,且二者的关系可用一条直线近似表示,这种回归分析称为一元线性回归分析。</li> </ul> <p><img src="/images/ai/01.png" alt="线性回归" /></p> <ul> <li>如果回归分析中包括两个或两个以上的自变量,且因变量和自变量之间是线性关系,则称为多元线性回归分析。</li> </ul> <p><img src="/images/ai/02.png" alt="多元线性回归" /></p> <h2>机器学习例子:逻辑回归</h2> <ul> <li>输入连续的(多个)值,输出0-1之间的概率,可以用于解决分类/是非判断问题</li> </ul> <p><img src="/images/ai/03.png" alt="逻辑回归" /></p> <ul> <li>例子:图片分类、语音助手</li> </ul> <p><img src="/images/ai/04.png" alt="逻辑回归:图片分类" /></p> <h2>为什么要用机器学习</h2> <ul> <li>有些问题无法用编写代码规则的方法来解决,例如图片识别。</li> <li>获取数据比编写规则更容易</li> <li>GPU等计算能力显著提升(上世纪神经网络就已发明,但是受限于计算机计算能力,得不到发展</li> </ul> <h2>机器学习如何运作</h2> <ul> <li>神经网络</li> <li>决策树、支持向量机、贝叶斯分类器、强化学习</li> </ul> <h2>什么是神经网络</h2> <ul> <li>人工神经网络</li> <li>一种运算模型(输入输出的映射)</li> <li>由大量的节点(神经元)之间相互连接构成</li> </ul> <p>&lt;!-- eg. 相亲 <img src="http://note.youdao.com/yws/res/26525/FDAB01287A58444E9C6205F65EE8A164" alt="image" /> --&gt;</p> <ul> <li>神经网路包括:一个输入层,若干隐藏层,一个输出层。</li> <li>每条线的权重可能不同</li> </ul> <h2>神经元、权重、偏置、激活函数</h2> <ul> <li>每个神经元里都存储着若干<strong>权重wight</strong>、<strong>偏置bias</strong>和一个<strong>激活函数activation</strong></li> <li>输入<strong>权重 + 偏置</strong>,经过<strong>激活函数</strong>得到<strong>输出</strong></li> <li><strong>激活函数</strong>:用于添加<strong>非线性</strong>变换</li> </ul> <h2>神经网络的训练是什么?</h2> <ul> <li>给大量输入输出,算出神经网络里所有神经元的<strong>权重、偏置</strong>,然后给定新的输入,可以算出新的输出</li> </ul> <h2>机器学习中的术语</h2> <ul> <li><strong>==特征==</strong>:输入</li> <li><strong>==标签==</strong>:输出</li> <li><strong>训练集</strong>:大量输入输出</li> </ul> <h2>如何训练</h2> <ol> <li>初始化:随便生成一些<strong>weight</strong>,<strong>bias</strong></li> <li>计算<strong>损失</strong>:给定特征,计算出标签,得到其与真实标签的差距</li> <li>优化:微调<strong>weight</strong>和<strong>bias</strong>,使损失变小</li> </ol> <h2>前向传播</h2> <ul> <li>将训练数据的<strong>特征(输入)<strong>送入网络,得到</strong>标签(输出)</strong></li> </ul> <h2>反向传播</h2> <ul> <li>计算<strong>损失</strong>并优化</li> </ul> <h2>如何计算损失</h2> <p><strong>损失函数</strong>:均方误差、对数损失、交叉熵...</p> <p>(了解损失函数原理即可,可以从第三方库调用。eg.TensorFlow.js)</p> <h2>如何优化</h2> <p><strong>优化器</strong>:随即梯度下降<strong>SGD</strong>、<strong>Adam</strong></p> <p>(了解损失函数原理即可,可以从第三方库调用。eg.TensorFlow.js)</p> <hr /> <p><a>代码仓库</a></p> 前端https://www.scarsu.com/fed_ml_01/#post-comment/被讨厌的勇气:一切的人际烦恼都可以用8个字来释怀https://www.scarsu.com/life_courage/https://www.scarsu.com/life_courage/“课题分离:与我何关,与你何关”、“自由就是被人讨厌”、“一切烦恼皆来自于人际关系”Sat, 09 Nov 2019 00:00:00 GMT<h2>简介</h2> <h2>我们的不幸是谁的错?</h2> <h2>一切烦恼都来自于人际关系</h2> <h2>让干涉你的人见鬼去</h2> <h2>要有被讨厌的勇气</h2> <h2>认真的人生活在“当下”</h2> <hr /> <p>有的人并不是天生的脾气暴躁,而是明白了有时候合适的时机散播怒火,才能有效的达到目的。</p> 个人成长https://www.scarsu.com/life_courage/#post-comment/ES6编程风格&最佳实践https://www.scarsu.com/es6_code_style/https://www.scarsu.com/es6_code_style/遵守一定的规范和统一的风格写代码,是程序猿的基本素养😺Wed, 06 Nov 2019 00:00:00 GMT<h2>块级作用域</h2> <ul> <li><code>let</code>完全取代<code>var</code></li> <li>let和const<strong>优先const</strong>: <ul> <li>函数式编程思想,运算不改变值,只是新建值</li> <li>防止了无意间修改变量值所导致的错误</li> <li>有利于将来的分布式运算</li> <li>JavaScript 编译器会对const进行优化,所以多使用const,有利于提高程序的运行效率</li> </ul> </li> </ul> <h2>字符串</h2> <ul> <li>静态一律用单引号/反引号</li> <li>动态使用反引号</li> <li><strong>不使用双引号</strong></li> </ul> <h2>解构赋值</h2> <ul> <li>从数组取值给变量时,优先用<strong>数组解构</strong></li> <li>函数参数是对象属性,优先用<strong>对象解构</strong></li> <li>函数有多个返回值时,优先用<strong>对象解构</strong></li> </ul> <h2>对象</h2> <ul> <li>单行定义的对象,最后一个成员不以逗号结尾;多行定义的对象,最后一个成员要以逗号结尾</li> <li>对象尽量静态化,一旦定义就不要随意添加属性。非要加,就用 <strong>Object.assign</strong> 方法</li> <li>对象有动态属性名:用属性名表达式 <strong>[表达式]</strong></li> <li>对象的属性和方法,尽量用<strong>简洁表达式</strong>,易于书写和描述</li> </ul> <h2>数组</h2> <ul> <li>拷贝数组:用 <strong>...</strong> 扩展运算符</li> <li>类数组对象转数组:用<strong>Array.from</strong>方法</li> </ul> <h2>函数</h2> <ul> <li>立即执行函数:用箭头函数</li> <li>匿名函数:用箭头函数</li> <li>简单的、单行的、不会复用的函数:用箭头函数</li> <li>用箭头函数取代<strong>Function.prototype.bind</strong></li> <li>不再用 <code>_this/that/self/sf</code>去绑定this</li> <li>不在函数体内用 <strong>arguments</strong>变量,用<strong>rest运算符</strong><code>...</code>代替</li> <li>用<strong>默认值语法</strong>设置函数参数</li> </ul> <h2>Map和Object</h2> <ul> <li>只有模拟现实世界的对象时,采用<code>Object</code></li> <li>只需要<code>key:value</code>数据结构时,就用<code>Map</code></li> </ul> <h2>Class和prototype</h2> <ul> <li>尽量用Class取代需要prototype的操作,更易书写和便于理解</li> <li>用<code>extends</code>实现继承,更简单,不会使instanceof运算有风险</li> </ul> <h2>Module</h2> <ul> <li>Module语法使ES的标准写法</li> <li>用import代替require</li> <li>用export代替module.exports</li> <li>如果模块只有一个输出值,就用default,否则别用</li> <li>export default和export不要混合使用</li> <li>模块输出的函数,函数名首字母应该用小写</li> </ul> <h2>使用ESLint</h2> <ul> <li>安装 ESLint</li> <li>安装 Airbnb 等语法规则,以及 import、a11y、react 等插件</li> <li>在项目的根目录下新建一个<code>.eslintrc</code>文件,配置 ESLint</li> </ul> 前端https://www.scarsu.com/es6_code_style/#post-comment/自控力:即时反馈&延迟折扣https://www.scarsu.com/self_control/https://www.scarsu.com/self_control/了解意志力/欲望的生理心理精神学原理,从而更好的掌控自己Thu, 19 Sep 2019 00:00:00 GMT<h2>《自控力》介绍</h2> <ul> <li>“斯坦福大学广受欢迎的心理学课程”</li> <li>总结 意志力/欲望的现象</li> <li>分析 意志力/欲望的 生理 心理 精神学原理</li> <li>找出 提升自控力/控制欲望 的对策</li> </ul> <h4>思维导图</h4> <p><img src="/images/self_control.png" alt="《自控力思维导图》" /></p> <h2>意志力的本质</h2> <ol> <li><code>我要</code>的力量:行动</li> <li><code>我不要</code>的力量:抵制</li> <li><code>我想要</code>的力量:目标</li> </ol> <h2>意志力的生理特征</h2> <ul> <li>意志力像<code>肌肉</code>一样有限制。</li> <li>意志力被消耗,会导致失控。</li> <li>意志力从早到晚,逐渐减弱——把需要意志力的事情放在<code>早上</code>(意志力最强的时候)做。</li> <li>饥饿/疲惫/紧张会影响意志力。</li> <li>意志力可以训练:在一些小事上持续自控会提升整体的意志力</li> </ul> <h2>增强意志力的生理方法</h2> <ul> <li><code>运动</code>:坚持运动,能提升意志力</li> <li><code>睡眠</code>:睡眠是对能量的恢复,早上的意志力最强</li> <li><code>放松</code>:压力会消耗意志力</li> <li><code>呼吸等待</code>:做失控决定前深呼吸,告诉自己等待几分钟再去做</li> <li><code>训练</code>:通过持续性的小事自控来训练意志力</li> <li><code>动力</code>:找出“我想要”的动力,让它环绕在你的生活的角角落落</li> </ul> <h2>引起“失控”的几种心理</h2> <ul> <li><code>自我感觉良好</code>会让自己更易纵容。</li> <li><code>把进步当作放纵的接口</code>:前进一小步,后退两大步</li> <li><code>透支成就感</code>:向未来赊账</li> </ul> <h2>多巴胺 &amp; 欲望vs幸福</h2> <h4>多巴胺:让人产生欲望,而不是快乐</h4> <ul> <li>人脑的多巴胺系统,与快感中心不是同一个部分。</li> <li>多巴胺系统刺激人原始动力系统的一部分。</li> <li>使人产生欲望,预见快感,追逐欲望,而不是真正使人快乐。</li> <li>过量的多巴胺:上瘾</li> </ul> <h4>欲望 != 幸福</h4> <ul> <li>没有欲望不幸福,欲望过多使人失控。</li> <li>好欲望-》产生动力-》促进意志力</li> <li>坏欲望-》屈服于诱惑-》失控</li> <li>所以要合理利用欲望,分清“欲望”和“幸福”</li> </ul> <h4>多巴胺系统的特点</h4> <ul> <li>对新鲜事物/未知奖励敏感</li> <li>对多样性敏感</li> </ul> <h4>多巴胺对策</h4> <ul> <li>“多巴胺化”:把不喜欢的东西 和 能促进多巴胺的事联系起来。</li> <li>“鱼缸奖励法”:完成目标时,抽取未知的不同的奖励,而不是小儿稳定的奖励。</li> </ul> <h2>压力带来的“失控负循环”</h2> <p><img src="/images/stress_circle.png" alt="压力带来的“失控负循环”" /></p> <h4>打破循环的方法</h4> <ul> <li>及时止损,不要破罐子破摔</li> <li>“自我谅解”,而不是加深自责加深压力促进循环</li> <li>“行动”而不是“发誓改变”,不要满足于指定计划,这种满足感来源于“对想象中未来成就感的透支”</li> <li>用有效的方式解压↓</li> </ul> <h4>有效的解压方式</h4> <ul> <li>运动</li> <li>培养爱好</li> <li>社交</li> <li>音乐</li> <li>阅读</li> <li>牢牢记住以上方式解压后愉悦的心情</li> </ul> <h2>现代 vs 未来</h2> <h4><code>即时反馈</code>&amp;<code>延迟折扣</code></h4> <ul> <li><code>多巴胺系统</code>使人乐于追求即时反馈</li> <li>眼前的“小奖励” 比 “未来的大奖励” 更有诱惑力</li> <li>延迟折扣:需要等待时间越久的奖励,诱惑力越低</li> </ul> <h4>抵制即时反馈</h4> <ul> <li>拉开与诱惑的距离:时间 &amp; 空间</li> <li>“10分钟法则”:决定放纵前,先等待10分钟(利用延迟折扣,诱惑力会降低</li> <li>放大未来的奖励,降低折扣率,让想要的未来离自己更近,例如把偶像/目标贴在经常能看到的地方</li> </ul> <h4>缩小“现在的自己” 与“未来的自己”的差距</h4> <ul> <li>不要高看未来的自己</li> <li>不要一切都拖到未来去做</li> </ul> <h2>意志力会传染</h2> <ul> <li>人生来就具有社会性:不可能脱离社会生存,要与他人产生联系</li> </ul> <h4><code>社会认同感</code></h4> <ul> <li>“自豪”,“惭愧”等社会性情绪,会促进人的自控</li> <li>让自己相信“大多数人都自控”,“自控是个社会规范”,更有利于自控</li> </ul> <h4><code>镜像神经元</code>的行为:</h4> <ul> <li>无意识的模仿他人</li> <li>情绪传染</li> <li>自控力传染</li> </ul> <h4>对策</h4> <ul> <li>增强免疫力</li> <li>坚定自我</li> <li>远离不自控人群</li> </ul> <h2>讽刺性反弹</h2> <h4>“我不要”的神经学原理</h4> <ol> <li>大脑的“操作系统”:消耗能力去自控(耗能高)</li> <li>大脑的“监控系统”:充满了“不要xxx”的警告 (自动机制,耗能很低)</li> </ol> <ul> <li>当人的精力不足时,1、2失去平衡,不断的执行2,不断的想起不能做的事情,却没有足够的能量去执行1去抵制,就会导致失控</li> </ul> <h4>讽刺性反弹的结果</h4> <ul> <li>“我不要”的力量,有时候会产生相反的效果</li> <li>通过“抑制想法”来抵抗诱惑,可能会适得其反</li> <li>越压抑人的本能,越容易适得其反</li> </ul> <h4>对策</h4> <ul> <li>了解认知偏见:认知偏见:想起xx的次数多,容易让人对xx的真实性产生误判。要知道自己不断想起的事情不一定是真的,不一定是对的</li> <li>放弃控制内心的感受,坦率的面对与接受,关注自己的想法与感受,去理解分析,判断真实性的对错</li> <li><code>直面自身的欲望,但不去行动</code>:对内接受自我,对外控制行为</li> <li>把“我不要”转为“我想要”效果更好。</li> </ul> <p>&lt;small&gt;注:书中列出的观点,大多数都有实验数据支撑,都是很有趣的实验,建议亲自阅读&lt;/small&gt;</p> 个人成长https://www.scarsu.com/self_control/#post-comment/刻意学习:如何更高效的成长https://www.scarsu.com/continuous_action/https://www.scarsu.com/continuous_action/提升执行力 | 持续精进 | 轻松成为更好的自己Mon, 19 Aug 2019 00:00:00 GMT<h2>书的主旨 : 持续行动 + 持续学习</h2> <h2>为什么要持续行动</h2> <h4>为了成长</h4> <ul> <li>生而为成长,在这个变化万千的时代,不进则退。</li> </ul> <h4>跳出困境,重构现在与未来</h4> <ul> <li>现状有多痛苦,过往有多不堪,持续行动就该有多深。</li> <li>“悟已往之不谏,知来者之可追”,我们的原生家庭、出身条件、容貌身体发肤、以及过去的种种,都是不可变的默认参数,只能靠当下的行动,去改变未来的轨迹。</li> </ul> <h2>正确的自我认知</h2> <h4>拒绝自我感动</h4> <ul> <li>正是因为做得少,才容易“感动”,自欺欺人。</li> <li>提前透支快感:为自己定下宏大的目标,并为之沾沾自喜,提前透支着目标达成的快感,真正要开始做事便耐不住寂寞开始放弃</li> </ul> <h4>拒绝“强及时反馈”</h4> <ul> <li>我们与外界互动,通常渴望强及时反馈,得不到变容易焦虑、急躁。</li> <li>强及时反馈对复杂系统是不起作用的:</li> </ul> <table> <thead> <tr> <th>复杂系统</th> <th>行为</th> <th>强及时反馈</th> </tr> </thead> <tbody> <tr> <td>人的身体系统</td> <td>跑一次步</td> <td>变瘦变健康</td> </tr> <tr> <td>大海</td> <td>撒一泡尿</td> <td>变脏</td> </tr> </tbody> </table> <h4>不要过度依赖技巧</h4> <ul> <li>投机取巧是追求强即时反馈的表现</li> <li>过度追逐技巧的人,往往缺乏行动量</li> <li>能用思路解决的问题,尽量不用技巧。从全局的层面看问题,理清逻辑思路,而不是抓住某个细节投机取巧</li> </ul> <h4>不要标榜/贴标签,去行动</h4> <ul> <li>通过标榜自己是谁,给自己贴标签,并且能马上得到本来要经过努力做成事才嗯那个得到的反馈,就不会再踏实的做事了。</li> <li>通过“宣称”自己写作、在GRE、在奋斗,快速透支大量快感,往往时不会他是做事的。</li> </ul> <h4>不要自我迷恋,高估自己</h4> <ul> <li>不要做事无巨细的完美主义者:等到把所有的因素都准备完美再开工。不如先把一部分事情做起来。</li> <li>制定计划时,总是雄心勃勃,透支着未来的成就感,高估自己的能力,往往开始正真做事的时候,更容易放弃。</li> </ul> <h4>放大格局</h4> <ul> <li>人是一种容易短视的动物,因为我们的圈子往往比整个世界小的太多太多微乎其微,这种短视会带来认知偏差,让我们做出错误的判断</li> <li>时不时跳出自己的圈子,主动接触外界信息,不要过度相信自己的认知,是提升格局的关键</li> </ul> <h2>成长系统</h2> <p><img src="/images/continuous_action.png" alt="" /></p> <h2>如何行动</h2> <h4>松散到紧凑</h4> <ul> <li>建立合理的作息</li> <li>坚定的坚持下去</li> </ul> <h4>耐得住寂寞:没有成就感也要行动</h4> <ul> <li>持续行动的要义就在于持续,不要以任何理由打破自己定下的原则</li> <li>不依靠透支未来的成就感,作为坚持下去的动力</li> </ul> <h4>​克服拖延</h4> <ul> <li>五分钟内能做完的事,现在立即做。五分钟做不完的,现在开始做一部分。</li> </ul> <h4>放大对未来的感知</h4> <ul> <li>提前完成任务,而不是到deadline</li> <li>不要高度自己的能力,低估自己完成任务所需的时间</li> <li>时刻警醒自己,让自己感知着未来不完成任务带来的后果</li> </ul> <h4>早起是拓宽增量</h4> <ul> <li>更高效的利用时间,有两个途径。一是“存量优化”,在现有的作息时间中,更高效的利用时间。二是“拓宽增量”,也就是增加可支配的时间。</li> <li>对于大多数人来说,“存量优化”是很难的,也是有瓶颈的,因此“拓宽增量”是更好的选择。</li> <li>“拓宽增量”意味着压缩睡眠时间,起的更早显然比睡的更晚对身体更有利,并且清晨的时光,更以利用。</li> </ul> <h4>投资资源(时间+金钱)</h4> <ul> <li>首先,投资自己是一种收益最高的投入,不能因为惜钱,而去绕弯路,去用时间换钱</li> <li>其次,投资自己不光意味花钱,花钱只是获得了更好的资源,真正的成长,需要你投入时间去持续行动</li> </ul> <h4>信息分级,对海量信息抗压</h4> <ul> <li>面对海量的信息,不因噎废食,直接切断所有的信息源</li> <li>不自我焦虑,培养抗压能力,克服“永远刷不完的小红点”带来的焦虑不安</li> <li>形成对信息分级的系统,主动的对信息分级,知道自己想要什么</li> </ul> <h2>关于n阶行动计划</h2> <table> <thead> <tr> <th>阶数</th> <th>时长</th> <th>特点</th> </tr> </thead> <tbody> <tr> <td>一</td> <td>10^1 = 10天,一个周</td> <td>瓶颈在于执行力,行动系统有问题</td> </tr> <tr> <td>二</td> <td>10^2 = 100天,三个月</td> <td>瓶颈在于学习系统和格局,有一定执行力,但是需要完善学习系统,升华格局</td> </tr> <tr> <td>三</td> <td>10^3 = 1000天,三年</td> <td>时间足够长,能够见到真正的对复杂系统的改变,形成了思维惯性和依赖路径,瓶颈在于创新、重构、与时俱进</td> </tr> <tr> <td>...</td> <td>...</td> <td>...</td> </tr> </tbody> </table> <h2>关于1000天持续行动计划</h2> <h4>开局阶段:0-300天</h4> <ul> <li>认清自我,了解现状,认清现实,找出“我能做的”和“我想做的”之间的差距</li> <li>仅能完成任务,倒逼自己</li> </ul> <h4>中盘持续阶段:200-600天</h4> <ul> <li>补足不全,缩短“我能做的”和“我想做的”之间的差距</li> <li>能每天完成任务,并在其基础上有所进步</li> </ul> <h4>突破创新阶段:600-1000天</h4> <ul> <li>突破现有的固定模式,打破思维惯性</li> <li>根据环境的改变,做出新的规划,升华行动</li> </ul> <p>&lt;small&gt;希望你看完,能做点什么&lt;/small&gt;</p> 个人成长https://www.scarsu.com/continuous_action/#post-comment/断舍离:物品的价值在于使用而不在于拥有https://www.scarsu.com/danshari/https://www.scarsu.com/danshari/在极简极致的生活中了解自我,认识自我,找到自己真正想做的事情。Mon, 05 Aug 2019 00:00:00 GMT<h2>断舍离是什么</h2> <p>断舍离是一种,通过收拾物品来了解自己,整理自己,让人生更舒适的方法</p> <h2>‌如何做到断舍离</h2> <ul> <li>断(行为):断绝要进入自己家里/生活里/脑海里的 不需要的东西</li> <li>舍(行为):舍弃自己的世界里既有的破烂(clutter)</li> <li>离(状态):脱离对物品的执念,使自己处于游刃有余的自在空间</li> </ul> <h2>‌用湖泊比喻生活</h2> <ul> <li>断:对上游留下来的东西进行筛选,对生活入口有把控/筛选能力</li> <li>舍:让不需要的东西流出</li> </ul> <p>这样才能让生活保持新鲜,清静。</p> <h2>‌断舍离的灵魂一问</h2> <p><code>自己</code> <code>当下</code> 是否需要?</p> <ul> <li>断舍离的主角:自己</li> <li>断舍离的时间轴:当下</li> </ul> <h2>‌断舍离vs收纳</h2> <p>断舍离是对进入/留存在自己世界中的物品进行筛选(先)</p> <p>收纳是对已有物品的整理(后)</p> <p>通过先达到断舍离的状态,让自己的生活从加法走向减法,让自己陷于收纳整理的时间更少,让生活更轻松自在</p> <h2>‌为什么我们的生活里满是杂物</h2> <ul> <li>捡便宜,通过消费满足物欲,这也新奇,那也想买,买来新鲜感一过就闲置(物欲泛滥,对物品有执念)</li> <li>执念于过去,念旧,舍不得(时间轴错位)</li> <li>囤积癖,对未来过度忧虑,“万一以后会用到”,但实际概率很小(时间轴错位)</li> <li>不想收拾不想改变(懒)</li> </ul> <h2>‌断舍离是令人愉悦的</h2> <p>通过断舍物品,完成自我发现,自我肯定的过程</p> <h2>物品的真正价值</h2> <p>任何物品都需要被使用,这才是它本身价值的体现。我们需要的东西其实并没有那么多,而留在身边的应该是<code>最少量最好用</code>的。</p> <h2>‌“拥有物品”是个伪命题</h2> <p>人的生命是有限的,一切有形的东西都是虚幻的,人心也是不断变化的。</p> <p>物品只应该是我们追求人生幸福感的工具,而不是一种拥有/维护/收纳/处理的累赘。</p> <p>因此“物品被使用的时候才是发挥价值的时候”,物品当下应该在需要他的地方,而不应该是闲置。</p> <h2>七、五、一总量限制原则</h2> <p><code>七</code>:柜子等<code>看不见的</code>收纳物品装备只能放满七成,空出来的三成空间成为物品出入的通道,这样会让人有收拾整齐的欲望和心情。</p> <p><code>五</code>:<code>看得见的收纳</code>只放五成,主要作用于看得见的位置,比如置物架,茶几等等,比如商场高级的商品,摆放位置较零散。</p> <p><code>一</code>:通常用于装饰墙之类的,例如美术馆的画展,名画都单独挂在一面墙,显示了这幅画的重要性,营造了高端的感觉。</p> <p><code>总量限制替换原则</code>:当收纳超出<code>七五一原则</code>时,就需要考虑限制总量不变,替换现有的物品或者限制新入的物品</p> <h2>‌单一动作原则</h2> <p>收纳,要让(经常使用的)物品依赖尽量少的动作就能拿出来</p> <h2>‌自立原则</h2> <p>收纳尽量避免堆叠,立体放置可以让下面的/里面的物品更便于取出</p> 个人成长https://www.scarsu.com/danshari/#post-comment/如何与情绪相处https://www.scarsu.com/emotions/https://www.scarsu.com/emotions/接受、正视、了解我们的感觉和情绪Tue, 09 Jul 2019 00:00:00 GMT<p>从人性上来说,我们倾向于保护自我最脆弱的部分</p> <p>伤痛、需求未被满足、罪恶、耻辱会激发我们痛苦、恐惧、愤怒的情绪,这是人类天生的保护机制</p> <p>我们无法控制自己的本能,但是应该学会接受、正视、了解我们的感觉和情绪,</p> <p>去发现并解决 情绪背后 激发情绪的问题,而不是去任由情绪发泄</p> 个人成长https://www.scarsu.com/emotions/#post-comment/如何追求快乐https://www.scarsu.com/how_to_be_happy/https://www.scarsu.com/how_to_be_happy/短篇Tue, 09 Jul 2019 00:00:00 GMT<blockquote> <p>有很多快乐是放纵的快乐,是降低了人性尊严的快乐,而越能体现人性尊严的快乐,越是一种高级的快乐。</p> <p>追求高级的快乐并不意味着放弃低级的快乐,但是如果你的眼目永远只关注地下,你永远不知道向上看有多么的快乐。</p> </blockquote> <p>——罗翔</p> <p><a>@https://www.bilibili.com/video/BV1AE411T7p7</a></p> <blockquote> <p>I don't need dollar bills to have fun</p> </blockquote> <p>——【Cheap Thrills】 Sia</p> <p>降低欲望、培养兴趣</p> <p>享受平静才是生活的真谛</p> <blockquote> <p>“上次我去一个朋友家玩,看到他们客厅里摆着一张很长的桌子。朋友说,每到周末,两个大人,一个孩子,还有两只猫都会围在这个桌子旁,家里很安静,只有书页翻动和画笔接触纸张的细微声音。”</p> </blockquote> 个人成长https://www.scarsu.com/how_to_be_happy/#post-comment/为什么要趁年轻多学习https://www.scarsu.com/keep_proper_pressure/https://www.scarsu.com/keep_proper_pressure/爆炸性压力才能带来爆炸性进步Tue, 09 Jul 2019 00:00:00 GMT<p><a>原文</a></p> <blockquote> <p><strong>爆炸性压力才能带来爆炸性进步</strong></p> <p>每次我状态低迷的时候,我都会看看这个视频,视频18分钟,如果你懒得看,我简述一下:</p> <p>演讲者是许峰源先生,他出身一个非常贫穷的家庭,整个家庭,靠的是父亲踩着三轮车出去卖豆腐微薄的收入支撑着。</p> <p>这不是一个烂仔逆袭的故事,因为从小看到了生活艰苦的一面,许峰源一直很努力想考上台大法律系,因为成为律师才有高收入,才能改变家庭的现状。</p> <p>不幸的是,在他上大学的时候,父亲却查出了舌癌晚期,只剩一年左右的时间,为了让父亲在临终前看到自己的孩子成才,许峰源用了极短的时间通过了司法考试,成为了一名律师,让父亲看到了自己的律师证,才安然去世。</p> <p>祸不单行,很快许峰源的母亲也查出了患有肺腺癌,一种扩散很迅猛的癌症,为了让母亲有一个安享晚年的环境,许峰源在23岁的时候,毅然辞职创业,白天在律师事务所打拼,晚上做培训,最终让母亲住上了好房子,接受更好的治疗,然后平静地送走了母亲。</p> <p>前半生,许峰源先生为之奋斗的两个对象都走了,迷茫了一阵子之后,他依然没有放弃努力,而是选择了实现自我,成为了一名作家。</p> <p>再烂的牌也得打下去,这就是人生</p> </blockquote> 个人成长https://www.scarsu.com/keep_proper_pressure/#post-comment/别让任何人打乱你的人生节奏https://www.scarsu.com/value_yourself/https://www.scarsu.com/value_yourself/短篇Tue, 09 Jul 2019 00:00:00 GMT<h2>每个人的人生都不同</h2> <blockquote> <p>"Not everything that counts can be counted,and not everything that's counted truly counts"</p> <p>"并不是每件算出来的事,都有意义;也不是每件有意义的事,都能被算出来" ——爱因斯坦</p> </blockquote> <p><a>@https://www.bilibili.com/video/BV1WW411F7Hx</a></p> <h2>建立自己的价值体系</h2> <p>世人觉得瘦才是美,你就要以健康为代价过度减肥; 世人觉得大眼睛双眼皮才是美,你就要花钱在脸上动刀; 世人觉得肤白才是美,你无法改变就去否定自己; 世人觉得出身决定地位,你就要否定自己和父母;</p> <p>不要再活在别人的价值体系下,</p> <p>不要再被这个世界灌输好与坏,</p> <p>自己亲身去感受、去体验、去思考,</p> <p>什么是真的好与坏</p> 个人成长https://www.scarsu.com/value_yourself/#post-comment/就是不想努力怎么办https://www.scarsu.com/why_make_efforts/https://www.scarsu.com/why_make_efforts/短篇Tue, 09 Jul 2019 00:00:00 GMT<blockquote> <p>我就想做一个安于现状的人</p> <p>就想利用上班赚钱过好自己的小日子</p> <p>就想平凡的过完一生</p> <p>我就是不想拼命奋斗,拼命努力,拼命内卷</p> <p>不可以吗?</p> </blockquote> <p>当然可以,每个人的追求不同,淡泊名利,平静一生,真正能做到的话,是一种很高的人生境界。</p> <p>但是你做出这种决定,就要考虑其带来的结果</p> <blockquote> <p>你能做到真正的“淡泊名利”吗?</p> <p>当别人用光鲜亮丽的服装、车子、房子包装和提升自己的生活品质时,你能做到不羡慕吗</p> <p>当别人在马尔代夫浮潜、在阿尔卑斯滑雪、在土耳其滑翔、在富士山脚泡温泉喝清酒,你能做到不羡慕吗</p> <p>你身边的人生活品质都比你高得时候,你会不会后悔</p> <p>你的普通收入扣除房子首付、房贷、车子、奶粉钱之后你还足够安稳吗</p> <p>如果不买房,你可以做到一生租房,并容忍一生到老不断的搬家吗</p> <p>你的普通收入能让你匹配上你心仪的另一半吗</p> <p>你的现状能维持你一生的稳定平凡吗?你能对抗人生所有的风险吗</p> <p>你可以为自己的一生、父母后半生、孩子前半生的大大小小的健康问题买单吗</p> <p>如果你有了孩子,你作为爸爸/妈妈,能给孩子最好的教育吗</p> </blockquote> <p>如果你深刻的考虑了这些问题,都能得到坚定的答案,那么安于现状,不拼命努力,也没什么不好</p> <p>每个人的人生都不同,人生的路也没有对错之分,只是路上的酸甜苦辣,你需要独自承担</p> 个人成长https://www.scarsu.com/why_make_efforts/#post-comment/JavaScript开发者应懂的33个概念https://www.scarsu.com/33_js_concepts/https://www.scarsu.com/33_js_concepts/知识点复盘手册Mon, 01 Jul 2019 00:00:00 GMT<h2>简介</h2> <p><a>原文链接</a></p> <blockquote> <p>本篇文章是参照 @leonardomso 创立,英文版项目地址在<a>这里</a>。</p> </blockquote> <hr /> <h2>目录</h2> <ol> <li><strong><a>调用堆栈</a></strong></li> <li><strong><a>原始类型</a></strong></li> <li><strong><a>值类型和引用类型</a></strong></li> <li><strong><a>隐式, 显式, 名义和鸭子类型</a></strong></li> <li><strong><a>== 与 ===, typeof 与 instanceof</a></strong></li> <li><strong><a>this, call, apply 和 bind</a></strong></li> <li><strong><a>函数作用域, 块级作用域和词法作用域</a></strong></li> <li><strong><a>闭包</a></strong></li> <li><strong><a>map, reduce, filter 等高阶函数</a></strong></li> <li><strong><a>表达式和语句</a></strong></li> <li><strong><a>变量提升</a></strong></li> <li><strong><a>Promise</a></strong></li> <li><strong><a>立即执行函数, 模块化, 命名空间</a></strong></li> <li><strong><a>递归</a></strong></li> <li><strong><a>算法</a></strong></li> <li><strong><a>数据结构</a></strong></li> <li><strong><a>消息队列和事件循环</a></strong></li> <li><strong><a>setTimeout, setInterval 和 requestAnimationFrame</a></strong></li> <li><strong><a>继承, 多态和代码复用</a></strong></li> <li><strong><a>按位操作符, 类数组对象和类型化数组</a></strong></li> <li><strong><a>DOM 树和渲染过程</a></strong></li> <li><strong><a>new 与构造函数, instanceof 与实例</a></strong></li> <li><strong><a>原型继承与原型链</a></strong></li> <li><strong><a>Object.create 和 Object.assign</a></strong></li> <li><strong><a>工厂函数和类</a></strong></li> <li><strong><a>设计模式</a></strong></li> <li><strong><a>Memoization</a></strong></li> <li><strong><a>纯函数, 函数副作用和状态变化</a></strong></li> <li><strong><a>耗性能操作和时间复杂度</a></strong></li> <li><strong><a>JavaScript 引擎</a></strong></li> <li><strong><a>二进制, 十进制, 十六进制, 科学记数法</a></strong></li> <li><strong><a>偏函数, 柯里化, Compose 和 Pipe</a></strong></li> <li><strong><a>代码整洁之道</a></strong></li> </ol> <hr /> <h2>1. 调用堆栈</h2> <h3>文章</h3> <ul> <li>:book: <a>Call Stack — MDN</a></li> <li>:book: <a>[译] JavaScript 如何工作:对引擎、运行时、调用堆栈的概述 —— 掘金</a></li> <li>:book: <a>[译] 理解 JavaScript 中的执行上下文和执行栈 —— 掘金</a></li> <li>:book: <a>这一次,彻底弄懂 JavaScript 执行机制 —— 掘金</a></li> <li>:book: <a>解读 JavaScript 之引擎、运行时和堆栈调用 —— 开源中国</a></li> <li>:book: <a>Tasks, microtasks, queues and schedules —— Jake Archibald</a></li> <li>:book: <a>Tasks, microtasks, queues and schedules(译) —— 掘金</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>What is the event loop anyway? —— 腾讯视频(英文字幕)</a></li> <li>:tv: <a>Understanding The JavaScript Call Stack, Event Queue, Event Table, &amp; Event Loop —— Bilibili</a></li> <li>:tv: <a>JS 中的变量提升、堆栈内存及闭包详解 —— Acfun</a></li> <li>:tv: <a>事件循环模型 —— PHP 中文网</a></li> <li>:tv: <a>Javascript: the Call Stack explained — Coding Blocks India</a></li> <li>:tv: <a>The JS Call Stack Explained In 9 Minutes — Colt Steele</a></li> <li>:tv: <a>JavaScript Execution Stack — Codecademy</a></li> <li>:tv: <a>What is the Call Stack? — Eric Traub</a></li> <li>:tv: <a>The Call Stack — Kevin Drumm</a></li> <li>:tv: <a>Understanding JavaScript Execution — Codesmith</a></li> <li>:tv: <a>Call Stack &amp; Event Loop — movies com</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>2. 原始类型</h2> <h3>文章</h3> <ul> <li>:book: <a>原始数据 —— MDN</a></li> <li>:book: <a>[译]JavaScript 是怎样编码数字的 —— SegmentFault</a></li> <li>:book: <a>每一个 JavaScript 开发者应该了解的浮点知识 —— 颜海镜</a></li> <li>:book: <a>JavaScript 标准参考教程(基本语法之数值) —— 阮一峰</a></li> <li>:book: <a>The Secret Life of JavaScript Primitives —— Angus Croll</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>javascript 六种数据类型 —— 慕课网</a></li> <li>:tv: <a>javascript 视频教程(数据类型) —— PHP 中文网</a></li> <li>:tv: <a>JavaScript Reference vs Primitive Types — Academind</a></li> <li>:tv: <a>JavaScript Primitive Types — Simon Sez IT</a></li> <li>:tv: <a>Javascript Primitive and Reference Types — Baljeet Singh</a></li> <li>:tv: <a>Value Types and Reference Types in JavaScript — Programming with Mosh</a></li> <li>:tv: <a>JavaScript Primitive Data Types — Avelx</a></li> <li>:tv: <a>Everything you never wanted to know about JavaScript numbers — Bartek Szopka</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>3. 值类型和引用类型</h2> <h3>文章</h3> <ul> <li>:book: <a>ECMAScript 引用类型 —— W3school</a></li> <li>:book: <a>js 中的值类型和引用类型的区别 —— 博客园</a></li> <li>:book: <a>JavaScript 的值传递和引用传递 —— FunDebug</a></li> <li>:book: <a>Primitive Types &amp; Reference Types in JavaScript —— Bran van der Meer</a></li> <li>:book: <a>JavaScript: Passing by Value or by Reference —— CSDN</a></li> <li>:book: <a>js 值引用和值复制 —— SegmentFault</a></li> <li>:book: <a>js- 引用和复制(传值和传址) —— CSDN</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>Javascript Pass by Value vs Pass by Reference — techsith</a></li> <li>:tv: <a>JavaScript Value vs Reference Types — Programming with Mosh</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>4. 隐式, 显式, 名义和鸭子类型</h2> <h3>文章</h3> <ul> <li>:book: <a>ECMAScript 类型转换 —— W3school</a></li> <li>:book: <a>JavaScript 的怪癖 1:隐式类型转换 —— justjavac</a></li> <li>:book: <a>JavaScript 运算符规则与隐式类型转换详解 —— 掘金</a></li> <li>:book: <a>聊一聊 JS 中的隐式类型转换 —— SegmentFault</a></li> <li>:book: <a>有趣的 JavaScript 隐式类型转换 —— 博客园</a></li> <li>:book: <a>JavaScript 显式类型转换与隐式类型转换 —— CSDN</a></li> <li>:book: <a>你不知道的 JavaScript(中卷)强制类型转换 —— 简书</a></li> <li>:book: <a>你懂 JavaScript 嗎?#8 強制轉型 —— cythilya</a></li> <li>:book: <a>动态类型语言和鸭子类型 —— 曾探</a></li> <li>:book: <a>Nominal &amp; Structural Typing —— flow</a></li> <li>:book: <a>What exactly is Type Coercion in Javascript? —— stackoverflow</a></li> <li>:book: <a>You Don't Know JS: Types &amp; Grammar —— github</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>javascript 隐式转换 —— 慕课网</a></li> <li>:tv: <a>Javascript 基础加强-类型转换 —— 黑马程序员</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <p>&lt;div id="5--vs--typeof-vs-instanceof"&gt;&lt;/div&gt;</p> <h2>5. == vs ===, typeof vs instanceof</h2> <h3>文章</h3> <ul> <li>:book: <a>JavaScript 中的相等性判断 —— MDN</a></li> <li>:book: <a>js 中 == 和 === 的区别 —— 掘金</a></li> <li>:book: <a>== vs === in Javascript —— CSDN</a></li> <li>:book: <a>深入理解 javascript 之 typeof 和 instanceof —— CSDN</a></li> <li>:book: <a>JavaScript 的 typeof 的用途 —— justjavac</a></li> <li>:book: <a>一张图看懂 Function 和 Object 的关系及简述 instanceof 运算符 —— 掘金</a></li> <li>:book: <a>浅谈 instanceof 和 typeof 的实现原理 —— 掘金</a></li> <li>:book: <a>typeof 和 instanceOf 的区别</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>6. this, call, apply 和 bind</h2> <h3>文章</h3> <ul> <li>:book: <a>Javascript 的 this 用法 —— 阮一峰</a></li> <li>:book: <a>学会 JS 的 this 这一篇就够了,根本不用记 —— 简书</a></li> <li>:book: <a>[译] this(他喵的)到底是什么 — 理解 JavaScript 中的 this、call、apply 和 bind —— 掘金</a></li> <li>:book: <a>this、apply、call、bind —— 掘金</a></li> <li>:book: <a>使用 call、apply 和 bind 解决 js 中烦人的 this,事件绑定时的 this 和传参问题 —— 博客园</a></li> <li>:book: <a>call、apply 和 bind 的原生实现 —— github</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>JavaScript 关于 this 关键字解释 —— 爱奇艺</a></li> <li>:tv: <a>JS 关于作用域闭包和 this 的综合面试题 —— 百度视频</a></li> <li>:tv: <a>js 面向对象闭包数组 12.函数中的 this —— 乐视视频</a></li> <li>:tv: <a>1.3.10-this 指向及 this 应用 —— 乐视视频</a></li> <li>:tv: <a>珠峰培训 JavaScript 开发课程:关于 this 关键字、闭包作用域 —— 网易云课堂</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>7. 函数作用域, 块级作用域和词法作用域</h2> <h3>文章</h3> <ul> <li>:book: <a>变量作用域与解构赋值 —— 廖雪峰</a></li> <li>:book: <a>学习 Javascript 闭包(Closure) —— 阮一峰</a></li> <li>:book: <a>JavaScript 中词法作用域、闭包与跳出闭包 —— SegmentFault</a></li> <li>:book: <a>JavaScript 深入之词法作用域和动态作用域 —— 掘金</a></li> <li>:book: <a>深入理解闭包之前置知识 → 作用域与词法作用域 —— 掘金</a></li> <li>:book: <a>What is lexical scope? —— stackoverflow</a></li> <li>:book: <a>You Don't Know JS: Scope &amp; Closures —— Kyle Simpson</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>8. 闭包</h2> <h3>文章</h3> <ul> <li>:book: <a>闭包 —— MDN</a></li> <li>:book: <a>ECMAScript 闭包(closure)—— w3school</a></li> <li>:book: <a>学习 Javascript 闭包(Closure) —— 阮一峰</a></li> <li>:book: <a>闭包 —— 廖雪峰</a></li> <li>:book: <a>一次性搞懂 JavaScript 闭包 —— 简书</a></li> <li>:book: <a>JavaScript 闭包 —— SegmentFault</a></li> <li>:book: <a>js 匿名自执行函数中闭包的高级使用 —— 掘金</a></li> <li>:book: <a>高效使用 JavaScript 闭包 —— 掘金</a></li> <li>:book: <a>深入理解 JavaScript 原型与闭包 —— 王福朋</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>JavaScript 闭包和闭包面试题 —— 爱奇艺</a></li> <li>:tv: <a>js 面向对象闭包数组 11.闭包 —— 乐视</a></li> <li>:tv: <a>白贺翔_函数(闭包) —— 乐视</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>9. map, reduce, filter 等高阶函数</h2> <h3>文章</h3> <ul> <li>:book: <a>高阶函数 —— 廖雪峰</a></li> <li>:book: <a>ES5 中新增的 Array 方法详细说明 —— 张鑫旭</a></li> <li>:book: <a>一张图看懂 JavaScript 中数组的迭代方法:forEach、map、filter、reduce、every、some —— 掘金</a></li> <li>:book: <a>Transducing(上)-《JavaScript 轻量级函数式编程》 —— SegmentFault</a></li> <li>:book: <a>JavaScript 函数式编程(三) —— @BuptStEve</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>10. 表达式和语句</h2> <h3>文章</h3> <ul> <li>:book: <a>js 表达式与语句 —— 博客园</a></li> <li>:book: <a>JS 表达式和语句的区别 —— SegmentFault</a></li> <li>:book: <a>JavaScript 中的表达式(expression)和语句/声明(statement) —— CSDN</a></li> <li>:book: <a>重讀 Axel 的 Javascript 中的 Expression vs Statement 一文 —— SegmentFault</a></li> <li>:book: <a>Expressions versus statements in JavaScript —— Dr. Axel</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>11. 变量提升</h2> <h3>文章</h3> <ul> <li>:book: <a>JavaScript 变量提升 —— 菜鸟教程</a></li> <li>:book: <a>ES6 变量作用域与提升:变量的生命周期详解 —— 掘金</a></li> <li>:book: <a>[翻译] JavaScript Scoping and Hoisting —— SegmentFault</a></li> <li>:book: <a>JavaScript Scoping and Hoisting —— Ben Cherry</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>12. Promise</h2> <h3>文章</h3> <ul> <li>:book: <a>使用 promises —— MDN</a></li> <li>:book: <a>Promise —— MDN</a></li> <li>:book: <a>Promise — 廖雪峰</a></li> <li>:book: <a>JavaScript Promise:去而复返 —— 司徒正美</a></li> <li>:book: <a>(上面的原文)JavaScript Promise:简介 —— Web Fundamentals</a></li> <li>:book: <a>1 分钟读完《10 分钟学会 JavaScript 的 Async/Await》 —— justjavac</a></li> <li>:book: <a>JavaScript Promise 迷你书(中文版)</a></li> <li>:book: <a>JavaScript 进阶之路——认识和使用 Promise,重构你的 Js 代码 —— 博客园</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>Promise 入门 —— 慕课网</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>13. 立即执行函数, 模块化, 命名空间</h2> <h3>文章</h3> <ul> <li>:book: <a>Javascript 模块化编程(一):模块的写法 —— 阮一峰</a></li> <li>:book: <a>javascript 模块化编程-详解立即执行函数表达式 —— 简书</a></li> <li>:book: <a>Javascript 的匿名函数与自执行 —— 掘金</a></li> <li>:book: <a>前端模块化——技术选型 —— SegmentFault</a></li> <li>:book: <a>谈谈 Js 前端模块化规范 —— SegmentFault</a></li> <li>:book: <a>函数声明与函数表达式的区别 —— 伯乐在线</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>14. 递归</h2> <h3>文章</h3> <ul> <li>:book: <a>求解释 js 递归 —— SegmentFault</a></li> <li>:book: <a>JavaScript 中的递归 —— 掘金</a></li> <li>:book: <a>递归(上)-《JavaScript 轻量级函数式编程》 —— 掘金</a></li> <li>:book: <a>递归(下)-《JavaScript 轻量级函数式编程》 —— 掘金</a></li> <li>:book: <a>尾调用和尾递归 —— 掘金</a></li> <li>:book: <a>几个经典递归问题用 js 实现 —— CSDN</a></li> <li>:book: <a>递归函数的几个例子 —— CSDN</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>15. 算法</h2> <h3>文章</h3> <ul> <li>:book: <a>十大经典排序算法总结(JavaScript 描述) —— 掘金</a></li> <li>:book: <a>在 JavaScript 中学习数据结构与算法 —— 掘金</a></li> <li>:book: <a>JS 中可能用得到的全部的排序算法 —— 掘金</a></li> <li>:book: <a>JS 家的排序算法 —— 简书</a></li> <li>:book: <a>前端常见算法的 JS 实现 —— SegmentFault</a></li> <li>:book: <a>前端面试中的常见的算法问题 ——蒲小花的博客</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>Javascript 实现二叉树算法 —— 慕课网</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>16. 数据结构</h2> <h3>文章</h3> <ul> <li>:book: <a>来我们浅谈一下 js 的数据结构 —— 简书</a></li> <li>:book: <a>JavaScript 中的算法与数据结构 —— 简书</a></li> <li>:book: <a>学 JS 必看-JavaScript 数据结构深度剖析 —— 大道至简的博客</a></li> <li>:book: <a>js 中基础数据结构数组去重问题 —— 掘金</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: :tv: <a>JavaScript 数据结构-运算符 —— 乐视</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>17. 消息队列和事件循环</h2> <h3>文章</h3> <ul> <li>:book: <a>并发模型与事件循环 —— MDN</a></li> <li>:book: <a>JavaScript 运行机制详解:再谈 Event Loop —— 阮一峰</a></li> <li>:book: <a>深入理解 JavaScript 事件循环 —— 博客园</a></li> <li>:book: <a>深入浅出 Javascript 事件循环机制 —— 知乎</a></li> <li>:book: <a>JS 事件循环机制(event loop)之宏任务、微任务 —— SegmentFault</a></li> <li>:book: <a>JavaScript:彻底理解同步、异步和事件循环 —— SegmentFault</a></li> <li>:book: <a>从浏览器多进程到 JS 单线程,JS 运行机制最全面的一次梳理 —— 掘金</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>18. setTimeout, setInterval 和 requestAnimationFrame</h2> <h3>文章</h3> <ul> <li>:book: <a>Window setTimeout() 方法 —— 菜鸟教程</a></li> <li>:book: <a>Window setInterval() 方法 —— 菜鸟教程</a></li> <li>:book: <a>关于 setTimeout —— 掘金</a></li> <li>:book: <a>你不知道的 Javascript:有趣的 setTimeout —— 掘金</a></li> <li>:book: <a>原来你是这样的 setTimeout —— 掘金</a></li> <li>:book: <a>setTimeout() 和 setInterval() 本质区别在哪里? —— SegmentFault</a></li> <li>book: <a>window.requestAnimationFrame —— MDN</a></li> <li>:book: <a>requestAnimationFrame 知多少? —— 博客园</a></li> <li>:book: <a>CSS3 动画那么强,requestAnimationFrame 还有毛线用? —— 张鑫旭</a></li> <li>:book: <a>「JavaScript 定时器」setInterval、setTimeout 和 requestAnimationFrame 浅析 —— SegmentFault</a></li> <li>:book: <a>翻译:setInterval 与 requestAnimationFrame 的时间间隔测试 —— SegmentFault</a></li> <li>:book: <a>阿里前端面试题:requestAnimationFrame 实现类似 setInterval 的计时器 —— SegmentFault</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>setTimeout 和 setInterval —— 优酷</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>19. 继承, 多态和代码复用</h2> <h3>文章</h3> <ul> <li>:book: <a>JS 面向对象编程之:封装、继承、多态 —— 博客园</a></li> <li>:book: <a>Javascript 的继承与多态 —— 简书</a></li> <li>:book: <a>js:面向对象编程,带你认识封装、继承和多态 —— 掘金</a></li> <li>:book: <a>JavaScript 中的“多继承” —— 掘金</a></li> <li>:book: <a>代码复用模式 —— github</a></li> <li>:book: <a>深入理解 JavaScript:代码复用模式(推荐篇) —— 汤姆大叔</a></li> <li>:book: <a>深入理解 JavaScript:代码复用模式(避免篇) —— 汤姆大叔</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>20. 按位操作符, 类数组对象和类型化数组</h2> <h3>文章</h3> <ul> <li>:book: <a>按位操作符 —— MDN</a></li> <li>:book: <a>类数组对象 —— MDN</a></li> <li>:book: <a>类型化数组 —— MDN</a></li> <li>:book: <a>JavaScript ArrayBuffer 浅析 —— 博客园</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>21. DOM 树和渲染过程</h2> <h3>文章</h3> <ul> <li>:book: <a>如何创建一个 DOM 树 —— MDN</a></li> <li>:book: <a>HTML DOM 节点 —— W3school</a></li> <li>:book: <a>DOM 概述 —— 阮一峰</a></li> <li>:book: <a>《JavaScript 闯关记》之 DOM(上)—— 掘金</a></li> <li>:book: <a>《JavaScript 闯关记》之 DOM(下)—— 掘金</a></li> <li>:book: <a>掌握 DOM 操作 —— 掘金</a></li> <li>:book: <a>操作 DOM —— 廖雪峰</a></li> <li>:book: <a>原来 CSS 与 JS 是这样阻塞 DOM 解析和渲染的 —— 掘金</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>DOM 探索之基础详解篇 —— 慕课网</a></li> <li>:tv: <a>DOM 事件探秘 —— 慕课网</a></li> <li>:tv: <a>jQuery 基础(二)DOM 篇 —— 慕课网</a></li> <li>:tv: <a>JS 操作 DOM 对象属性和方法 —— 爱奇艺</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>22. new 与构造函数, instanceof 与实例</h2> <h3>文章</h3> <ul> <li>:book: <a>构造函数与 new 命令 —— 阮一峰</a></li> <li>:book: <a>Javascript 面向对象编程(二):构造函数的继承 —— 阮一峰</a></li> <li>:book: <a>完整原型链详细图解(构造函数、原型、实例化对象) —— CSDN</a></li> <li>:book: <a>JavaScript 中构造函数与 new 操作符的实例详解 —— PHP 中文网</a></li> <li>:book: <a>构造函数、实例、原型、原型链之间的关系 —— CSDN</a></li> <li>:book: <a>深入理解 JS—instanceof 和原型链 —— CSDN</a></li> <li>:book: <a>前端基础进阶(九):详解面向对象、构造函数、原型与原型链 —— 简书</a></li> <li>:book: <a>js 用 new 实例化对象与直接调用的 this 的区别 —— 简书</a></li> <li>:book: <a>JavaScript 并非所有的东西都是对象 —— justjavac</a></li> <li>:book: <a>JavaScript instanceof 运算符深入剖析 —— IBM</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>改良版的构造函数 —— 乐视</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>23. 原型继承与原型链</h2> <h3>文章</h3> <ul> <li>:book: <a>继承与原型链 —— MDN</a></li> <li>:book: <a>构造函数、原型与原型链 —— github</a></li> <li>:book: <a>原型及原型链 —— github(1269 Star)</a></li> <li>:book: <a>理清 javascript 中的面向对象(一) 原型继承 —— SegmentFault</a></li> <li>:book: <a>JavaScript:继承和原型链(译) —— justjavac</a></li> <li>:book: <a>三张图搞懂 JavaScript 的原型对象与原型链 —— 博客园</a></li> <li>:book: <a>一张图让你搞懂 JavaScript 的继承与原型链 —— CSDN</a></li> <li>:book: <a>JS 高级--原型链(一看就懂,但 18 岁以下请绕道) —— CSDN</a></li> <li>:book: <a>原型继承 —— 廖雪峰</a></li> <li>:book: <a>JS 原型链与继承别再被问倒了 —— 掘金</a></li> <li>:book: <a>征服 JavaScript 面试系列:类继承和原型继承的区别 —— 掘金</a></li> <li>:book: <a>JavaScript 深入之从原型到原型链 —— 冴羽</a></li> <li>:book: <a>深入理解 JavaScript 原型与闭包 —— 王福朋</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>JS 高级-07-原型链继承 —— 乐视</a></li> <li>:tv: <a>JS 原型对象和原型链简介 —— 腾讯视频</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>24. Object.create 和 Object.assign</h2> <h3>文章</h3> <ul> <li>:book: <a>Object.create —— MDN</a></li> <li>:book: <a>Object.assign —— MDN</a></li> <li>:book: <a>Object.create vs Object.assign —— 慕课网手记</a></li> <li>:book: <a>JS 中的 Object.assign()、Object.create()、Object.defineProperty() —— CSDN</a></li> <li>:book: <a>es6 中 object.create()和 object.assign() —— 风信子博客</a></li> <li>:book: <a>Object-Assign-Deep —— github</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>25. 工厂函数和类</h2> <h3>文章</h3> <ul> <li>:book: <a>类 —— MDN</a></li> <li>:book: <a>类和实例 —— 廖雪峰</a></li> <li>:book: <a>Javascript 定义类(class)的三种方法 —— 阮一峰</a></li> <li>:book: <a>【译】ES6 的工厂函数 —— 掘金</a></li> <li>:book: <a>JavaScript 创建对象之单例、工厂、构造函数模式 —— 掘金</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>26. 设计模式</h2> <h3>文章</h3> <ul> <li>:book: <a>JavaScript 设计模式 —— 掘金</a></li> <li>:book: <a>学用 JavaScript 设计模式 —— 极客学院</a></li> <li>:book: <a>[面试专题]JS 设计模式 —— SegmentFault</a></li> <li>:book: <a>JavaScript Patterns 中译本 —— github</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>HTML5 课程大纲 2-11JS 设计模式</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>27. Memoization</h2> <h3>文章</h3> <ul> <li>:book: <a>JavaScript Memoization —— 司徒正美</a></li> <li>:book: <a>memoization 提升递归效率 —— 博客园</a></li> <li>:book: <a>如何提升 JavaScript 的递归效率 —— 51CTO</a></li> <li>:book: <a>JavaScript 高级技巧 Memoization —— SegmentFaut</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>28. 纯函数, 函数副作用和状态变化</h2> <h3>文章</h3> <ul> <li>:book: <a>纯函数(Pure Function) —— React.js 小书</a></li> <li>:book: <a>JavaScript Functional Programming:纯函数 —— 宁皓网</a></li> <li>:book: <a>js 函数的副作用分析 —— 脚本之家</a></li> <li>:book: <a>如何使用纯函数式 JavaScript 处理脏副作用 —— 掘金</a></li> <li>:book: <a>原生 JavaScript 实现 state 状态管理系统 —— 博客园</a></li> <li>:book: <a>JavaScript 函数式编程 —— @BuptStEve</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>29. 耗性能操作和时间复杂度</h2> <h3>文章</h3> <ul> <li>:book: <a>时间复杂度 O(log n) 意味着什么? —— 掘金</a></li> <li>:book: <a>算法的时间复杂度和空间复杂度 —— 掘金</a></li> <li>:book: <a>算法(一)时间复杂度 —— 掘金</a></li> <li>:book: <a>Big O Search Algorithms in JavaScript —— Bradley Braithwaite</a></li> <li>:book: <a>Time Complexity Analysis in JavaScript — Jennifer Bland</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>30. JavaScript 引擎</h2> <h3>文章</h3> <ul> <li>:book: <a>javascript 引擎 —— 百度百科</a></li> <li>:book: <a>V8(JavaScript 引擎) —— 百度百科</a></li> <li>:book: <a>图解搞懂 JavaScript 引擎 Event Loop —— 掘金</a>3</li> <li>:book: <a>V8 JavaScript 引擎:高性能的 ES2015+ —— justjavac</a></li> <li>:book: <a>10 分钟理解 JS 引擎的执行机制 —— SegmentFaut</a></li> <li>:book: <a>V8 javascript 引擎 —— 博客园</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>31. 二进制, 十六进制, 十进制, 科学记数法</h2> <h3>文章</h3> <ul> <li>:book: <a>二、八、十、十六进制转换(图解篇) —— 博客园</a></li> <li>:book: <a>JavaScript 读写二进制数据 —— 掘金</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>二进制、十进制、十六进制互相转化很难吗? —— 百度视频</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>32. 偏函数, 柯里化, Compose 和 Pipe</h2> <h3>文章</h3> <ul> <li>:book: <a>Javascript 函数式编程之偏函数 —— CSDN</a></li> <li>:book: <a>JavaScript 专题之偏函数 —— SegmentFault</a></li> <li>:book: <a>柯里化和偏函数有什么区别? —— SegmentFault</a></li> <li>:book: <a>Javascript 偏函数与柯里化 —— CSDN</a></li> <li>:book: <a>柯里化(curry) —— JS 函数式编程指南</a></li> <li>:book: <a>代码组合(compose) —— JS 函数式编程指南</a></li> <li>:book: <a>关于 javascript 函数式编程中 compose 的实现 —— SegmentFault</a></li> <li>:book: <a>实现 compose 的五种思路 —— SegmentFault</a></li> <li>:book: <a>JavaScript 函数式编程之函数组合函数 compose 和 pipe 的实现 —— SegmentFault</a></li> <li>:book: <a>JavaScript 轻量级函数式编程-第 4 章:组合函数 ——掘金</a></li> <li>:book: <a>JavaScript 函数式编程(二) —— @BuptStEve</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>33. 代码整洁之道</h2> <h3>文章</h3> <ul> <li>:book: <a>[译] JavaScript 代码整洁之道 —— 边城</a></li> <li>:book: <a>Javascript 编程风格 —— 阮一峰</a></li> <li>:book: <a>重构 - 代码整洁之道 —— 掘金</a></li> <li>:book: <a>让你的代码更简短,更整洁,更易读的 ES6 小技巧 —— 掘金</a></li> <li>:book: <a>Web 前端:11 个让你代码整洁的原则 —— 伯乐在线</a></li> <li>:book: <a>Clean Code concepts adapted for JavaScript —— ryanmcdermott</a></li> </ul> <p>&lt;br&gt;</p> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> 前端https://www.scarsu.com/33_js_concepts/#post-comment/Grunt 学习总结https://www.scarsu.com/grunt/https://www.scarsu.com/grunt/自动化 压缩(minification)、编译、单元测试、linting等Sat, 01 Jun 2019 00:00:00 GMT<h1>是什么 &amp; 用途 &amp; 场景</h1> <p>grunt本身是一种自动化任务处理工具,它是一个工具框架,有很多插件扩展它的功能。</p> <p>通过丰富的grunt插件可以实现以下功能:</p> <ul> <li>jshint代码检查</li> <li>代码合并</li> <li>代码压缩--js/css/html都可以</li> <li>SASS/LESS编译css</li> <li>watch监听---文件发生改变自动执行任务</li> </ul> <h1>相关</h1> <ul> <li><a>官方github</a></li> <li><a>官方网址(文档)</a></li> <li><a>中文文档</a></li> <li><a>插件列表</a></li> </ul> <h1>环境</h1> <p>grunt依赖Nodejs和npm环境</p> <p>使用npm安装全局grunt-cli命令行工具:<code>npm install -g grunt-cli</code></p> <h1>demo</h1> <ol> <li>需求</li> </ol> <p>假设你手上有一个项目,叫gruntlearn,项目文件中你的源码存储在src目录下,包含四个模块的js文件,还没编译的scss文件,html文件,图片文件:</p> <p><img src="/images/grunt/grunt01.png" alt="demo src 目录结构" /></p> <p>现在你想用grunt,自动给你的源代码执行几个任务:</p> <ul> <li>将images/html和复制到 发布文件夹build下</li> <li>用jshint检查js语法</li> <li>合并四个js文件(分别合并,因为a,b用于不同的页面)</li> <li>编译scss文件</li> <li>压缩合并后的js文件,存储到build下</li> <li>调试:新建一个本地服务器监听文件改变自动刷新HTML文件</li> </ul> <ol> <li>搭建环境</li> </ol> <ul> <li>在命令行里打开到gruntlearn的目录下,执行<code>npm init</code></li> <li>安装 grunt 和 grunt-cli</li> </ul> <pre><code>npm install grunt-cli --global npm install grunt --save-dev </code></pre> <ul> <li>在项目中安装grunt和相关插件,根据第1步中的需求,需要用到一下插件: <ul> <li>复制文件:grunt-contrib-copy</li> <li>合并文件:grunt-contrib-concat</li> <li>语法检查:grunt-contrib-jshint</li> <li>Scss 编译:grunt-contrib-sass</li> <li>压缩文件:grunt-contrib-uglify</li> <li>监听文件变动:grunt-contrib-watch</li> <li>建立本地服务器:grunt-contrib-connect</li> </ul> </li> <li>安装插件:</li> </ul> <pre><code>npm install --save-dev grunt-contrib-copy grunt-contrib-concat grunt-contrib-jshint grunt-contrib-sass grunt-contrib-uglify grunt-contrib-watch grunt-contrib-connect </code></pre> <ul> <li> <p>创建gruntfile.js文件,代码结构: <img src="/images/grunt/grunt02.png" alt="gruntfile.js 代码结构" /></p> </li> <li> <p>根据demo需求配置gruntfile:</p> </li> </ul> <pre><code>//wrapper函数 module.exports = function (grunt) { //你可以像普通的js文件一样添加自己的代码 var sassStyle = "expanded"; //1.配置任务 tasks--根据插件的文档来定义任务 grunt.initConfig({ pkg: grunt.file.readJSON("package.json"), //将html和图片从src复制到build copy: { //task html: { //target files: [ { expand: true, cwd: "./src/html", src: "*", dest: "./build/html/" }, ], }, images: { //target files: [ { expand: true, cwd: "./src/images", src: "*", dest: "./build/images/", }, ], }, }, //合并js concat: { /* options: { separator: ';',//合并分隔符 }, */ dist: { files: { //文件路径 "./src/js/a.all.js": ["./src/js/a.1.js", "./src/js/a.2.js"], "./src/js/b.all.js": ["./src/js/b.1.js", "./src/js/b.2.js"], }, }, }, //task:编译sass sass: { output: { //target options: { //target options style: sassStyle, }, files: { "./build/css/style.css": "./src/scss/style.scss", //'目标文件':'源文件' }, }, }, //代码检查 jshint: { all: ["./src/js/a.all.js", "./src/js/b.all.js"], }, //压缩 uglify: { uglifyjs: { files: { "./build/js/a.min.js": ["./src/js/a.all.js"], "./build/js/b.min.js": ["./src/js/b.all.js"], }, }, }, //监听 watch: { scripts: { files: [ "./src/js/a.1.js", "./src/js/a.2.js", "./src/js/b.1.js", "/src/js/b.2.js", ], tasks: ["concat", "jshint", "uglify"], }, sass: { files: ["./src/scss/style.scss"], tasks: ["sass"], }, livereload: { options: { liverelload: "&lt;%= connect.options.livereload %&gt;", }, files: [ "./src/html/index.html", "./src/scss/style.scss", "./src/js/a.1.js", "./src/js/a.2.js", "./src/js/b.1.js", "./src/js/b.2.js", ], }, }, connect: { options: { port: 9000, open: true, livareload: 35729, //change this to '0.0.0.0' to access the server from outside hostname: "localhost", }, server: { options: { port: 9001, base: "./", }, }, }, }); //2.加载插件 grunt.loadNpmTasks("grunt-contrib-copy"); grunt.loadNpmTasks("grunt-contrib-concat"); grunt.loadNpmTasks("grunt-contrib-sass"); grunt.loadNpmTasks("grunt-contrib-jshint"); grunt.loadNpmTasks("grunt-contrib-uglify"); grunt.loadNpmTasks("grunt-contrib-watch"); grunt.loadNpmTasks("grunt-contrib-connect"); //3.注册任务 grunt.registerTask("copyhtml", ["copy:html"]); //可以用task:target的方法分别注册 grunt.registerTask("concatjs", ["concat"]); //也可以只用task名称注册,默认执行task下全部target grunt.registerTask("outputcss", ["sass"]); grunt.registerTask("watchit", [ "concat", "sass", "jshint", "uglify", "connect", "watch", ]); grunt.registerTask("default", ["copy", "concat", "sass", "jshint", "uglify"]); }; </code></pre> <ul> <li> <p>执行定义好的命令<code>grunt default</code>: <img src="/images/grunt/grunt03.png" alt="执行命令" /></p> </li> <li> <p>执行后的项目目录结构: <img src="/images/grunt/grunt04.png" alt="执行后目录结构" /></p> </li> </ul> 前端https://www.scarsu.com/grunt/#post-comment/英语 | 计算机相关 单词书📖https://www.scarsu.com/cs_english/https://www.scarsu.com/cs_english/总结一下,我看英文前端文档/视频遇到的一些计算机/前端相关的单词/专业术语Tue, 01 Jan 2019 00:00:00 GMT<p>从2014年大一过了六级之后,就把学英语落下了,但是作为一名程序员,英语是很重要的。</p> <p>所以工作之后经常刻意要求自己读英文文档,也看过一些英文前端视频,比如FrontEndMaster、WesBos。</p> <p>利用本文总结一下,我看英文前端文档/视频遇到的一些计算机/前端相关的单词/专业术语/非英语环境难遇到的一些词汇👇。</p> <p>(另外推荐一个相关资源:<a>中国程序员容易发音错误的单词</a>)</p> <table> <thead> <tr> <th>单词</th> <th>释义</th> <th>来源</th> </tr> </thead> <tbody> <tr> <td>under the hood</td> <td>底层</td> <td></td> </tr> <tr> <td>specify</td> <td>指定</td> <td></td> </tr> <tr> <td>get passed in</td> <td>传入</td> <td></td> </tr> <tr> <td>sync/async</td> <td>同步异步</td> <td></td> </tr> <tr> <td>asynchronously</td> <td>异步</td> <td></td> </tr> <tr> <td>whatnot</td> <td>诸如此类的</td> <td></td> </tr> <tr> <td>in good shape</td> <td>(运行代码的时候祈祷的</td> <td></td> </tr> <tr> <td>gotchas</td> <td>陷阱</td> <td></td> </tr> <tr> <td>shortcut</td> <td>捷径</td> <td></td> </tr> <tr> <td>inventory</td> <td>库存/牛</td> <td></td> </tr> <tr> <td>neat</td> <td>整齐利落</td> <td></td> </tr> <tr> <td>scaffold</td> <td>脚手架</td> <td></td> </tr> <tr> <td>handy</td> <td>便利</td> <td></td> </tr> <tr> <td>ultimate</td> <td>最终</td> <td></td> </tr> <tr> <td>rewind</td> <td>倒回/回退</td> <td></td> </tr> <tr> <td>isolation</td> <td>隔离</td> <td></td> </tr> <tr> <td>interfere</td> <td>妨碍 打扰</td> <td></td> </tr> <tr> <td>capture</td> <td>捕获</td> <td></td> </tr> <tr> <td>raw</td> <td>原生的</td> <td></td> </tr> <tr> <td>vanilla js</td> <td>raw js:原生js</td> <td></td> </tr> <tr> <td>nail</td> <td>钉子 固定 (巩固知识)</td> <td></td> </tr> <tr> <td>built-in</td> <td>内置的</td> <td></td> </tr> <tr> <td>newbies</td> <td>新手</td> <td></td> </tr> <tr> <td>tutorial</td> <td>教程</td> <td></td> </tr> <tr> <td>sane</td> <td>合理的明智的</td> <td></td> </tr> <tr> <td>modular</td> <td>模块化的</td> <td></td> </tr> <tr> <td>cardio</td> <td>有氧运动</td> <td></td> </tr> <tr> <td>hard code</td> <td>写死的代码</td> <td></td> </tr> <tr> <td>reinstate</td> <td>恢复</td> <td></td> </tr> <tr> <td>verbose</td> <td>冗余的</td> <td></td> </tr> <tr> <td>upstream</td> <td>(向上返回)</td> <td></td> </tr> <tr> <td>downstream</td> <td>(向下传)</td> <td></td> </tr> <tr> <td>CRUD acronym</td> <td>CRUD</td> <td></td> </tr> <tr> <td>manually</td> <td>手动</td> <td></td> </tr> <tr> <td>DEPRECATED</td> <td>启用</td> <td></td> </tr> <tr> <td>bottleneck</td> <td>瓶颈</td> <td></td> </tr> <tr> <td>audit</td> <td>审计</td> <td></td> </tr> <tr> <td>monitor</td> <td>监控</td> <td></td> </tr> <tr> <td>profile</td> <td>分析</td> <td></td> </tr> <tr> <td>memory leaks</td> <td>内存泄漏</td> <td></td> </tr> <tr> <td>emulate/simulation</td> <td>仿真/模拟</td> <td></td> </tr> <tr> <td>refactor</td> <td>重构</td> <td></td> </tr> <tr> <td>parser</td> <td>解析器</td> <td></td> </tr> <tr> <td>anonymous</td> <td>匿名</td> <td></td> </tr> <tr> <td>deactivated</td> <td>停用</td> <td></td> </tr> <tr> <td>stats</td> <td>统计数据</td> <td></td> </tr> <tr> <td>optimization</td> <td>优化</td> <td></td> </tr> <tr> <td>AST abstract syntax tree</td> <td>抽象语法树</td> <td></td> </tr> <tr> <td>meg</td> <td>兆</td> <td></td> </tr> <tr> <td>thrashing</td> <td>抖动</td> <td></td> </tr> <tr> <td>idle</td> <td>空闲</td> <td></td> </tr> <tr> <td>trigger</td> <td>触发</td> <td></td> </tr> <tr> <td>GC garbage collector</td> <td>垃圾回收器</td> <td></td> </tr> <tr> <td>snapshot</td> <td>快照</td> <td></td> </tr> <tr> <td>shallow size</td> <td>是指用于存储其本身的内存大小</td> <td></td> </tr> <tr> <td>retained size</td> <td>释放该对象后对象所占总内存该类的所有实例可支配的内存大小</td> <td></td> </tr> <tr> <td>heap snapshot</td> <td>堆快照</td> <td></td> </tr> <tr> <td>containment</td> <td>容量</td> <td></td> </tr> <tr> <td>overhead</td> <td>开销</td> <td></td> </tr> <tr> <td>distribution</td> <td>分配</td> <td></td> </tr> <tr> <td>timeline</td> <td>时间轴</td> <td></td> </tr> <tr> <td>delegate</td> <td>转交,委托</td> <td>Event Delegation事件委托</td> </tr> <tr> <td>prefix/postfix</td> <td>前缀后缀</td> <td></td> </tr> <tr> <td>Adaptor</td> <td>适配器</td> <td></td> </tr> <tr> <td>TL;DR</td> <td>too long;don't/didn't read 精华/总结</td> <td></td> </tr> <tr> <td>conjecture</td> <td>猜测猜想,推测</td> <td>https://www.codewars.com/kata/52fefe6cb0091856db00030e/train/javascript</td> </tr> <tr> <td>Threshold</td> <td>阈值</td> <td></td> </tr> <tr> <td>constants</td> <td>常量</td> <td></td> </tr> <tr> <td>assign</td> <td>赋值</td> <td></td> </tr> <tr> <td>dirty</td> <td>一般指代更改了未保存的数据/文件</td> <td></td> </tr> <tr> <td>truthy</td> <td>泛指真值</td> <td></td> </tr> <tr> <td>singly-linked list</td> <td>单链表</td> <td></td> </tr> <tr> <td>legacy</td> <td>遗留问题(legacy code:万恶的遗留代码)</td> <td></td> </tr> <tr> <td>instruction</td> <td>指令</td> <td></td> </tr> <tr> <td>Glossary</td> <td>术语</td> <td></td> </tr> <tr> <td>constrained</td> <td>受约束的</td> <td></td> </tr> <tr> <td>deterministic</td> <td>确定的</td> <td></td> </tr> <tr> <td>decent</td> <td>优雅的、体面的</td> <td></td> </tr> <tr> <td>bulk</td> <td>体积</td> <td></td> </tr> <tr> <td>parallel</td> <td>并行的。平行的</td> <td></td> </tr> <tr> <td>fraction</td> <td>片段</td> <td></td> </tr> <tr> <td>standstill</td> <td>停止停顿</td> <td></td> </tr> <tr> <td>subtle</td> <td>微妙的</td> <td></td> </tr> <tr> <td>augment</td> <td>增强,扩展(vue 拦截数组方法,扩展数组的原型方法时使用 protoAugment</td> <td></td> </tr> <tr> <td>instantiation</td> <td>实例化</td> <td></td> </tr> <tr> <td>Cheat sheet</td> <td>手册 清单</td> <td></td> </tr> <tr> <td>on-the-fly</td> <td>动态</td> <td></td> </tr> <tr> <td>convention</td> <td>公约,惯例</td> <td></td> </tr> <tr> <td>cluster</td> <td>集群</td> <td></td> </tr> <tr> <td>resolve</td> <td>解析</td> <td></td> </tr> <tr> <td>amend</td> <td>修正修订 eg.git commit --amend</td> <td></td> </tr> <tr> <td>abort</td> <td>中止</td> <td></td> </tr> <tr> <td>bias</td> <td>偏差/偏置</td> <td>机器学习术语</td> </tr> <tr> <td>explicit</td> <td>显式的,清楚明确的</td> <td></td> </tr> <tr> <td>Conquer</td> <td>攻破、征服的</td> <td></td> </tr> <tr> <td>carve</td> <td>雕刻</td> <td></td> </tr> <tr> <td>carve out some time</td> <td>挤出一些时间</td> <td></td> </tr> <tr> <td>tackle</td> <td>处理、解决、应付</td> <td></td> </tr> <tr> <td>intentionally</td> <td>刻意地、故意地</td> <td></td> </tr> <tr> <td>corresponding</td> <td>相对应的</td> <td></td> </tr> <tr> <td>nest</td> <td>巢,嵌套</td> <td></td> </tr> <tr> <td>nested array</td> <td>嵌套数组</td> <td></td> </tr> <tr> <td>flat(ten)</td> <td>展开,铺平,扁平化</td> <td>Array.prototype.flat方法</td> </tr> <tr> <td>scenario</td> <td>/səˈnɛrioʊ/方案;场景,情景</td> <td></td> </tr> <tr> <td>operands</td> <td>操作数,运算对象</td> <td></td> </tr> <tr> <td>diagonal</td> <td>对角线,斜线</td> <td>leetcode 52. N皇后问题,棋盘斜线集合变量名</td> </tr> <tr> <td>dimensions</td> <td>尺寸,维度</td> <td>FCC https://www.freecodecamp.org/learn/responsive-web-design/responsive-web-design-principles/make-typography-responsive</td> </tr> <tr> <td>circuit</td> <td>线路,回路</td> <td>https://www.codewars.com/kata/5536a85b6ed4ee5a78000035/train/javascript</td> </tr> <tr> <td>polyfill</td> <td>填充</td> <td>https://github.com/inexorabletash/polyfill</td> </tr> <tr> <td>shim</td> <td>垫片</td> <td>https://github.com/es-shims/es5-shim</td> </tr> <tr> <td>exceed</td> <td>超过,溢出</td> <td></td> </tr> <tr> <td>exponential</td> <td>指数</td> <td>https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number/toExponential</td> </tr> <tr> <td>allowlists</td> <td>白名单</td> <td>https://developers.google.com/web/fundamentals/security/csp</td> </tr> <tr> <td>pitfall</td> <td>陷阱</td> <td>https://css-tricks.com/debouncing-throttling-explained-examples/</td> </tr> <tr> <td>traverse</td> <td>遍历,今天leetcode每日一题又遇到一次,renew</td> <td>https://developer.mozilla.org/en-US/docs/Web/API/Element/closest</td> </tr> <tr> <td>successive</td> <td>连续的</td> <td>https://www.codewars.com/kata/562b384167350ac93b00010c/train/javascript</td> </tr> <tr> <td>immersive</td> <td>沉浸式</td> <td></td> </tr> <tr> <td>trade-off</td> <td>交换,权衡,妥协</td> <td>技术选型场景常用语</td> </tr> <tr> <td>interceptor</td> <td>拦截器</td> <td>axios</td> </tr> <tr> <td>peer</td> <td>对等的</td> <td>npm WARN经常出现:You must install peer dependencies yourself.</td> </tr> <tr> <td>actuator</td> <td>致动器,执行机</td> <td><a>github</a></td> </tr> <tr> <td>Ambiguous</td> <td>模棱两可的,多义的机</td> <td>com.microsoft.sqlserver.jdbc.SQLServerException: Ambiguous column name 'xx'</td> </tr> <tr> <td>discard</td> <td>丢弃 放弃 遗弃</td> <td>常见'确认discard changes?'</td> </tr> <tr> <td>diagonals</td> <td>对角线,斜线</td> <td>算法 N皇后问题遇到</td> </tr> <tr> <td>Semantic</td> <td>语义</td> <td>https://probot.github.io/apps/semantic-pull-requests/</td> </tr> <tr> <td>transmitter</td> <td>发送器,传输器</td> <td>https://github.com/zhantewei2/ztwx-http#readme</td> </tr> <tr> <td>intersection</td> <td>交叉、交集</td> <td>IntersectionObserver from https://developer.mozilla.org/zh-CN/docs/Web/API/IntersectionObserver</td> </tr> <tr> <td>in place</td> <td>就地</td> <td>modify arr in-place就地更改数组 https://leetcode.cn/problems/duplicate-zeros/</td> </tr> <tr> <td>macro</td> <td>宏</td> <td>计算机科学里的宏是一种抽象,它根据一系列预定义的规则替换一定的文本模式。 https://baike.baidu.com/item/MACRO/10429400</td> </tr> <tr> <td>stale</td> <td>陈旧的</td> <td>cache-control:stale-while-revalidate , https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control</td> </tr> <tr> <td>offload</td> <td>卸下、卸载</td> <td></td> </tr> <tr> <td>markup</td> <td>标识、标记</td> <td></td> </tr> <tr> <td>prioritize</td> <td>v. 按优先顺序列出;优先考虑(处理)</td> <td></td> </tr> <tr> <td>hint</td> <td>n. v. 提示、暗示,迹象</td> <td></td> </tr> <tr> <td>rasterization</td> <td>n. 格栅化</td> <td></td> </tr> <tr> <td>phase</td> <td>n. 阶段</td> <td></td> </tr> <tr> <td>dimension</td> <td>n. 尺寸、维度、规模、范围</td> <td></td> </tr> <tr> <td>geometry</td> <td>n. 几何</td> <td></td> </tr> <tr> <td>omit</td> <td>n. 省去,不做;遗漏,未能做</td> <td></td> </tr> <tr> <td>intact</td> <td>保持原样、原封不动</td> <td></td> </tr> <tr> <td>peer</td> <td>对等、同行</td> <td>peer-to-peer 点对点 端对端 对等</td> </tr> <tr> <td>disclaimer</td> <td>免责声明、 不承诺</td> <td>https://raw.githubusercontent.com/GoogleChrome/lighthouse/f943f8948276188a365214e668aee02e9753484d/docs/Network-Timings.svg</td> </tr> <tr> <td>fatigue</td> <td>疲劳</td> <td>frontend fatigue 前端疲劳,表达前端太卷学不到了</td> </tr> </tbody> </table> 个人成长https://www.scarsu.com/cs_english/#post-comment/State of JS | 2018年度javascript行业报告https://www.scarsu.com/2018_javascript_report/https://www.scarsu.com/2018_javascript_report/JavaScript生态圈总是在变化。新的库,新的框架,新的语言..这有时是有乐趣的,但有时也会让人感到压力。Mon, 31 Dec 2018 00:00:00 GMT<p><img src="/images/stateofjs/000.png" alt="" /></p> <h1>数据来源</h1> <p>来自 153 个不同的国家</p> <p>共 20,268 名 JavaScript 开发者参与调查</p> <p>中国占总数的 0.37%,共 75 个开发者</p> <p>(因此本调查报告整体上能反映全球范围的 Javascript 发展趋势,但对国内情况不具有代表性)</p> <p><strong>调查参与者 国家分布图:</strong></p> <p><img src="/images/stateofjs/1.png" alt="" /></p> <p><strong>调查参与者 薪资分布图:</strong></p> <p><img src="/images/stateofjs/2.png" alt="" /></p> <p><strong>调查参与者 开发经验分布图:</strong></p> <p><img src="/images/stateofjs/3.png" alt="" /></p> <p><strong>调查参与者 所属公司体量分布图:</strong></p> <p><img src="/images/stateofjs/4.png" alt="" /></p> <p><strong>调查参与者 性别分布图:</strong></p> <p><img src="/images/stateofjs/5.png" alt="" /></p> <h1>调查结果</h1> <h2>1.JavaScript Flavors</h2> <p>可以编译成 javasript 代码 的 各种语言/语法规范/javascript 超集</p> <p><img src="/images/stateofjs/6.png" alt="" /></p> <h2>2.前端框架 Front-end Frameworks</h2> <p><img src="/images/stateofjs/7.png" alt="" /></p> <h2>3.数据层 Data Layer</h2> <p><img src="/images/stateofjs/8.png" alt="" /></p> <h2>4.后端框架 Back-end Frameworks</h2> <p><img src="/images/stateofjs/9.png" alt="" /></p> <h2>5.测试 Testing</h2> <p><img src="/images/stateofjs/10.png" alt="" /></p> <h2>6.移动端/客户端 Mobile &amp; Desktop</h2> <p><img src="/images/stateofjs/11.png" alt="" /></p> <h2>7.js 开发者使用的其他语言 Other Languages</h2> <p><img src="/images/stateofjs/12.png" alt="" /></p> <h2>8.浏览器 API Browser APIs</h2> <p><img src="/images/stateofjs/13.png" alt="" /></p> <h2>9.构建工具 Build Tools</h2> <p><img src="/images/stateofjs/14.png" alt="" /></p> <h2>10.函数库 Utility Libraries</h2> <p><img src="/images/stateofjs/15.png" alt="" /></p> <h2>11.编辑器 Text Editors</h2> <p><img src="/images/stateofjs/16.png" alt="" /></p> <h2>12.js 开发者的使用感受+期望</h2> <p><strong>“Javascript 正在往正确的方向发展”</strong></p> <p><img src="/images/stateofjs/17.png" alt="" /></p> <p><strong>“当下构建 Javascript app 过于复杂惹”</strong></p> <p><img src="/images/stateofjs/18.png" alt="" /></p> <p><strong>“Javascript 被过度使用”</strong></p> <p><img src="/images/stateofjs/19.png" alt="" /></p> <p><strong>“我喜欢构建 JavaScript 应用程序”</strong></p> <p><img src="/images/stateofjs/20.png" alt="" /></p> <p><strong>“我希望 JavaScript 成为我的主要编程语言”</strong></p> <p><img src="/images/stateofjs/21.png" alt="" /></p> <p><strong>“JavaScript 生态系统变化太快”</strong></p> <p><img src="/images/stateofjs/22.png" alt="" /></p> <p><strong>“这项调查太长惹!”</strong></p> <p><img src="/images/stateofjs/23.png" alt="" /></p> <h1>年度之最</h1> <ul> <li><strong>最满意: Jest</strong></li> </ul> <blockquote> <p>96.5%的使用者表示会再次使用</p> </blockquote> <ul> <li><strong>最感兴趣: GraphQL</strong></li> </ul> <blockquote> <p>听说过 GraphQL 的开发者中有 87.7%表示想要学习</p> </blockquote> <ul> <li><strong>最多提及: Vuex</strong></li> </ul> <blockquote> <p>在“other libraries”提问中最多被提及的库</p> </blockquote> <ul> <li><strong>最多使用: React</strong></li> </ul> <blockquote> <p>年度被使用最多的库,参与调查者中有 14417 位使用 React</p> </blockquote> <ul> <li><strong>最黑马: Reason</strong></li> </ul> <blockquote> <p>Facebook 带来的 崭露头角的 新技术,也许会像 React 和 GraphQL 一样受欢迎?</p> </blockquote> <ul> <li><strong>最特别: VSCode</strong></li> </ul> <blockquote> <p>我们今年刚刚爱上并无法自拔的工具</p> </blockquote> <h1>参赛选手信息</h1> <h3>Javascript Flavors</h3> <ul> <li>ES6</li> </ul> <blockquote> <p>ECMA-262 标准的 Edition6(目前已经发布到 ECMA-262 2018/Edition 9),是 javascript 的规范</p> <p>https://github.com/tc39/ecma262#ecmascript</p> </blockquote> <ul> <li>Typescript</li> </ul> <blockquote> <p>由微软开发的 添加了可选的静态类型和基于类的面向对象编程 的 JS 超集</p> <p>https://github.com/Microsoft/TypeScript</p> </blockquote> <ul> <li>Flow</li> </ul> <blockquote> <p>JavaScript 添加静态类型检查器</p> <p>https://github.com/facebook/flow</p> </blockquote> <ul> <li>Reason</li> </ul> <blockquote> <p>简单,快速,类型安全,利用 JavaScript 和 OCaml 生态系统的库</p> <p>http://reasonml.github.io/</p> </blockquote> <ul> <li>Elm</li> </ul> <blockquote> <p>生成具有出色性能且没有运行时异常的 JavaScript 的语言。</p> <p>https://elm-lang.org/</p> </blockquote> <ul> <li>ClojureScript</li> </ul> <blockquote> <p>ClojureScript 是将 Clojure 成 JavaScript 的编译器。</p> <p>https://clojurescript.org/</p> </blockquote> <h3>前端框架</h3> <ul> <li>React</li> </ul> <blockquote> <p>React 是一个用于设计用户界面的开源 JavaScript 库。</p> <p>https://github.com/facebook/react</p> </blockquote> <ul> <li>Vue.js</li> </ul> <blockquote> <p>一套用于构建用户界面的渐进式框架</p> <p>https://cn.vuejs.org/</p> </blockquote> <ul> <li>Angular</li> </ul> <blockquote> <p>基于 TypeScript 的开源前端 Web 应用程序平台。</p> <p>https://angular.io/</p> </blockquote> <ul> <li>Preact</li> </ul> <blockquote> <p>3kB 大小的 使用相同的现代 API 的 React 快速替代方案,拥有组件和虚拟 DOM。</p> <p>https://github.com/developit/preact</p> </blockquote> <ul> <li>Ember</li> </ul> <blockquote> <p>用于创建大型的 Web 应用程序的 JavaScript 框架</p> <p>https://github.com/emberjs/ember.js</p> </blockquote> <ul> <li>Polymer</li> </ul> <blockquote> <p>Web 组件库</p> <p>https://github.com/Polymer/polymer</p> </blockquote> <h3>数据层</h3> <ul> <li>Redux</li> </ul> <blockquote> <p>JavaScript 应用程序的可预测状态容器</p> <p>https://github.com/reduxjs/redux</p> </blockquote> <ul> <li>GraphQL</li> </ul> <blockquote> <p>一种与后端服务相关联的查询语言和执行引擎</p> <p>https://github.com/facebook/graphql</p> </blockquote> <ul> <li>Apollo</li> </ul> <blockquote> <p>适用于每个 UI 框架和 GraphQL 服务器的功能齐全的 可用于生产的 缓存 GraphQL 客户端</p> <p>https://github.com/apollographql/apollo-client</p> </blockquote> <ul> <li>MobX</li> </ul> <blockquote> <p>简单,可扩展的状态管理</p> <p>https://github.com/mobxjs/mobx</p> </blockquote> <ul> <li>Relay/Relay Modern</li> </ul> <blockquote> <p>Relay 是一个用于构建数据驱动的 React 应用程序的 JavaScript 框架</p> <p>https://github.com/facebook/relay</p> </blockquote> <h3>后端框架</h3> <ul> <li>Express</li> </ul> <blockquote> <p>快速简单的 Node 框架</p> <p>https://github.com/expressjs/express</p> </blockquote> <ul> <li>Next.js</li> </ul> <blockquote> <p>一个多功能 React 服务端框架</p> <p>https://nextjs.org</p> </blockquote> <ul> <li>Koa</li> </ul> <blockquote> <p>使用 ES2017 异步函数的 node.js 的中间件</p> <p>https://github.com/koajs/koa</p> </blockquote> <ul> <li>Meteor</li> </ul> <blockquote> <p>JavaScript 应用程序平台</p> <p>https://github.com/meteor/meteor</p> </blockquote> <ul> <li>Sails</li> </ul> <blockquote> <p>Node.js 的实时 MVC 框架</p> <p>https://github.com/balderdashy/sails</p> </blockquote> <ul> <li>FeathersJS</li> </ul> <blockquote> <p>适用于现代应用程序的 REST 和实时 API 层 https://github.com/feathersjs/feathers</p> </blockquote> <h3>Javascript 测试工具</h3> <ul> <li>Jest</li> </ul> <blockquote> <p>令人愉快的 JavaScript 测试工具</p> <p>https://jestjs.io/</p> </blockquote> <ul> <li>Mocha</li> </ul> <blockquote> <p>node.js 和浏览器的简单,灵活,有趣的 javascript 测试框架</p> <p>https://github.com/mochajs/mocha</p> </blockquote> <ul> <li>Jasmine</li> </ul> <blockquote> <p>适用于浏览器和 node.js 的简单 JavaScript 测试框架</p> <p>https://github.com/jasmine/jasmine</p> </blockquote> <ul> <li>Enzyme</li> </ul> <blockquote> <p>用于 React 的 JavaScript 测试实用程序</p> <p>https://github.com/airbnb/enzyme</p> </blockquote> <ul> <li>Karma</li> </ul> <blockquote> <p>健壮的 Javascript 测试工具</p> <p>https://github.com/karma-runner/karma</p> </blockquote> <ul> <li>Storybook</li> </ul> <blockquote> <p>用于交互式 UI 组件:React,React Native,Vue,Angular,Ember 的开发和测试工具</p> <p>https://github.com/storybooks/storybook</p> </blockquote> <ul> <li>Ava</li> </ul> <blockquote> <p>未来的 JavaScript 测试工具</p> <p>https://github.com/avajs/ava</p> </blockquote> <h3>移动端/客户端</h3> <ul> <li>Electron</li> </ul> <blockquote> <p>使用 JavaScript,HTML 和 CSS 构建跨平台桌面应用程序</p> <p>https://github.com/electron/electron</p> </blockquote> <ul> <li>React Native</li> </ul> <blockquote> <p>使用 React 构建应用程序的框架</p> <p>https://github.com/facebook/react-native</p> </blockquote> <ul> <li>Native Apps</li> </ul> <blockquote> <p>原生客户端 App 语言:Java, Kotlin, Objective-C, or Swift 等</p> </blockquote> <ul> <li>Cordova</li> </ul> <blockquote> <p>移动应用程序开发框架</p> <p>https://cordova.apache.org/</p> </blockquote> <ul> <li>Ionic</li> </ul> <blockquote> <p>使用开放式 Web 技术构建的原生和渐进式 Web 应用</p> <p>https://github.com/ionic-team/ionic</p> </blockquote> <ul> <li>NativeScript</li> </ul> <blockquote> <p>用于使用 JavaScript 构建移动端应用程序的开源框架。使用 Web 技能,如 Angular 和 Vue.js,FlexBox 和 CSS,并在 iOS 和 Android 上获得原生 UI 和性能</p> <p>https://github.com/NativeScript/NativeScript</p> </blockquote> 前端https://www.scarsu.com/2018_javascript_report/#post-comment/Node版本管理工具 nvm for windowshttps://www.scarsu.com/nvm_for_windows/https://www.scarsu.com/nvm_for_windows/node版本更新那么快,怎么才能在机子上多装几版node?还能一句命令切换?Sat, 29 Sep 2018 00:00:00 GMT<h1>nvm</h1> <p>只支持 linux 和 cent os</p> <h1>nvm for windows</h1> <p><a>https://github.com/coreybutler/nvm-windows/releases</a></p> <h1>安装</h1> <pre><code>0. 安装前卸载干净已经有的node 1. 设置nvm安装路径(不能有空格,否则nvm use 报错) 2. 设置node路径(当前使用的node的存放路径,会被添加到环境变量) </code></pre> <h1>常用命令</h1> <pre><code>nvm list -当前安装的node版本 nvm list available -可获取的版本 nvm install xx.xx.xx -安装某版本node nvm use xx.xx.xx -使用某版本node nvm uninstall xx.xx.xx -卸载某版本node </code></pre> <h1>其他命令</h1> <pre><code>nvm arch -查看当前系统位数 nvm on/off -打开/关闭nvm(好像并没有什么区别 nvm proxy [url] -设置代理下载地址 nvm root [path] -nvm安装路径 nvm node_mirror [url] -node下载库路径 nvm npm_mirror [url] -npm下载库路径 </code></pre> <hr /> <pre><code>“重点是node为什么更新那么快?” </code></pre> 前端https://www.scarsu.com/nvm_for_windows/#post-comment/360FED课程 - CSShttps://www.scarsu.com/360fe_02_css/https://www.scarsu.com/360fe_02_css/大佬为什么是大佬?Fri, 07 Sep 2018 00:00:00 GMT<h1>css</h1> <p>cascading stylesheet 级联样式表</p> <h1>Level 版本</h1> <ul> <li>CSS Level 1(废弃</li> <li>CSS Level 2 (CSS 2.2 完整规范)</li> <li>CSS Level 3(在 2.2 的基础上增加新模块特性 <ul> <li>Color Module Level 3</li> <li>Selectors Level 3</li> <li>Media Queries</li> <li>Fonts Level 3</li> </ul> </li> </ul> <h1>选择器</h1> <h2>简单</h2> <ul> <li>通配 *</li> <li>标签 E</li> <li>类 .class</li> <li>id #id</li> </ul> <h2>属性选择器 [ ]</h2> <pre><code>/* 具有某个属性 */ [disabled] /* 属性为指定的值 */ [type="checkbox"] /* 属性值包含某个字符串 */ [href*="example"] /* 属性值以某个字符串开头 */ [href^="http:"] /* 属性值以某个字符串结束 */ [href$="jpg"] /* 属性值以空格分割后包含某个字符串 */ [lang~="zh-cn"]/* class选择器的实现机制 */ </code></pre> <h2>伪类</h2> <pre><code>/* 动态性伪类,根据状态选择 */ a:link { ... } /* 未访问过的链接 */ a:visited { ... } /* 已访问过的链接 */ a:hover { ... } /* 鼠标移到链接上的样式 */ a:active { ... } /* 鼠标在连接上按下时的样式 */ a:focus { ... } /* 获得焦点时的样式 */ input:disabled { ... } /* 禁用时的样式 */ input:checked { ... } /* 选中时的样式 */ /*利用:checked来做某些toggle组件状态转换*/ /* 结构性伪类 */ :first-child :last-child :nth-child(2n+1) :first-of-type :last-of-type div:nth-of-type(2n+1) /*对nth-child()增加类型限制*/ :empty </code></pre> <h2>组合性选择器</h2> <ul> <li>后代 E F</li> <li>父子 E&gt;F</li> <li>兄弟 E~F</li> <li>相邻兄弟 E+F</li> </ul> <h1>伪元素</h1> <ul> <li>::before</li> <li>::after</li> <li>::first-letter</li> <li>::first-line</li> </ul> <h1>优先级/特异度 Specificity</h1> <ul> <li>!important &gt; 内联 &gt; id &gt; (伪)类 &gt; (伪)元素</li> <li>覆盖:同样优先级:后面写的覆盖前面写的</li> <li>复合选择器:从优先级高的选择器 的 数量 开始比较</li> </ul> <h1>样式来源</h1> <ul> <li>页面开发者</li> <li>用户设置(浏览器可以指定一个本地 CSS 文件,打开所有页面时自动加载</li> <li>浏览器预设 <ul> <li><a>Mozilla Firefox 预设样式</a></li> <li><a>Google Chrome 预设样式</a></li> </ul> </li> <li>优先级: 开发者 &gt; 用户设置 &gt; 浏览器预设</li> <li>加了!important 的优先级:用户 important &gt; 开发者 important &gt; 开发者 &gt; 用户设置 &gt; 浏览器预设</li> </ul> <h1>默认值策略 Defaulting</h1> <h2>继承</h2> <p>某些属性若不指定值,会自动继承父元素的 !!!【计算值】</p> <h2>显示继承</h2> <pre><code>html { box-sizing: border-box; } * { box-sizing: inherit; /* 优点是有某一块都要设置为content-box时,只需要设置其最外层元素,不需要全设置 */ } #xxx { box-sizing: content-box; } </code></pre> <h2>初始值 initial</h2> <ul> <li>CSS 中,每个属性都有一个初始值</li> <li>background-color 的初始值为 transparent</li> <li>margin-left 的初始值为 0,font-size 是 16px,line-height 是 1.2,但根据 font-family 而不同</li> <li>可以显式重置为初始值,比如 background-color: initial</li> <li>可以上 mdn 查初始值</li> </ul> <h1>CSS 求值过程</h1> <h2>一个令人疑惑的很皮的 CSS 求值例子</h2> <pre><code>&lt;article&gt; &lt;h1&gt;卡尔斯巴德洞窟&lt;/h1&gt; &lt;p&gt; 卡尔斯巴德洞窟(Carlsbad Caverns)是美国的一座国家公园, 位于新墨西哥州东南部。游客可以通过天然入口徒步进入,也可以 通过电梯直接到达230米的洞穴深处。 &lt;/p&gt; &lt;/article&gt; &lt;style&gt; body { margin: 0; } article { line-height: 150%; } h1 { font-size: 40px; /*最终实际的line-height值为24px*/ } p { font-size: 14px; /*最终实际的line-height值为24px*/ } &lt;/style&gt; &lt;style&gt; body { margin: 0; } article { line-height: 1.5; } h1 { font-size: 40px; /*最终实际的line-height值为60px*/ } p { font-size: 14px; /*最终实际的line-height值为21px*/ } &lt;/style&gt; &lt;!-- 原因: 设为150%时,子元素继承前,父元素的line-height=150%会先被计算(resolving),得到一个绝对值,被计算为16px(默认的font-size值)*1.5=24px,子元素继承到的值是24px 设为1.5时,子元素继承前,父元素在执行resolving时,1.5是绝对值,不会被转换,所以子元素继承到值1.5,后面再根据自己的font-size*1.5计算line-height 总结:子元素继承到的是父元素的 计算值(一个绝对值) --&gt; </code></pre> <h2>CSS 求值详细过程</h2> <ul> <li>filtering:有效选择器 有效属性值 符合 media ,筛选出所有<strong>声明值 Declared Values</strong></li> <li>cascading:选出优先级最高的一条声明,得到<strong>层叠值 Cascaded Value</strong></li> <li>defaulting:当层叠值为空时,用 继承 | 初始值,得到<strong>指定值 Specified Value</strong></li> <li>resolving:将相对值、关键字转化为绝对值,如 em 转换为 px,%被转换为 px,相对路径转换为绝对路径,得到<strong>计算值 Computed Value</strong></li> <li>formatting:将计算值进一步转换,比如百分比、关键字转换为绝对值,得到<strong>使用值 Used Value</strong></li> <li>constraining:将小数像素转为整数,得到<strong>实际值</strong></li> </ul> <h1>CSS 排版原理</h1> <h2>盒模型</h2> <h3>content-box:</h3> <ul> <li>margin</li> <li>border</li> <li>padding</li> <li>content(width height)</li> </ul> <h3>border-box</h3> <ul> <li>margin</li> <li>border (width = border + padding + content_width)</li> <li>padding</li> <li>content</li> </ul> <h2>height 100%(一般不用</h2> <ul> <li>高度百分数,是相对于父元素的高度</li> <li>若父元素无高度,则百分比高度不生效</li> <li>用 vw vh 设置相对于屏幕的百分比高度,100vh 即 100%屏幕高度</li> </ul> <h2>padding 100%</h2> <ul> <li>padding 百分比值,不论是 padding top、left,都是相对于<strong>父元素宽度</strong></li> <li>应用:做固定宽高比的盒子.</li> </ul> <h2>margin 折叠</h2> <p>上下相邻元素的间距会取其 margin 中较大值。</p> <h2>border:四条边不同颜色</h2> <ul> <li>实际相邻的 border 交界处,是斜切的。</li> <li>当元素的 width height 为 0 时,会得到四个三角形</li> </ul> <h1>background: repeating-conic-gradient(black 0 60deg, yellow 0 120deg);</h1> <h1>视觉格式化模型</h1> <h2>Viewport 视口</h2> <p>浏览器的可视区域,所有元素都在 viewport 内</p> <h2>块级元素(Block-level Elements)</h2> <ul> <li>会被格式化成块状的元素</li> <li>例如 p、div、section 等</li> <li>将 display 设置为 block、list-item、table 会使元素变为块级</li> </ul> <h2>行内元素(Inline-level Elements)</h2> <ul> <li>不会为其内容生成块级框</li> <li>让其内容分布在多行中</li> <li>display 设置为 inline、inline-block、inline-table 会使元素变为行级</li> </ul> <hr /> <pre><code>“因为大佬比你知道的多” </code></pre> 前端https://www.scarsu.com/360fe_02_css/#post-comment/360FED课程 - HTMLhttps://www.scarsu.com/360fe_01_html/https://www.scarsu.com/360fe_01_html/这么穷为什么还花钱买HTML学?Sun, 02 Sep 2018 00:00:00 GMT<h1>1. 前端做什么</h1> <p>用 web 标准技术 html css js svg http 等</p> <p>做界面与交互</p> <p>功能+美观+无障碍+安全+兼容+性能+体验</p> <h1>2. 知识图谱/技术栈</h1> <h2>2.1. 语言</h2> <ul> <li>js</li> <li>html</li> <li>css</li> <li>php</li> </ul> <h2>2.2. 行业标准</h2> <ul> <li>DOM</li> <li>ES2018</li> <li>HTTP</li> <li>JSON</li> <li>XML</li> </ul> <h2>2.3. 框架</h2> <ul> <li>React.js</li> <li>Angular.js</li> <li>jQuery</li> <li>Vue.js</li> <li>lodash</li> </ul> <h2>2.4. 兼容性</h2> <ul> <li>IE 等浏览器</li> <li>CSS3 新特性</li> <li>HTML5 新特性</li> <li>ES2018</li> <li>移动端</li> </ul> <h2>2.5. 编程思想</h2> <ul> <li>函数式编程</li> <li>面向对象</li> <li>设计模式</li> </ul> <h2>2.6. 调试</h2> <ul> <li>浏览器</li> <li>Fiddler http</li> </ul> <h2>2.7. 工程化</h2> <ul> <li>npm</li> <li>webpack</li> <li>postcss</li> </ul> <h2>2.8. 安全性</h2> <ul> <li>XSS</li> <li>CSRF</li> <li>加密解密</li> <li>编解码</li> </ul> <h2>2.9. 性能</h2> <ul> <li>优化规则</li> <li>开发者工具</li> <li>浏览器原理</li> </ul> <h2>2.10. 团队协作</h2> <ul> <li>git/svn</li> <li>编码规范/eslint</li> <li>文档管理</li> </ul> <h2>2.11. 交互设计</h2> <h1>3. 前端边界</h1> <p>node、electron、react native、webRTC、WebGL、WEBAssembly</p> <h1>4. HTML</h1> <h2>4.1. doctype</h2> <ul> <li>指定文档使用的标准和版本;</li> <li>浏览器根据 doctype 决定使用哪种渲染模式;</li> <li>没写会以怪异模式渲染(盒模型不同等待)</li> <li>渲染模式</li> </ul> <h2>4.2. 语义化</h2> <ul> <li>元素、属性、属性值都有特定含义,应该遵循语义来写 HTML</li> <li>可读性、可维护性、搜索引擎优化、无障碍性</li> </ul> <h2>4.3. 标签</h2> <h3>4.3.1. flow 流式元素:</h3> <ul> <li>heading 标题</li> <li>sectioning 章节</li> <li>phrasing 段落内容 p h</li> <li>Embedded 嵌入式内容 audio canvas</li> <li>interactive 可交互性内容 button a</li> <li>metadata 元数据元素 base link meta noscript script style title</li> </ul> <h3>4.3.2. 看规范</h3> <h2>4.4. HTML 扩展</h2> <h3>4.4.1. meta 标签(增加元数据</h3> <pre><code>&lt;!-- 编码 --&gt; &lt;meta charset="utf-8"&gt; &lt;!-- 指定http header --&gt; &lt;meta http-equiv="Content-Security-Policy" content="script-src 'self'"&gt; &lt;!-- seo优化 --&gt; &lt;meta name="keywords" content="关键词"&gt; &lt;meta name="description" content="页面介绍"&gt; &lt;!-- 移动设备的viewport 初始缩放比例,视口宽度 --&gt; &lt;meta name="viewport" content="initial-scale=1"&gt; &lt;!-- 关闭IOS电话号码识别 --&gt; &lt;meta name="format-detection" content="telphone=no"&gt; &lt;!-- 360等双核浏览器 指定渲染内核 --&gt; &lt;meta name="renderer" content="webkit"&gt; &lt;!-- 指定IE渲染模式 --&gt; &lt;meta name="X-UA-Compatibla" content="IE=Edge"&gt; </code></pre> <h3>4.4.2. data-*属性(规范内-自定义的属性)</h3> <pre><code> datasetAPI &lt;el data-id=""/&gt; el.dataset.id </code></pre> <h3>4.4.3. link</h3> <ul> <li>rel 属性(relation 关系,外部资源与当前页面的关系)</li> </ul> <pre><code>&lt;!-- 引入css --&gt; &lt;link rel="stylesheet" href="" /&gt; &lt;!-- 浏览器性能优化:dns预解析rel=dns-prefetch、资源预加载rel=prefetch、预渲染 rel=prerender --&gt; &lt;link rel="dns-prefetch" href="" /&gt; &lt;link rel="prefetch" href="" /&gt; &lt;link rel="prerender" href="" /&gt; &lt;!-- favicon:rel=icon --&gt; &lt;link rel="icon" type="image/png" href="" /&gt; &lt;!-- RSS:rel=alternate --&gt; &lt;link rel="alternate" type="application/rss+xml" href="" /&gt; </code></pre> <h3>4.4.4. JSON-LD</h3> <p>LD:linkdata 链接的数据 (直接在页面嵌 json 数据)</p> <pre><code>&lt;script type="application/ld+json"&gt; { "@context": "http://schema.org", "@type": "Person", "name": "John Doe", "jobTitle": "Graduate research assistant", "affiliation": "University of Dreams", "additionalName": "Johnny", "url": "http://www.example.com", "address": { "@type": "PostalAddress", "streetAddress": "1234 Peach Drive", "addressLocality": "Wonderland", "addressRegion": "Georgia" } } // 应用例如分享页面时的数据 // 搜索引擎能识别等等 // 分享链接带有一些标题图片等信息 &lt;/script&gt; </code></pre> <h2>4.5. Web 无障碍/Accessibility</h2> <ul> <li>一些 Web 开发者规范: <ul> <li>WCAG2.0</li> <li>ARIA</li> </ul> </li> <li>提升无障碍性 <ul> <li>img alt</li> <li>noscript</li> <li>input 和 label 对应</li> <li>图片验证码与语音验证码</li> <li>文字背景对比度</li> <li>键盘可操作(tab modal focus)</li> </ul> </li> </ul> <h2>4.6. 工具</h2> <ul> <li><a>W3C Validator(检查 html 合法性)</a></li> <li>emmet(插件)</li> <li>markdown(适合写文档)</li> </ul> <h2>4.7. 参考链接</h2> <ul> <li><a>HTML: The Living Standard</a></li> <li><a>Activating Browser Modes with Doctype</a></li> <li><a>Accessibility</a></li> <li>Web Content Accessibility Guidelines 2.0</li> <li><a>HTML5 Doctor: Semantics</a></li> </ul> <h2>全局属性</h2> <h3>class id style</h3> <h3>title</h3> <p>(兼容性最好的 tooltip😂)</p> <h3>tabindex</h3> <p>tab 键控制次序</p> <h3>lang</h3> <p>语言代码(利于语义化机器理解)(语言代码参考手册http://www.runoob.com/tags/html-language-codes.html)</p> <h3>dir</h3> <p>文本方向(rtl ltr auto)</p> <h3>accesskey</h3> <p>元素的键盘访问快捷键(例值为'h'则不同浏览器不同 OS 有不同的操作方式,例 chrome 是 alt + 'h')</p> <h2>(HTML5 全局属性)</h2> <h3>data-*属性</h3> <p>属性名不要包含大写字母,在 data- 后必须至少有一个字符。 该属性可以是任何字符串</p> <pre><code>el.getAttribute("data-xx") </code></pre> <h3>hidden</h3> <p>不需要属性值,隐藏元素,原理是 display:none</p> <h3>contenteditable</h3> <p>元素是否可编辑</p> <h3>contextmenu</h3> <p>(说是目前只有 firefox 支持,亲测没效果</p> <pre><code>&lt;p contextmenu="mymenu"&gt;&lt;/p&gt; &lt;menu id="mymenu"&gt; &lt;command label="xxx" onclick="fn()"/&gt; &lt;command label="xxx" onclick="fn()"/&gt; &lt;/menu&gt; </code></pre> <h3>draggable:(与 HTML5drag 结合用)</h3> <pre><code> &lt;div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"&gt;&lt;/div&gt; &lt;p id="drag1" draggable="true" ondragstart="drag(event)"&gt;这是一段可移动的段落。可把该段落拖入上下的矩形。&lt;/p&gt; &lt;div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)"&gt;&lt;/div&gt; function allowDrop(ev){ ev.preventDefault(); } function drag(ev){ ev.dataTransfer.setData("Text",ev.target.id); } function drop(ev){ var data=ev.dataTransfer.getData("Text"); ev.target.appendChild(document.getElementById(data)); ev.preventDefault(); } </code></pre> <h3>dropzone 属性:</h3> <p>规定当被拖动的数据在拖放到元素上时,是否被复制### 动或链接,无浏览器支持</p> <h3>sppelcheck:</h3> <p>对元素的文本进行拼写检查</p> <h3>translate 属性:</h3> <p>规定元素内容是否要翻译,=yes|no</p> <h1>遗留</h1> <p>表单元素 属性 datalist select 下拉多选 input 的 multiple 属性 button 的 type 属性默认值 video 不能嵌套 img p 不能嵌套 div figure dfn cite 标签</p> <hr /> <pre><code>“因为你永远不知道你不知道的有多少” </code></pre> 前端https://www.scarsu.com/360fe_01_html/#post-comment/古老神奇的<table>https://www.scarsu.com/ancient_magical_table/https://www.scarsu.com/ancient_magical_table/凭什么table能兼容IE6?Wed, 29 Aug 2018 00:00:00 GMT<h1>结构</h1> <pre><code>&lt;table&gt; &lt;caption&gt;表格上方的居中标题&lt;/caption&gt; &lt;colgroup&gt; &lt;col span="2" style=""&gt; &lt;col style=""&gt; &lt;/colgroup&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;ISBN&lt;/th&gt; &lt;th&gt;Title&lt;/th&gt; &lt;th&gt;Price&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tody&gt; &lt;tr&gt; &lt;td&gt;3476896&lt;/td&gt; &lt;td&gt;My first HTML&lt;/td&gt; &lt;td&gt;$53&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;tfoot&gt; &lt;tr&gt; &lt;td&gt;3476896&lt;/td&gt; &lt;td&gt;My first HTML&lt;/td&gt; &lt;td&gt;$53&lt;/td&gt; &lt;/tr&gt; &lt;/tfoot&gt; &lt;/table&gt; </code></pre> <h1>标签</h1> <pre><code>&lt;caption&gt;、&lt;col&gt;、&lt;colgroup&gt;、&lt;thead&gt;、&lt;tfoot&gt; 以及 &lt;tbody&gt; </code></pre> <h1><code>&lt;caption&gt;标题</code></h1> <p>对齐方式:</p> <ul> <li>用 CSS 属性 "text-align" 和 "caption-side"</li> <li>caption-side 只有 top 和 bootom 两个,即位于表格上方或下方</li> <li>用 text-align 来控制左右位置</li> </ul> <p>无其他属性(HTML4.01 的 align 属性被 HTML5 删除)</p> <h1><code>&lt;colgroup&gt;</code> 和 <code>&lt;col&gt;</code> :对列进行组合</h1> <p>对列进行组合</p> <p>span 属性:定义横跨的列数,无 span 属性默认为 1(类似于 td 的 colspan 属性)</p> <p>无其他属性(表示样式的 HTML4.01 属性均被 HTML5 删除)</p> <h1><code>&lt;thead&gt; &lt;tbody&gt; &lt;tfoot&gt;</code></h1> <p>无属性(样式属性被 HTML5 删除)</p> <p>默认不会影响表格的样式布局</p> <p>优点:</p> <ul> <li>使浏览器有能力支持独立于表格表头和表格页脚的表格主体滚动。</li> <li>当包含多个页面的长的表格被打印时,表格的表头和页脚可被打印在包含表格数据的每张页面上。</li> <li>可以方便的定义 三部分 的样式</li> </ul> <h1><code>&lt;table&gt;</code></h1> <p>属性:border=1 或"" 规定是否有边框</p> <p>无其他属性(表示样式的 HTML4.01 属性均被 HTML5 删除)</p> <h1>表格行:<code>&lt;tr&gt;</code></h1> <p>无属性(表示样式的 HTML4.01 属性均被 HTML5 删除)</p> <h1>单元格:<code>&lt;td&gt;</code> 和 <code>&lt;th&gt;</code></h1> <p>差异</p> <ul> <li>th:文本粗体,居中</li> <li>td:文本普通,左对齐</li> </ul> <p>属性</p> <ul> <li>colspan:横跨的列数</li> <li>rowspan:横跨的行数</li> <li>headers:header_id 单元格关联的一个或多个表头单元格</li> <li>无其他属性(表示样式的 HTML4.01 属性均被 HTML5 删除)</li> </ul> <p>自动居中</p> <ul> <li>如果给 td 定义了尺寸,且子元素的尺寸小于 td 尺寸,子元素会自动垂直居中</li> <li>居中后子元素与 td 的边距,不属于 td 的 padding 值,也不属于子元素的 margin 值</li> <li>IE6 居中随便写,写不出来算我输</li> </ul> <h1>CSS 属性:border-collapse</h1> <p>默认情况:单元格之间有间隔隔开,border-collapse:separate</p> <p>一般不需要隔开:</p> <pre><code>table { border-collapse: collapse; } </code></pre> <hr /> <pre><code>"你大爷还是你大爷" </code></pre> 前端https://www.scarsu.com/ancient_magical_table/#post-comment/用chrome调试node.js服务端代码https://www.scarsu.com/debug_nodejs_with_chrome/https://www.scarsu.com/debug_nodejs_with_chrome/不然你想用什么调试?Mon, 30 Jul 2018 00:00:00 GMT<h3>开启调试命令</h3> <pre><code>node --inspect app.js //在第一行就停下来等待调试,也可以使用 node --inspect-brk app.js </code></pre> <h3>debugger 地址</h3> <pre><code>//运行开启调试命令后,能看到类似如下的输出: Debugger listening on ws://127.0.0.1:9229/4dc825ec-a204-46f8-8edc-4afadc8da61a For help see https://nodejs.org/en/docs/inspector </code></pre> <h3>在 chrome 中打开 debugger</h3> <pre><code>在Chrome中打开chrome://inspect/#devices 点击inspect进入调试界面 </code></pre> <h3>debugger 端口</h3> <p>inspect 调试默认监听 9229 端口,可以通过下面的参数指定端口</p> <pre><code>--inspect=9222 </code></pre> <hr /> <pre><code>用VSC、用webstorm啊 对不起我懒(~﹃~)~zZ </code></pre> 前端https://www.scarsu.com/debug_nodejs_with_chrome/#post-comment/成熟的一些标志https://www.scarsu.com/be_mature/https://www.scarsu.com/be_mature/克制欲望、保持一致性、有原则有底线有追求Mon, 09 Jul 2018 00:00:00 GMT<blockquote> <p>能克制欲望,不追求即时反馈,延迟享受。</p> <p>保持一致性,无论在人群中还是独处时,知行合一,不卑不亢,不矫揉造作,不哗众取宠。</p> <p>心中始终有底线、有原则、有追求。</p> <p>时刻反省自己:what在做什么、why为什么这样做、how如何做的更好</p> </blockquote> <p>—— 尼古拉斯·鱼</p> 个人成长https://www.scarsu.com/be_mature/#post-comment/No means Nohttps://www.scarsu.com/no_means_no/https://www.scarsu.com/no_means_no/该表达态度的时候,要明确、干净、利落的表达。Mon, 09 Jul 2018 00:00:00 GMT<p>该表达态度的时候,要明确、干净、利落的表达。</p> 个人成长https://www.scarsu.com/no_means_no/#post-comment/不要扮演受害者https://www.scarsu.com/play_victim/https://www.scarsu.com/play_victim/受害者的防卫机制常常是自我否定,并将自己置于一个道德正确的位置。Mon, 09 Jul 2018 00:00:00 GMT<p>责怪、批评与指责是人类防御机制的关键要素。</p> <p>责怪他人、批评他人行为、指责他人不愿改变,其实是一种轻而易举的手段,</p> <p>能够简单地利用道德批判,将自己提升到一个高于他人的位置,也使我们摆脱了自身的不安。</p> <p>然而,责怪、批评与指责的态度最终只会加强自我的受害者意识。</p> <p>受害者常感到无力、无助、无价值且无法自我满足。</p> <p>他们的防卫机制常常是自我否定,并将自己置于一个道德正确的位置。</p> <p><strong>当我们坦然面对内在的受害情绪时,我们将有机会更具有意识地正视这份感觉,并了解这仅是一种感受,而非事实</strong></p> <p>责怪、批评与指责也终将不再发生。</p> 个人成长https://www.scarsu.com/play_victim/#post-comment/学习最原始的驱动力https://www.scarsu.com/why_learning/https://www.scarsu.com/why_learning/来自于胡适的心得Mon, 09 Jul 2018 00:00:00 GMT<p>保持质疑</p> <p>保持好奇心和兴趣</p> <p>保持对努力的自信</p> 个人成长https://www.scarsu.com/why_learning/#post-comment/认知 | 看电影/阅读的意义是什么?https://www.scarsu.com/why_reading/https://www.scarsu.com/why_reading/谁看到的维度越多,世界在谁的眼中便越真实。Mon, 09 Jul 2018 00:00:00 GMT<blockquote> <p>谁看到的维度越多,世界在谁的眼中便越真实。</p> <p>练习自己感动、愤怒、喜悦、震惊、欢笑、平静的能力 不被苟且的生活捆绑致死。</p> <p>认识这个世界,丰富认知维度。</p> <p>即使生活一平如水、或筋疲力尽、或颠沛流离,仍要感受这个形形色色的世界,满怀希望,拥有细腻的情感。</p> </blockquote> 个人成长https://www.scarsu.com/why_reading/#post-comment/关于坚持https://www.scarsu.com/will_power/https://www.scarsu.com/will_power/短篇Mon, 09 Jul 2018 00:00:00 GMT<blockquote> <p>坚持这两个字,远比你想象中的要难的多,但也比你想象中的有效的多。</p> <p>'You do make a difference!'</p> </blockquote> <p><a>@https://www.bilibili.com/video/BV1XJ411d7Xx</a></p> <blockquote> <p>两年,是很容易虚度过去的时长,也是足够改变自己的时长。</p> </blockquote> <p><a>@https://www.bilibili.com/video/BV1NE41197sr</a></p> 个人成长https://www.scarsu.com/will_power/#post-comment/FullPage.jshttps://www.scarsu.com/fullpagejs/https://www.scarsu.com/fullpagejs/fullPage.js 是一个基于 jQuery 的插件。Thu, 19 Apr 2018 00:00:00 GMT<h2>主要功能有:</h2> <ul> <li>支持鼠标滚动</li> <li>支持前进后退和键盘控制</li> <li>多个回调函数</li> <li>支持手机、平板触摸事件</li> <li>支持 CSS3 动画</li> <li>支持窗口缩放</li> <li>窗口缩放时自动调整</li> <li>可设置滚动宽度、背景颜色、滚动速度、 循环选项、回调、文本对齐方式等等</li> </ul> <h2>兼容性</h2> <pre><code>jQuery 兼容: 兼容 jQuery 1.7+。 浏览器兼容: IE8+ ✔ Chrome ✔ Firefox ✔ Opera ✔ Safari ✔ </code></pre> <h2>引入文件</h2> <pre><code>&lt;link rel="stylesheet" href="css/jquery.fullPage.css"&gt; &lt;script src="js/jquery.fullPage.js"&gt;&lt;/script&gt; &lt;script src="js/jquery.min.js"&gt;&lt;/script&gt; &lt;!-- jquery.easings.min.js 用于 easing 参数,也可以使用完整的 jQuery UI 代替,如果不需要设置 easing 参数,可去掉改文件 --&gt; &lt;script src="js/jquery.easings.min.js"&gt;&lt;/script&gt; &lt;!-- 如果 scrollOverflow 设置为 true,则需要引入 jquery.slimscroll.min.js,一般情况下不需要 --&gt; &lt;script src="js/jquery.slimscroll.min.js"&gt;&lt;/script&gt; </code></pre> <h2>HTML</h2> <pre><code> &lt;div id="dowebok"&gt; &lt;div class="section"&gt; &lt;h3&gt;第一屏&lt;/h3&gt; &lt;/div&gt; &lt;div class="section"&gt; &lt;h3&gt;第二屏&lt;/h3&gt; &lt;/div&gt; &lt;div class="section"&gt; &lt;h3&gt;第三屏&lt;/h3&gt; &lt;/div&gt; &lt;div class="section"&gt; &lt;h3&gt;第四屏&lt;/h3&gt; &lt;/div&gt; &lt;/div&gt; 每个 section 代表一屏,默认显示“第一屏”,如果要指定加载页面时显示的“屏幕”,可以在对应的 section 加上 class=”active”,如: &lt;div class="section active"&gt;第三屏&lt;/div&gt; 同时,可以在 section 内加入 slide,如: &lt;div id="dowebok"&gt; &lt;div class="section"&gt;第一屏&lt;/div&gt; &lt;div class="section"&gt;第二屏&lt;/div&gt; &lt;div class="section"&gt; &lt;div class="slide"&gt;第三屏的第一屏&lt;/div&gt; &lt;div class="slide"&gt;第三屏的第二屏&lt;/div&gt; &lt;div class="slide"&gt;第三屏的第三屏&lt;/div&gt; &lt;div class="slide"&gt;第三屏的第四屏&lt;/div&gt; &lt;/div&gt; &lt;div class="section"&gt;第四屏&lt;/div&gt; &lt;/div&gt; ### JavaScript `` $(function(){ $('#dowebok').fullpage(); }); </code></pre> <h2>详细配置见官方文档</h2> <p><a>Fullpage.js-Github</a></p> <hr /> <pre><code>皮不动了... </code></pre> 前端https://www.scarsu.com/fullpagejs/#post-comment/MongoDB配置https://www.scarsu.com/mongodb_configuration/https://www.scarsu.com/mongodb_configuration/MongoDB被我选来做毕设的数据库,在此记录配置过程。Tue, 06 Mar 2018 00:00:00 GMT<h2>官网下载安装</h2> <pre><code>(我版本3.0.15 [官网下载地址](https://www.mongodb.com/download-center?jmp=nav) </code></pre> <h2>安装路径</h2> <pre><code>将C:\Program Files\MongoDB\Server\3.0\bin(windows下的默认路径)添加到环境变量 即可在任何位置使用 mongo 使用数据库 mongod 开机 mongoimport 导入数据 </code></pre> <h2>新建</h2> <pre><code>C:\data\db路径作为数据库 </code></pre> <h2>开机 cmd 命令:</h2> <pre><code>mongod --dbpath c:\data\db (保持该cmd窗口才能正常运行mongodb) (其他数据操作另外开cmd) --dbpath是选择数据库文档所在文件夹 即,mongodb中数据库有物理文件 </code></pre> <h2>use</h2> <pre><code>use 数据库名字 使用一个数据库 如果想新建数据库,也是use。use一个不存在的,就是新建。 </code></pre> <h2>查看当前所在数据库</h2> <pre><code>db </code></pre> <h2>插入数据</h2> <pre><code>数据库中不能直接插入数据, 只能往集合(collections)中插入数据 db.userid.insert({"id":"zengsuyu","password":"123456789"}); 此处的userid就是集合 </code></pre> <h2>删除当前所在的数据库</h2> <pre><code>db.dropDatabase(); </code></pre> <h2>导入外部 json 数据</h2> <pre><code>用sublime在外部写好json数据库的形式,然后导入数据库: -db 数据库名(选择数据库 --collection 集合名( 选择集合 --drop (把集合清空 --file json文件名(选择要导入的json文件 </code></pre> <h2>查找数据:</h2> <pre><code>db.集合名.find() (列出所有数据 db.集合名.find({"key":"value"}) (精确匹配key为value值的数据 db.集合名.find().sort("") (升降排序 </code></pre> <h2>mongoose</h2> <pre><code>不用直接操作数据库,操作对象,对象自动持久 </code></pre> <ul> <li>连接 Mongo 数据库</li> </ul> <pre><code>var mongoose = require('mongoose'); var db = mongoose.connect('mongodb://localhost/geekChat');//;连接数据库 </code></pre> <ul> <li>监听 open 事件</li> </ul> <pre><code>db.once('open', function (callback) { console.log("数据库成功连接"); }); </code></pre> <ul> <li>创建类</li> </ul> <pre><code>//创建了一个模型。猫的模型。所有的猫,都有名字,是字符串。“类”。 var Cat = mongoose.model('Cat', { name: String }); //实例化一只猫 var kitty = new Cat({ name: 'Zildjian' }); //调用这只猫的save方法,保存这只猫 kitty.save(function (err) { console.log('喵喵喵'); }); </code></pre> <ul> <li>创建模型</li> </ul> <pre><code>var Schema = mongoose.Schema; var userScheMa = new Schema({ name: String, password: String }); // 定义了一个新的模型,但是此模式还未和users集合有关联 exports.user = db.model('user', userScheMa); // 与users集合关联 ref 数据表关联 </code></pre> <hr /> <pre><code>这次不皮了 </code></pre> 前端https://www.scarsu.com/mongodb_configuration/#post-comment/Animate.csshttps://www.scarsu.com/animatecss/https://www.scarsu.com/animatecss/Animate.css是一个来自国外的 CSS3 动画库。Thu, 01 Feb 2018 00:00:00 GMT<h2>功能</h2> <ul> <li>它预设了抖动(shake)</li> <li>闪烁(flash)</li> <li>弹跳(bounce)</li> <li>翻转(flip)</li> <li>旋转(rotateIn/rotateOut)</li> <li>淡入淡出(fadeIn/fadeOut)</li> <li>等多达 60 多种动画效果</li> </ul> <h2>浏览器兼容:</h2> <pre><code>只兼容支持 CSS3 animate 属性的浏览器, 分别是:IE10+、Firefox、Chrome、Opera、Safari。 </code></pre> <h2>引入文件</h2> <pre><code>&lt;link rel="stylesheet" href="animate.min.css"&gt; </code></pre> <h2>官网</h2> <pre><code>[Animate.css](https://daneden.github.io/animate.css/) [Github](https://github.com/daneden/animate.css) </code></pre> <h2>使用</h2> <pre><code> &lt;h1 class="animated infinite bounce delay-2s"&gt;Example&lt;/h1&gt; </code></pre> <ul> <li>首先给元素加上 animated 类</li> <li>第二个 infinate 使动画无限播放,可选</li> <li>第三个 bounce 是具体的动画效果名称,<a>全部动效演示</a></li> <li>第四个 delay-2s 是动效延迟播放 2s,可选</li> </ul> <h2>通过 Js,Jq 给元素添加 class:</h2> <pre><code> $(function(){ $('#dowebok').addClass('animated bounce'); }); </code></pre> <h2>更改 animate.css 的默认设置:</h2> <pre><code> #dowebok { animate-duration: 2s; //动画持续时间 animate-delay: 1s; //动画延迟时间 animate-iteration-count: 2; //动画执行次数 } //兼容各种浏览器代码,需要添加各浏览器前缀: #dowebok{ -webkit-animation-duration: 3s; -webkit-animation-delay: 4s; -webkit-animation-iteration-count: 5; -moz-animation-duration: 3s; -moz-animation-delay: 4s; -moz-animation-iteration-count: 5; -o-animation-duration: 3s; -o-animation-delay: 4s; -0-animation-iteration-count: 5; -ms-animation-duration: 3s; -ms-animation-delay: 4s; -ms-animation-iteration-count:5; animation-duration: 3s; animation-delay: 4s; animation-iteration-count: 5; } </code></pre> <h2>动画结束触发函数:</h2> <pre><code> $(".test").click(function(){ $(this).addClass('animated fadeOut'); }); var animateEnd=(function(el){ var animations={ animation:'animationend', OAnimation:'oAnimationEnd', MozAnimation:'mozAnimationEnd' WebktiAnimation:'webkitAnimationEnd' } for(var i in animations){ if(el.style[i]!==undefined){ return animations[i] } } })(document.createElement('div'));//通过任意元素检测浏览器内核类型 $('.test').one(animateEnd, doSomething); //$.one():为元素的特定事件绑定一个一次性的事件处理函数。 </code></pre> <h2>将以上过程整合为 Jq 扩展函数</h2> <pre><code>jq自定义函数 $.fn.extend({ animateCss: function (animationName, callback) { var animationEnd = (function (el) { var animations = { animation: 'animationend', OAnimation: 'oAnimationEnd', MozAnimation: 'mozAnimationEnd', WebkitAnimation: 'webkitAnimationEnd', }; for (var t in animations) { if (el.style[t] !== undefined) { return animations[t]; } } })(document.createElement('div')); this.addClass('animated ' + animationName).one(animationEnd, function () { //某些动画效果执行完后元素不可见又需要这个元素(实际遇过这个问题) //eg.淡出、向左滑动等等, //可能需要将 class 删除 $(this).removeClass('animated ' + animationName); if (typeof callback === 'function') callback(); }); return this; }, }); $('#yourElement').animateCss('bounce'); $('#yourElement').animateCss('bounce', function () { // 事件结束触发的函数 }); </code></pre> <hr /> <pre><code>为什么不自己写动画? 别人比你写的好啊小辣鸡。 </code></pre> 前端https://www.scarsu.com/animatecss/#post-comment/提高效率的前端工具https://www.scarsu.com/fe_tools/https://www.scarsu.com/fe_tools/分享一些用的顺手的前端效率工具~Mon, 01 Jan 2018 00:00:00 GMT<h4>http-server 本地快速静态资源服务器</h4> <ul> <li>npm 全局安装</li> <li>执行<code>hs</code>命令</li> <li>即可在terminal当前路径创建一个本地http静态资源服务器,方便调试</li> </ul> <h4>nrm npm快速切换国内源</h4> <ul> <li>npm全局安装nrm</li> <li><code>nrm ls</code>命令列出当前可使用的国内npm源,eg. taobao</li> <li><code>nrm use xx</code>即可切换到某一源</li> </ul> <h4>nvm 快速切换node版本</h4> <ul> <li>nvm官网安装</li> <li><code>nvm list</code>列出当前机器已经安装的node版本</li> <li><code>nvm install vxx</code>安装某一版本node</li> <li><code>nvm use</code>切换到某一版本node</li> </ul> <h4>parcel 极简配置版<strong>webpack</strong></h4> <ul> <li>npm全局安装parcel<code>npm i parcel-bundler -g</code></li> <li><code>parcel setup/index.html</code>即可创建一个本地服务器,并构建打包当前html的依赖</li> </ul> <h4>nodemon 热更新</h4> <ul> <li>npm全局安装<code>npm i nodemon -g</code></li> <li><code>nodemon xx.js</code></li> </ul> 前端https://www.scarsu.com/fe_tools/#post-comment/胡言乱语 | 我与这世界的距离https://www.scarsu.com/escape_from_the_world/https://www.scarsu.com/escape_from_the_world/一些胡言乱语Thu, 06 Jun 1996 00:00:00 GMT<h2>如何与情绪相处</h2> <p>从人性上来说,我们倾向于保护自我最脆弱的部分</p> <p>伤痛、需求未被满足、罪恶、耻辱会激发我们痛苦、恐惧、愤怒的情绪,这是人类天生的保护机制</p> <p>我们无法控制自己的本能,但是应该学会接受、正视、了解我们的感觉和情绪,</p> <p>去发现并解决 情绪背后 激发情绪的问题,而不是去任由情绪发泄</p> <h2>不要扮演受害者</h2> <p>责怪、批评与指责是人类防御机制的关键要素。</p> <p>责怪他人、批评他人行为、指责他人不愿改变,其实是一种轻而易举的手段,</p> <p>能够简单地利用道德批判,将自己提升到一个高于他人的位置,也使我们摆脱了自身的不安。</p> <p>然而,责怪、批评与指责的态度最终只会加强自我的受害者意识。</p> <p>受害者常感到无力、无助、无价值且无法自我满足。</p> <p>他们的防卫机制常常是自我否定,并将自己置于一个道德正确的位置。</p> <p><strong>当我们坦然面对内在的受害情绪时,我们将有机会更具有意识地正视这份感觉,并了解这仅是一种感受,而非事实</strong></p> <p>责怪、批评与指责也终将不再发生。</p> <h2>亲密关系</h2> <p>亲密关系是一种完美设计</p> <p>在亲密关系中,所有的一切都是重要的部分,即使是令人不悦的冲突与不适的情境。</p> <p>当你继续在感情中成长时,你也开始<strong>懂得欣赏你跟伴侣之间所发生的任何事情</strong>。</p> <p>你的伴侣不是你的爱与幸福的来源,满足你的期待与使你开心不是他们的职责。</p> <p>你的伴侣在你的生活中扮演了三个重要的角色:</p> <ul> <li>一面镜子,让你看见引发你关注的不舒服感;</li> <li>一名老师,在你探寻真实自我的时候,激励与启发你;</li> <li>一名“玩伴”,开启并陪伴你一段生命的旅程。</li> </ul> <h2>学习最原始的驱动力</h2> <p>保持质疑</p> <p>保持好奇心和兴趣</p> <p>保持对努力的自信</p> <h2>No means No</h2> <p>该表达态度的时候,要明确、干净、利落的表达。</p> <h2>就是不想努力怎么办</h2> <blockquote> <p>我就想做一个安于现状的人</p> <p>就想利用上班赚钱过好自己的小日子</p> <p>就想平凡的过完一生</p> <p>我就是不想拼命奋斗,拼命努力,拼命内卷</p> <p>不可以吗?</p> </blockquote> <p>当然可以,每个人的追求不同,淡泊名利,平静一生,真正能做到的话,是一种很高的人生境界。</p> <p>但是你做出这种决定,就要考虑其带来的结果</p> <blockquote> <p>你能做到真正的“淡泊名利”吗?</p> <p>当别人用光鲜亮丽的服装、车子、房子包装和提升自己的生活品质时,你能做到不羡慕吗</p> <p>当别人在马尔代夫浮潜、在阿尔卑斯滑雪、在土耳其滑翔、在富士山脚泡温泉喝清酒,你能做到不羡慕吗</p> <p>你身边的人生活品质都比你高得时候,你会不会后悔</p> <p>你的普通收入扣除房子首付、房贷、车子、奶粉钱之后你还足够安稳吗</p> <p>如果不买房,你可以做到一生租房,并容忍一生到老不断的搬家吗</p> <p>你的普通收入能让你匹配上你心仪的另一半吗</p> <p>你的现状能维持你一生的稳定平凡吗?你能对抗人生所有的风险吗</p> <p>你可以为自己的一生、父母后半生、孩子前半生的大大小小的健康问题买单吗</p> <p>如果你有了孩子,你作为爸爸/妈妈,能给孩子最好的教育吗</p> </blockquote> <p>如果你深刻的考虑了这些问题,都能得到坚定的答案,那么安于现状,不拼命努力,也没什么不好</p> <p>每个人的人生都不同,人生的路也没有对错之分,只是路上的酸甜苦辣,你需要独自承担</p> <h2>别让任何人打乱你的人生节奏</h2> <blockquote> <p>每个人的人生都不同</p> <p>"Not everything that counts can be counted,and not everything that's counted truly counts"</p> <p>"并不是每件算出来的事,都有意义;也不是每件有意义的事,都能被算出来" ——爱因斯坦</p> </blockquote> <p><a>@https://www.bilibili.com/video/BV1WW411F7Hx</a></p> <h2>关于坚持</h2> <blockquote> <p>坚持这两个字,远比你想象中的要难的多,但也比你想象中的有效的多。</p> <p>'You do make a difference!'</p> </blockquote> <p><a>@https://www.bilibili.com/video/BV1XJ411d7Xx</a></p> <blockquote> <p>两年,是很容易虚度过去的时长,也是足够改变自己的时长。</p> </blockquote> <p><a>@https://www.bilibili.com/video/BV1NE41197sr</a></p> <h2>如何追求快乐</h2> <blockquote> <p>有很多快乐是放纵的快乐,是降低了人性尊严的快乐,而越能体现人性尊严的快乐,越是一种高级的快乐。</p> <p>追求高级的快乐并不意味着放弃低级的快乐,但是如果你的眼目永远只关注地下,你永远不知道向上看有多么的快乐。</p> </blockquote> <p>——罗翔</p> <p><a>@https://www.bilibili.com/video/BV1AE411T7p7</a></p> <blockquote> <p>I don't need dollar bills to have fun</p> </blockquote> <p>——【Cheap Thrills】 Sia</p> <h2>成熟的一些标志</h2> <blockquote> <p>能克制欲望,不追求即时反馈,延迟享受。</p> <p>保持一致性,无论在人群中还是独处时,知行合一,不卑不亢,不矫揉造作,不哗众取宠。</p> <p>心中始终有底线、有原则、有追求。</p> <p>时刻反省自己:what在做什么、why为什么这样做、how如何做的更好</p> </blockquote> <p>—— 尼古拉斯·鱼</p> <h2>享受平静才是生活的真谛</h2> <blockquote> <p>“上次我去一个朋友家玩,看到他们客厅里摆着一张很长的桌子。朋友说,每到周末,两个大人,一个孩子,还有两只猫都会围在这个桌子旁,家里很安静,只有书页翻动和画笔接触纸张的细微声音。”</p> </blockquote> <h2>看电影/阅读的意义是什么?</h2> <blockquote> <p>谁看到的维度越多,世界在谁的眼中便越真实。</p> <p>练习自己感动、愤怒、喜悦、震惊、欢笑、平静的能力 不被苟且的生活捆绑致死。</p> <p>认识这个世界,丰富认知维度。</p> <p>即使生活一平如水、或筋疲力尽、或颠沛流离,仍要感受这个形形色色的世界,满怀希望,拥有细腻的情感。</p> </blockquote> <h2>子 瓜 犭 虫</h2> <blockquote> <p>稚儿擎瓜柳棚下,细犬逐蝶窄巷中,人间繁华多笑语,惟我空余两鬓风。</p> <p>“孤独”</p> <p>这两个字拆开看,有小孩,有水果,有走兽,有蚊蝇</p> <p>足以撑起一个盛夏傍晚的巷子口,人味十足。</p> <p>夏日的傍晚,你看着空中嗡嗡飞舞的飞虫,不远处的狗摇着尾巴穿巷而过,你手中拿着吃剩下的半块西瓜</p> <p>忽然觉得好像过了半辈子</p> <p>又好像只过了半分钟。</p> </blockquote> <h2>为什么要趁年轻多学习&lt;a rel="nofollow" href="https://www.zhihu.com/question/354919014/answer/906152325"&gt;&lt;i class="fa fa-link"&gt;&lt;/i&gt;原文&lt;/a&gt;</h2> <blockquote> <p><strong>爆炸性压力才能带来爆炸性进步</strong></p> <p>每次我状态低迷的时候,我都会看看这个视频,视频18分钟,如果你懒得看,我简述一下:</p> <p>演讲者是许峰源先生,他出身一个非常贫穷的家庭,整个家庭,靠的是父亲踩着三轮车出去卖豆腐微薄的收入支撑着。</p> <p>这不是一个烂仔逆袭的故事,因为从小看到了生活艰苦的一面,许峰源一直很努力想考上台大法律系,因为成为律师才有高收入,才能改变家庭的现状。</p> <p>不幸的是,在他上大学的时候,父亲却查出了舌癌晚期,只剩一年左右的时间,为了让父亲在临终前看到自己的孩子成才,许峰源用了极短的时间通过了司法考试,成为了一名律师,让父亲看到了自己的律师证,才安然去世。</p> <p>祸不单行,很快许峰源的母亲也查出了患有肺腺癌,一种扩散很迅猛的癌症,为了让母亲有一个安享晚年的环境,许峰源在23岁的时候,毅然辞职创业,白天在律师事务所打拼,晚上做培训,最终让母亲住上了好房子,接受更好的治疗,然后平静地送走了母亲。</p> <p>前半生,许峰源先生为之奋斗的两个对象都走了,迷茫了一阵子之后,他依然没有放弃努力,而是选择了实现自我,成为了一名作家。</p> <p>再烂的牌也得打下去,这就是人生</p> </blockquote> <h2>时光</h2> <blockquote> <p>小时候小时候,夏天穿过山间的风,打在树梢的雨,外婆灶台上的饭香,无奈回忆真的变成了回忆。</p> </blockquote> <h2>《stronger》kelly clarkson</h2> <blockquote> <p>Doesn't mean I'm lonely when I'm alone</p> </blockquote> <h2>《Lolita》</h2> <blockquote> <p>洛丽塔,我生命之光,我欲念之火。我的罪恶,我的灵魂。</p> </blockquote> <h2>《阿甘正传》</h2> <blockquote> <p>life's like a feather</p> </blockquote> <h2>《하루하루》</h2> <blockquote> <p>离开时请不要回头</p> <p>以后活着也不要找我</p> <p>因为爱你</p> <p>没有一丝悔意</p> <p>所以请带着美好的回忆离去</p> </blockquote> <h2>《安娜·卡列尼娜》列夫·托尔斯泰</h2> <blockquote> <p>“幸福的家庭总是相似的,不幸的家庭各有各的不幸。”</p> </blockquote> <h2>阿德勒</h2> <blockquote> <p>“幸运的人一生都被童年治愈,不幸的人一生都在治愈童年。”</p> </blockquote> <h2>二十多岁浅薄的人生的唯一信仰:自律 + 坚持</h2> 个人成长https://www.scarsu.com/escape_from_the_world/#post-comment/
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
<channel>
<title>ScarSu - 终身成长,前端技术,信息源</title>
<description>96女性程序员,以终身成长为人生意义,热爱前端技术,喜欢读各种书,关注自我管理、心智成长、认知提升、极简生活。</description>
<link>https://www.scarsu.com/</link>
<item>
<title>View Transition API - 实现HTML视图的过渡动画</title>
<link>https://www.scarsu.com/view_transition_api/</link>
<guid isPermaLink="true">https://www.scarsu.com/view_transition_api/</guid>
<description>无需使用CSS精确指定动效”元素“、实现MPA跳转页面动效</description>
<pubDate>Thu, 19 Sep 2024 00:00:00 GMT</pubDate>
<content:encoded><h2>触发视图动效的方法&amp;时机:</h2> <ul> <li> <p>对于SPA,将更新DOM的方法<code>updateDomTrigger</code>作为参数传递给<a><code>document.startViewTransition(updateDomTrigger)</code></a>方法,浏览器会&lt;u&gt;先截取&lt;/u&gt;当前页面DOM元素的快照(声明了 <a><code>view-transition-name</code></a> CSS属性的DOM元素,默认是:root),&lt;u&gt;再执行&lt;/u&gt;<code>updateDomTrigger</code>方法,然后&lt;u&gt;再执行过渡动效&lt;/u&gt;。</p> </li> <li> <p>对于MPA,添加以下CSS规则,过渡效果会在导航到下一个同源页面的时候自动触发。</p> <pre><code>@view-transition { navigaion: auto; } </code></pre> </li> </ul> <h2>默认的过渡效果是&lt;u&gt;交叉淡化&lt;/u&gt;:</h2> <p>旧视图快照<code>opacity</code>从1 到 0,新视图快照<code>opacity</code>从0 到 1。</p> <h2>如何自定义动效:</h2> <p>HTML会针对视图动效生成以下伪元素树:</p> <pre><code>::view-transition └─ ::view-transition-group(root) └─ ::view-transition-image-pair(root) ├─ ::view-transition-old(root) └─ ::view-transition-new(root) </code></pre> <ul> <li>可以通过在多个 DOM 元素上设置不同的 <a><code>view-transition-name</code></a> CSS属性,对不同的元素使用不同的自定义动效。因此,每一个 <a><code>view-transition-name</code></a>都对应一个<code>view-transition-group</code>(默认是<code>root</code>)</li> <li><code>view-transition-old</code>指向动效前元素的静态快照</li> <li><code>view-transition-new</code>指向动效后元素的实时快照</li> </ul> <p>具体的动画效果由CSS animation设置:</p> <pre><code> /* 只需要添加以下@view-transition规则,就会在切换页面时,触发默认的“淡化”动效 */ @view-transition { navigation: auto; } /* 自定义默认的动画行为 */ ::view-transition-group(root) { animation-duration: 0.5s; } /* 创建自定义动画 */ @keyframes move-out { from { transform: translateY(0%); } to { transform: translateY(-100%); } } @keyframes move-in { from { transform: translateY(100%); } to { transform: translateY(0%); } } /* 将自定义动画应用到新旧元素 */ ::view-transition-old(root) { animation: 0.4s ease-in both move-out; } ::view-transition-new(root) { animation: 0.4s ease-in both move-in; } </code></pre> <h2>用JavaScript控制动效:</h2> <p>对于SPA,<a><code>document.startViewTransition()</code></a> 方法会返回一个 <a><code>ViewTransition</code></a> 对象实例,这个实例包含多个 promise:</p> <ul> <li><a><code>ViewTransition.ready</code></a> 在创建伪元素树且动画即将开始时执行。</li> <li><a><code>ViewTransition.finished</code></a> 在动画完成后、且新的页面视图对用户可见且具有交互性时执行。</li> </ul> <p>对于MPA:</p> <ul> <li>旧页面在即将unload之前,会触发<a><code>pageswap</code></a> 事件,事件的event对象上的<a><code>PageSwapEvent.viewTransition</code></a> 属性包含了 <code>ViewTransition</code> 实例, <a><code>PageSwapEvent.activation</code></a> 包含当前切换页面的导航类型、当前文档和目标文档历史记录。</li> <li>新页面初次渲染时, 会触发<a><code>pagereveal</code></a> 事件,事件的event对象上的<a><code>PageSwapEvent.viewTransition</code></a> 属性包含了 <code>ViewTransition</code> 实例。</li> <li>要注意的是,为了确保处理<a><code>pagereveal</code></a> 事件的script脚本在渲染动效之前执行,需要给脚本添加 <a><code>blocking=“render”</code></a> 属性;</li> <li>另外,为了确保动效执行之前,元素是可视的,需要添加标签<code>&lt;link rel="expect" href="#lead-content" blocking="render" /&gt;</code>,其中<code>#lead-content</code>指向对应元素。</li> </ul> <h2>浏览器兼容性</h2> <p><img src="https://prod-files-secure.s3.us-west-2.amazonaws.com/5e915be4-bfc2-464c-9c97-ee926a121cf1/caaf8df9-de8e-4db8-9105-6f8d2de2e242/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&amp;X-Amz-Credential=AKIAT73L2G45HZZMZUHI%2F20240919%2Fus-west-2%2Fs3%2Faws4_request&amp;X-Amz-Date=20240919T160947Z&amp;X-Amz-Expires=3600&amp;X-Amz-Signature=872495ce4514afe71f22e589e72c68f6d14672586a903ff2baf2b0bde129dd80&amp;X-Amz-SignedHeaders=host&amp;x-id=GetObject" alt="image.png" /></p> <h2>参考</h2> <ul> <li><a>MDN - </a><a><strong>Using the View Transitions API</strong></a></li> </ul> <hr /> <p>本篇文章使用<a>Notion</a>创作,由我的<a>自动化工具</a>从Notion同步。</p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/view_transition_api/#post-comment/</comments>
</item>
<item>
<title>Stacking Context - DOM元素的层级关系</title>
<link>https://www.scarsu.com/stacking_context/</link>
<guid isPermaLink="true">https://www.scarsu.com/stacking_context/</guid>
<description>理解DOM元素在网页z轴上的“竞争”</description>
<pubDate>Wed, 04 Sep 2024 00:00:00 GMT</pubDate>
<content:encoded><h2>不是z-index越大的元素越在上层</h2> <p>通过z-index来控制层级是很常见的前端需求,</p> <p>但是你是否遇到过,无论z-index设置多大,仍然无法将一个元素移到最上层的情况?</p> <p>这是因为z-index依赖于一个抽象的概念:Stacking Context</p> <h2>Stacking Context是什么?</h2> <p>stacking context是层叠上下文,决定了DOM元素上下层级关系</p> <h2>Stacking Context的根元素</h2> <p>每个层叠上下文都由一个元素创建,这个元素被称为stacking context的根元素</p> <h2>什么情况会创建Stacking Context?</h2> <ul> <li>html根元素</li> <li>fixed定位的元素</li> <li>其他任何<code>z-index</code>不是默认值<code>auto</code>的元素(z-index=0也会创建层叠上下文)</li> <li>CSS <ul> <li>有透明度的元素:opacity&lt;1</li> <li>有二维/三维变幻的元素:transform不为none,或者will-change</li> <li>有滤镜的元素:filter不为none</li> <li><code>isolation: isolate;</code>:创建一个新的堆叠上下文,隔离混合效果</li> </ul> </li> </ul> <h2>Stacking Context之间的层级顺序</h2> <ul> <li>对于同级(根元素是兄弟元素)的stacking context,层级由z-index值决定,z-index大的在上层;</li> <li>同级stacking context如果z-index相同,由DOM中出现的顺序决定,出现晚的在上层;</li> <li>对于嵌套的stacking context,子stacking context在上层;</li> </ul> <h2>Stacking Context内部层级顺序</h2> <ul> <li>最底层:元素的背景色、背景图、边框</li> <li>子元素由底层到顶层的顺序: <ul> <li>z-index&lt;0的元素</li> <li>块级盒子</li> <li>浮动盒子</li> <li>内联盒子</li> <li>z-index:0或auto的定位盒子</li> <li>z-index&gt;0的元素</li> </ul> </li> </ul> <h2>例子🌰</h2> <p>DOM结构:</p> <pre><code>div1 div2 div3 -&gt; div4 -&gt; div5 -&gt; div6 </code></pre> <p>最终的层级顺序:</p> <p><img src="https://prod-files-secure.s3.us-west-2.amazonaws.com/5e915be4-bfc2-464c-9c97-ee926a121cf1/3f528781-3642-4a43-8531-6c8ad362289a/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&amp;X-Amz-Credential=AKIAT73L2G45HZZMZUHI%2F20240905%2Fus-west-2%2Fs3%2Faws4_request&amp;X-Amz-Date=20240905T160916Z&amp;X-Amz-Expires=3600&amp;X-Amz-Signature=4a51eecc58c81e55b2093473bcab93b4996cc0b3fa50bc208a592bd50cbd6ff4&amp;X-Amz-SignedHeaders=host&amp;x-id=GetObject" alt="image.png" /></p> <h2>一个有用的浏览器扩展:CSS Stacking Context inspector</h2> <p><img src="https://prod-files-secure.s3.us-west-2.amazonaws.com/5e915be4-bfc2-464c-9c97-ee926a121cf1/fe7e85f8-ad4a-499d-acd6-c727feda0e52/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&amp;X-Amz-Credential=AKIAT73L2G45HZZMZUHI%2F20240905%2Fus-west-2%2Fs3%2Faws4_request&amp;X-Amz-Date=20240905T160916Z&amp;X-Amz-Expires=3600&amp;X-Amz-Signature=7255fd56b56f4f2370eb2aaf52deb598058cfcf3313c43480bb76e142410ccec&amp;X-Amz-SignedHeaders=host&amp;x-id=GetObject" alt="image.png" /></p> <p>这个扩展在浏览器devtools中列出了网页上的stacking context。在遇到z-index和层级问题时,可以让我们更快的定位问题。</p> <hr /> <p>本篇文章使用<a>Notion</a>创作,由我的<a>自动化工具</a>从Notion同步。</p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/stacking_context/#post-comment/</comments>
</item>
<item>
<title>2023热门JS语法新特性</title>
<link>https://www.scarsu.com/2023_javascript_syntax/</link>
<guid isPermaLink="true">https://www.scarsu.com/2023_javascript_syntax/</guid>
<description>JS Syntax Feature from 《state of js 2023》</description>
<pubDate>Mon, 02 Sep 2024 00:00:00 GMT</pubDate>
<content:encoded><h2>Nullish Coalescing</h2> <p>空值合并运算符(??),识别null和undefined值;<a>MDN</a></p> <pre><code>const foo = null ?? 'default string'; console.log(foo); // Expected output: "default string" const baz = 0 ?? 42; console.log(baz); // Expected output: 0 </code></pre> <h2>Dynamic Import</h2> <p>动态引入,import函数支持异步引入js模块;<a>MDN</a></p> <pre><code>import(moduleName) import(moduleName, options) await import('/modules/my-module.js') </code></pre> <h2>Private Field</h2> <p>类私有属性,以<code>#</code>为前缀,无法在类的外部引用;<a>MDN</a></p> <pre><code>class ClassWithPrivateField { #privateField } </code></pre> <h2>Logical Assignment</h2> <p>逻辑与赋值<code>&amp;&amp;=</code>,逻辑或赋值<code>||=</code>;<a>MDN</a></p> <pre><code>const a = { duration: 50, title: '' }; a.duration ||= 10; console.log(a.duration); // expected output: 50 a.title ||= 'title is empty.'; console.log(a.title); // expected output: "title is empty" let a = 1; let b = 0; a &amp;&amp;= 2; console.log(a); // Expected output: 2 b &amp;&amp;= 2; console.log(b); // Expected output: 0 </code></pre> <h2>Hashbang Comments</h2> <p><code>#!</code> HashBang注释,用于在shell中执行js时,指定js解释器</p> <p>是单行注释,只能写在js代码的第一行;<a>MDN</a></p> <pre><code>#!/usr/bin/env node console.log("Hello world"); </code></pre> <h2>error.cause</h2> <p>error实例中cause属性,指示了引起错误的具体原因;<a>MDN</a></p> <pre><code>try { connectToDatabase(); } catch (err) { throw new Error('Connecting to database failed.', { cause: err }); } </code></pre> <h2>array.toSpliced(),toSorted(),toReversed()</h2> <p>不改变数组原始值,创建新数据作为返回值</p> <h2>array.with()</h2> <p>相对于直接用<code>[索引]</code>更新数组,with方法不改变原始值、返回新数组</p> <pre><code>const arr = [1, 2, 3, 4, 5]; console.log(arr.with(2, 6)); // [1, 2, 6, 4, 5] console.log(arr); // [1, 2, 3, 4, 5] </code></pre> <hr /> <p>本篇文章使用<a>Notion</a>创作,由我的<a>自动化工具</a>从Notion同步。</p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/2023_javascript_syntax/#post-comment/</comments>
</item>
<item>
<title>Notion到博客的自动化更新</title>
<link>https://www.scarsu.com/notion_to_blog/</link>
<guid isPermaLink="true">https://www.scarsu.com/notion_to_blog/</guid>
<description>在notion写文章,自动化更新到git 代码仓库,再自动化部署到网站</description>
<pubDate>Sat, 29 Jul 2023 00:00:00 GMT</pubDate>
<content:encoded><p>我在上周的文章<a>《</a><a><strong>程序员一定要有自己的博客</strong></a><a>》</a>中写了我博客工具链的5步:</p> <ol> <li>在趁手的工具写笔记(Notion PC端、移动端)</li> <li>工具将笔记转化为md文档</li> <li>自动推送md文档到我的博客git仓库</li> <li>git仓库更新,触发部署工具(netlify、vercel、jenkins)自动部署</li> <li>更新博客</li> </ol> <p>当时只实现了其中1245步,经过两天的探索我完成了第3步,让这个工具链实现了完整的自动化,这篇文章大致介绍一下。</p> <h2>从Notion到Git仓库</h2> <p>我的博客代码仓库使用Github托管,Github提供了一个十分有用的自动化工作流的工具:<a>Github Actions</a>。</p> <p>Github Actions 可以定时执行我提供的脚本,通过脚本,实现了从Notion到代码仓库的更新。大致逻辑是这样的:</p> <ol> <li>Github Actions 负责每天凌晨00:00执行脚本</li> <li>在脚本中,使用Notion API接口获取Notion特定数据库的数据,筛选出前一天更新的文章</li> <li>为每一篇文章,在代码仓库创建一个md文件</li> <li>将文章的attributes,转化为博客md文件的frontmatter</li> <li>将文章正文的md字符串,转化为md文件的正文内容</li> <li>将所有md文件通过git命令提交到github仓库中</li> <li>如果脚本执行失败,github会发邮件通知我</li> </ol> <p>通过以上脚本,实现了 notion文章数据库到git仓库的更新。</p> <p>脚本执行的频率是可以自由更改的,我偏向于损失一些时效性,保证环境稳定性,所以选择了一天一更新。</p> <p>以上脚本可以在我的博客开源仓库中看到,<a>链接在这里</a> 和 <a>这里</a>。</p> <p>由于我们的notion数据库字段、md文件的frontmatter配置很可能不同,我的脚本无法直接被你复用,有几个需要考虑变更的点:</p> <ul> <li>在你的git仓库中,需要配置几个脚本中需要使用的secrets。配置的地方在<code>你的github仓库首页 - settings - secrests and variables - actions</code>,参数名是<code>NOTION_DATABASE_ID</code>和<code>NOTION_KEY</code>,前者是你在Notion中文章所在数据库的id(可以通过copy link获得),后者是你开通的notion api的key(notion api的开通详见<a>这个文档</a>)。</li> <li>从notion page attributes到md frontmatter的映射,可以在<a>这个脚本</a>的<code>postToMDFile</code>中找到,逻辑比较简单,按照你的需求修改即可。</li> <li>脚本中的git信息,例如name、email、branch 可以按照你的需求修改。</li> <li>按照你的需求筛选notion数据,filter写在<a>这个脚本</a>的<code>getPosts</code>中。</li> <li>有一个可能踩坑的点在于,必须要将workflow读写仓库的权限开启,否则脚本会因为缺少git push权限而报错,开启权限的地方在:<code>github仓库首页-settings-actions-general-workflow permission - 开启read and write permissions</code></li> <li>脚本的执行周期,可以在上<a>述yml脚本</a>的cron字段中配置,注意脚本中的时间使用的是UTC时间,要考虑当地时区的时间差,例如UTC=北京时间-8,我希望在凌晨0点执行,所以写的小时是16。</li> </ul> <h2>从Git仓库到博客网站</h2> <p>这一步我使用的是Vercel工具,监听Git仓库的push事件,自动拉取代码更新,打包部署到网站。</p> <p>这一步Vercel的配置很简单,推荐查看<a>官方文档</a>,不做赘述。</p> <hr /> <p>本篇文章使用<a>Notion</a>创作,由我的<a>自动化工具</a>从Notion同步。</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/notion_to_blog/#post-comment/</comments>
</item>
<item>
<title>时钟准确的定时轮询函数</title>
<link>https://www.scarsu.com/accurate_setinterval/</link>
<guid isPermaLink="true">https://www.scarsu.com/accurate_setinterval/</guid>
<description>js的单线程异步机制决定了setInterval和setTimeout函数的时钟不准确性</description>
<pubDate>Fri, 28 Jul 2023 00:00:00 GMT</pubDate>
<content:encoded><p>浏览器原生的setTimeout(fn,timeout)函数的原理,是保证timeout时间后,将回调函数fn加入event loop的消息队列,不是保证timeout时间后一定执行。</p> <p>回调函数加入的消息队列后,实际的执行时间要等到 调用栈中已有函数 + 消息队列已有消息执行完毕。</p> <p>所以回调函数的实际执行时间与设定的timeout有偏差。</p> <p>setInterval函数也同样有偏差。</p> <p>以下实现了一个时间准确的定时轮询函数。</p> <h2>setClockInterval 函数</h2> <pre><code>/** * setClockInterval是时钟准确的定时轮询函数(原生setInterval时钟不准确) * @param func 与原生setInterval参数一致 * @param interval 与原生setInterval参数一致 * @return timer 类型为number */ const timerMap = new Map() export function setClockInterval(func: Function, interval: number) { let start: number let tick: number let clockTimer: number | null const timerId = Math.floor(Math.random() * 1e10) const recurFunc = () =&gt; { func() const realExcuTime = new Date().getTime() if (!start) { start = realExcuTime } tick = tick || start // bias是本次实际执行时间戳 与 理论执行时间戳tick之间的偏差 // bias一定&gt;=0,因为浏览器的setTimeout setInterval只会准时或者延迟执行,不会提前执行 // 经过本地浏览器统计 bias平均值在10ms以内,最大值在20ms左右 const bias = realExcuTime - tick console.log(`实际执行时间戳${realExcuTime},理论计划执行时间戳${tick},本次偏差${bias}ms`); // 下次tick时间戳 tick += interval // 因为本次实际执行时间有bias的延迟,所以下次执行提前 clockTimer = window.setTimeout(recurFunc, interval - bias) timerMap.set(timerId, clockTimer) } recurFunc() return timerId } </code></pre> <h2>clearClockInterval 函数</h2> <pre><code>/** * clearClockInterval 用于终止 setClockInterval 的定时轮询 * @param timer 是 setClockInterval 的返回值 */ export function clearClockInterval(timerId: number) { if (timerMap.has(timerId)) { window.clearTimeout(timerMap.get(timerId)) } else { console.warn(`timerId${timerId}not found`); } } </code></pre> <h2>demo执行效果</h2> <p>bias平均值在10ms以内,最大值在20ms左右</p> <pre><code>09:45:39.557 util.ts:23 实际执行时间戳1690508739557,理论计划执行时间戳1690508739550,本次偏差7ms 09:45:40.555 util.ts:23 实际执行时间戳1690508740555,理论计划执行时间戳1690508740550,本次偏差5ms 09:45:41.561 util.ts:23 实际执行时间戳1690508741561,理论计划执行时间戳1690508741550,本次偏差11ms 09:45:42.559 util.ts:23 实际执行时间戳1690508742559,理论计划执行时间戳1690508742550,本次偏差9ms 09:45:43.559 util.ts:23 实际执行时间戳1690508743559,理论计划执行时间戳1690508743550,本次偏差9ms 09:45:44.560 util.ts:23 实际执行时间戳1690508744560,理论计划执行时间戳1690508744550,本次偏差10ms 09:45:45.556 util.ts:23 实际执行时间戳1690508745555,理论计划执行时间戳1690508745550,本次偏差5ms 09:45:46.552 util.ts:23 实际执行时间戳1690508746552,理论计划执行时间戳1690508746550,本次偏差2ms 09:45:47.562 util.ts:23 实际执行时间戳1690508747562,理论计划执行时间戳1690508747550,本次偏差12ms 09:45:48.561 util.ts:23 实际执行时间戳1690508748561,理论计划执行时间戳1690508748550,本次偏差11ms </code></pre> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/accurate_setinterval/#post-comment/</comments>
</item>
<item>
<title>程序员一定要有自己的博客</title>
<link>https://www.scarsu.com/why_blog_and_how_to_choose/</link>
<guid isPermaLink="true">https://www.scarsu.com/why_blog_and_how_to_choose/</guid>
<description>聊聊为什么要有博客,以及选择博客工具链的目标</description>
<pubDate>Wed, 19 Jul 2023 00:00:00 GMT</pubDate>
<content:encoded><p>最近用astro对自己的博客进行了重构,投入了很大的热情和很多的时间,导致耽误了这个月的读书任务,于是反思了一下是否值得这么做。</p> <p><img src="/images/picgo/20230720232416.png" alt="" /></p> <h2>为什么要有博客</h2> <p>博客之于程序员意义重大,因为,<strong>输出</strong>是一个程序员的基本素养和技能,<strong>开源分享</strong>是科学技术发展和人类社会进步的重要美德和推动力,而博客正是输出分享的重要途径之一。</p> <p>为什么输出分享对程序员来说十分重要,我有以下几点看法。</p> <ul> <li> <p>从技术角度考虑,技术的提升依赖于专业知识的学习以及实际经验的积累,而人的大脑需要不断地进行重复记忆,才能将这些知识经验留在自己的知识库里。因此,无论是学习新知识还是通过实践得到的经验,有了即时的输出记录,才便于复盘与巩固。</p> </li> <li> <p>在实际工作中,当我们面临复杂大型的项目,和其中大量的代码时,如果只根据个人喜好而不根据代码规范去开发,写完后不留存开发文档以及接口文档,必然给项目的维护带来更高的代价,给团队中的其他开发者带来困扰。因此,代码规范和开发文档的输出也相当必要。</p> </li> </ul> <p>如果你还不相信,坚持输出给程序员带来好处的例子很多,我随意举几个。</p> <ul> <li> <p>例如 IT 圈出名的<a>阮一峰</a>,<a>张鑫旭</a>,stormzhang(这位已经不再分享技术了)等等大佬,他们有今天这种影响力的一个重要因素就是输出分享;</p> </li> <li> <p>我也曾不止一次收到前辈的建议,前端圈的<a>小爝</a>大佬在知乎的某个<a>回答</a>当中提到过“长期坚持技术输出和总结分享”在找工作面试中是一个亮点和加分项;</p> </li> <li> <p>“前端桃园”公号的运营者桃翁也十分提倡坚持输出,他在他星球小圈子中给我们分享过他自己 因为坚持输出提升了影响力 而多次收到阿里面试邀请的经历。</p> </li> </ul> <p>还有很多例子,不一一例举,分享本文的原因也就写到这,不再赘述。</p> <p>(当然输出分享的途径很多,本文以介绍博客为目的,如果选择其他途径可以忽略下文)</p> <h2>我选择博客工具链的目标</h2> <p>现在网络上有各式各样的博客,有基于第三方的平台(如博客园、csdn 等),自带用户和流量,但是要受平台约束和限制;</p> <p>也有可供个人搭建的工具(如 Hexo、Ghost、wordpress、jekyll 等),自由度高,但是需要从0开始搭建和积累流量;</p> <p>选择一个最适合自己的最重要。</p> <p>作为一个博客,我最重视的有两个方面:</p> <ol> <li>自由,可自定义,可个性化。</li> </ol> <p>因为每个人追求的博客风格不同,想要展示的内容和格式也有所不同。</p> <p>我希望能自由地表达自己想说的话。</p> <ol> <li>高效转化。</li> </ol> <p>我指的转化,是你的输出原文档 到 博客文本的转化,这一转化的过程对于想要存档原文,或不习惯于博客编辑器,不习惯于博客网页格式的人之分重要。</p> <p>我推崇用 markdown 来写笔记,因为 markdown 足够简约优雅,兼容性也十分强,</p> <blockquote> <p>Markdown 是一种轻量级的「标记语言」,通常为程序员群体所用,目前它已是全球最大的技术分享网站 GitHub 和技术问答网站 StackOverFlow 的御用书写格式。</p> <p>非技术类笔记用户,千万不要被「标记」、「语言」吓到,Markdown 的语法十分简单,常用的标记符号不超过十个,用于日常写作记录绰绰有余,不到半小时就能完全掌握。</p> <p>就是这十个不到的标记符号,却能让人优雅地沉浸式记录,专注内容而不是纠结排版,达到「心中无尘,码字入神」的境界。</p> </blockquote> <p>总结来说,我目标的工具链是这样的:</p> <ol> <li>在趁手的工具写笔记(Notion PC端、移动端)</li> <li>工具将笔记转化为md文档</li> <li>自动推送md文档到我的博客git仓库</li> <li>git仓库更新,触发部署工具(netlify、vercel、jenkins)自动部署</li> <li>更新博客</li> </ol> <p>目前已经实现了1,2,4,5,目前正在研究第3步,成功后我就不会再对工具链投入时间,而是把注意力放到内容上。</p> <h2>写在最后</h2> <p>以技术为目标的人,切忌浮躁。</p> <p>莫逞他人嘴上快,莫争浮世虚功名,心无旁骛,沉下心来钻研技术就好。</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/why_blog_and_how_to_choose/#post-comment/</comments>
</item>
<item>
<title>原则:Principles for Life and Work</title>
<link>https://www.scarsu.com/principles_life_and_work/</link>
<guid isPermaLink="true">https://www.scarsu.com/principles_life_and_work/</guid>
<description>以看待机器的方式看待生活和工作,找到事情反复发生的周期,总结经验,转化为原则;客观地承认自己的缺点和思维盲点,保持开放的态度,与他人协作。</description>
<pubDate>Tue, 27 Jun 2023 00:00:00 GMT</pubDate>
<content:encoded><h2>简介</h2> <ul> <li>书名:《原则》</li> <li>原名:Principles:Life and Work</li> <li>作者:瑞·达利欧</li> <li>出版时间:2018-1</li> <li>ISBN:9787508684031</li> <li>豆瓣链接:https://book.douban.com/subject/2760823</li> <li>豆瓣评分:8.3⭐</li> <li><a>官方动画讲解(全8集)- 哔哩哔哩</a></li> </ul> <p><img src="/images/picgo/IMG_0168.jpeg" alt="封面" /></p> <h2>必须做一个独立的思考者</h2> <ul> <li>必须自己思考真相是什么,必须基于自己的价值观总结自己的原则</li> <li>自己决定怎么做</li> <li>有勇气去做</li> <li>决策质量决定生活质量</li> <li>反思错误,形成原则。</li> </ul> <h2>拥抱现实,应对现实</h2> <ul> <li>真相是取得良好结果的根本基础</li> <li>梦想+现实+决心=成功的生活</li> <li>每个人都必须根据自身价值观选定目标、并选定实现目标的途径</li> <li>痛苦+反思=进步(一旦感受到痛苦,就是提示你反思进步的信号</li> <li>经历痛苦,反思,解决问题取得成功,总结经验原则应对未来</li> </ul> <h2>五步流程</h2> <ul> <li>知晓自己的目标</li> <li>应对阻碍你实现自己目标的问题,找出问题,不容忍问题</li> <li>诊断问题,找到问题根源,区分“症状和疾病根源”</li> <li>规划一个方案来彻底解决问题</li> <li>践行,推动自己做需要做的事</li> </ul> <h2>一切都是机器:事物运行原则</h2> <ul> <li>以看待机器的方式看待每个人、地球宇宙、生活、投资</li> <li>大多数事情都在以大同小异的方式反复发生,有些在易于识别的短期循环中发生(例如日出日落),有些可能在人的一生中也不会发生一次、或者在很长的周期才发生一次(例如百年一遇的地震 台风 养育孩子的周期)</li> <li>与其将每件事情当作一次性事件看待,不如将其视为类似情境的重现</li> <li>找到事情反复发生的周期和方式,看到其背后的因果关系,总结原则,以语言、算法的形式表达,以助于未来做更好的决策。</li> </ul> <h2>两个最大障碍</h2> <ul> <li>自我意识 <ul> <li>大脑里阻止你客观的承认自己缺点的区域,我们不喜欢直视自己错误和缺点,我们会不经过妥当的测试就相信自己的观点,我们本能地把对自己的弱点和错误的探讨 视作对自己的攻击 从而发怒。这导致我们接受不到客观反馈、做出差的决策</li> </ul> </li> <li>思维盲点 <ul> <li>人自以为能查知一切,但实际上任何人都无法完整的看到现实,人无法理解自己看不到的东西。</li> <li>每个人的音域、视力、辨色能力、味觉都不同,我们查知和理解事物的能力也不同,有的人习惯线性思维、有的人习惯发散思维;有些人可靠但没有创造力、有些人有创造力但却不可靠。 <ul> <li>只顺着自己的天性做事,就会忽略自己的弱点,就会失败。</li> </ul> </li> </ul> </li> </ul> <h2>如何解决上述两个问题:做到极度头脑开放</h2> <ul> <li>不为了「证明自己对而沾沾自喜」,而是为了「获得真相」而高兴</li> <li>与视角不同的思想者一起努力:找出与自己意见不同的最有想法的人,不在乎他们的结论,从他们的视角看问题,并让他们从我的视角看问题,这样就能一起把问题梳理明白,发现真相。</li> <li>把「惧怕错误结论的恐惧」转化为「追求真相的动力」。</li> </ul> <h2>奋力拼搏</h2> <ul> <li>直面现实、承认自己错误和缺陷、与在不同方面比自己更强的人走到一起,这些做法 是做出良好决策最有效的方式。</li> <li>目标只是诱饵,一次次奋力争取诱饵 迫使我们进化。与他人协作的个人进化才是拼搏的回报。</li> </ul> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/principles_life_and_work/#post-comment/</comments>
</item>
<item>
<title>Vite笔记</title>
<link>https://www.scarsu.com/vite/</link>
<guid isPermaLink="true">https://www.scarsu.com/vite/</guid>
<description>Vite组成、原理、配置、插件、性能优化</description>
<pubDate>Sat, 17 Jun 2023 00:00:00 GMT</pubDate>
<content:encoded><h2>Vite 读 /vit/</h2> <h2>资源</h2> <ul> <li>[官方文档](https ://Vitejs.dev/)</li> <li><a>Vite源码</a></li> <li><a>Awesome Vite</a></li> </ul> <h2>Vite发展&amp;现状</h2> <ul> <li><a>2021.2 v2版本</a></li> <li><a>2022.7 v3版本</a></li> <li><a>2022.12-至今 v4版本</a></li> <li>vue-cli官方推荐使用 <a><code>create-vue</code></a> 来创建基于 <a>Vite</a> 的新项目</li> </ul> <h2>Vite基本概念</h2> <p>Vite和webpack一样都是构建工具。</p> <p>使用webpack打包大型的前端应用,启动开发服务器时webpack必须优先抓取并分析 <strong>整个应用的依赖</strong> ,由于大型项目包含大量模块,可能需要很长时间(甚至是几分钟)才能启动dev server,文件修改后的HMR也可能长达几时秒到一分钟,极大影响开发者的开发效率。</p> <p>Vite就是为了解决这个问题而诞生。</p> <p><strong>目前Vite主要由两部分组成:</strong></p> <ul> <li><strong>一个开发服务器</strong>,服务于开发环境,它基于 <a>原生 ES 模块</a> 和ESBuild,提供了 <a>丰富的内建功能</a>:如速度很快的 <a>模块热更新(HMR)</a>。其原理是利用浏览器去解析 imports,在服务器端按需编译返回,完全跳过了打包这个概念,服务器随起随用。</li> <li><strong>一套构建指令</strong>,用于生产环境打包,使用 <a>Rollup</a> 打包代码,并且它是预配置的,可输出用于生产环境的高度优化过的静态资源。 &lt;!-- <img src="image/Vite/1685668545904.png" alt="1685668545904" /> --&gt;</li> </ul> <h2>上手</h2> <p>使用<code>npm create vite@latest</code>命令初始化一个Vite项目</p> <p>有六种框架可选:<img src="/images/picgo/20230702235218.png" alt="" /></p> <p>选择vue框架,初始化后的目录结构是这样: <img src="/images/picgo/20230702235353.png" alt="" /></p> <p>相较于过去基于webpack的vue项目,有2个不同之处。</p> <p>1是index.html从/public移出到了根目录,这是因为对于Vite项目而言,index.html就是一切依赖的入口。</p> <p>2是Vite.config.ts 替代了 vue.config.js。</p> <p>Vite其他命令如下:</p> <ul> <li><code>Vite</code>启动开发服务器</li> <li><code>Vite build</code> 打包</li> <li><code>Vite optimize</code> 预构建依赖</li> <li><code>Vite preview</code> 本地预览打包产物</li> </ul> <p>本地启动项目后,可以看到index.html中以原生ES模块的方式,引入了main.js和其他依赖:</p> <p><img src="/images/picgo/20230702235634.png" alt="" /></p> <p>对于浏览器对.vue文件的HTTP请求,通过设置<code>Content-Type: application/javascript</code>,被处理成了浏览器可识别的js逻辑,并且js中用的也是原生ES模块的导入导出语法: <img src="/images/picgo/20230703000005.png" alt="" /></p> <p>本地打包后,启动preview服务器查看效果: <img src="/images/picgo/20230703000124.png" alt="" /></p> <h2>学Vite的几个前置条件</h2> <h3>1 了解ES Module</h3> <p>Vite基于<a>原生ESM</a>实现。</p> <p>现在js程序越来越复杂,因此近年来Nodejs都支持<strong>将 JavaScript 程序拆分为可按需导入的单独模块</strong>的机制,例如,<a>CommonJS</a> 和基于 <a>AMD</a> 的其他模块系统 如 <a>RequireJS</a>、 <a>Webpack</a> 、 <a>Babel</a>。</p> <p>但是这类模块系统服务器启动缓慢,经历一条很长的编译打包链条,从入口开始需要逐步经历语法解析、依赖收集、代码转译、打包合并、代码优化,最终将高版本的、离散的源码编译打包成低版本、高兼容性的产物代码,流程如下图:</p> <p><img src="/images/picgo/20230703000211.png" alt="" /></p> <p>最新的<strong>浏览器开始原生支持模块功能</strong>、浏览器支持es语法中的import和export语法</p> <p>可以通过 <code>&lt;script type="module" src="xx"&gt; 引入模块</code>。</p> <p>浏览器通过HTTP请求的方式,按需加载每一个被引入的模块,在启动开发服务器时,可以达到免打包、随开随用的效果,流程如下:</p> <p><img src="/images/picgo/20230703000248.png" alt="" /></p> <h3>2 了解ESBuild</h3> <p>那么Vite为什么不直接使用浏览器原生esm,还要用ESBuild呢?</p> <p>因为浏览器原生ESM功能有限,例如:只支持用<strong>完整的相对路径/绝对路径</strong>引入模块,不支持引入裸模块(以模块名的方式从node_modules下引入模块),会报错,举个例子引入lodash的报错:</p> <p><img src="/images/picgo/20230703000821.png" alt="" /></p> <p><img src="/images/picgo/20230703000715.png" alt="" /></p> <p>为什么浏览器不支持自动从node_modules下寻找并引入模块?如果某个模块依赖项很多,而每个模块又会产生一次HTTP请求,会导致严重的HTTP请求并发问题。</p> <p>而 <a>ESBuild</a> 会对依赖进行 <a>预构建</a>,对原生的ESM功能进行了扩展。</p> <p>另外,ESBuild 使用 Go 编写,比以 JavaScript 编写的打包器预构建依赖快 10-100 倍。(<a>文章 - ESBuild 为什么那么快</a>)</p> <h3>3 了解Rollup</h3> <p>对于生产环境,Vite会使用rollup进行生产环境的构建和打包。</p> <p>ESBuild 也支持打包,为何不用 ESBuild 打包?</p> <p>目前Vite团队认为 Rollup 提供了更好的<strong>性能与灵活性</strong>方面的权衡:Vite 目前的插件 API 与使用 <code>ESBuild</code> 作为打包器并不兼容。尽管 <code>ESBuild</code> 速度更快,但 Vite 采用了 Rollup 灵活的插件 API 和基础建设,这对 Vite 在生态中的成功起到了重要作用。</p> <p>(即便如此,<code>ESBuild</code> 在过去几年有了很大进展,Vite不排除在未来使用 <code>ESBuild</code> 进行生产构建的可能性。)</p> <p>近年来对于构建工具的选择,主流的经验是:</p> <p><img src="/images/picgo/20230703000942.png" alt="" /></p> <p>关于Webpack和Rollup的区别,推荐阅读一篇2017年的Medium文章:<a>Webpack and Rollup: the same but different</a>。</p> <p>相较于Rollup,Webpack有着丰富庞大的生态系统、大量的contributors和sponsors,rollup的生态并没有webpack工具强大。</p> <p>但Rollup是React, Vue, Ember, Preact, D3, Three.js, Moment等众多知名开源库选择的构建工具,rollup相对webpack更轻量,其构建的代码并不会像webpack一样被注入大量的webpack内部结构,而是尽量的精简保持代码原有的状态。它同样支持tree-shaking、依赖解析等能力。</p> <h2>Dev Server 功能 &amp; 原理</h2> <p>我在本地进行了实际对比:</p> <p>使用vue cli创建一个webpack+vue的空项目,启动devserver时间在10s左右;</p> <p>使用Vite创建一个Vite+vue的空项目,启动dev server的时间在1s-2s左右。</p> <p>Vite本地启动比webpack快很多,那么Vite启动本地服务器的原理是什么?</p> <p><code>Vite</code> 会将应用代码分为 <strong>依赖</strong> 和 <strong>源码</strong> 两类,对不同的模块进行<strong>按需编译。</strong></p> <h3>1 依赖预构建</h3> <ul> <li>对于依赖:当首次启动 <code>dev server</code> 时,Vite 会在本地加载站点之前<strong>预构建</strong>依赖。</li> <li>默认情况下,预构建是自动且透明地完成的,可以在Vite.config.js配置中禁用。</li> <li>Vite 底层使用 <code>ESBuild</code> 预构建依赖( <code>Esbuild</code> 使用 Go 编写,比以 JavaScript 编写的打包器预构建依赖快 10-100 倍)。</li> </ul> <h4>兼容导出格式</h4> <p>为了兼容不同的第三方依赖包的不同的导出格式(例如浏览器不支持的commonjs),ESBuild会将所有依赖包转换为浏览器支持的esm格式,然后放到当前目录 <code>node_modules/.Vite/deps</code>下。</p> <h4>多包传输优化</h4> <p>为了解决浏览器网络多包传输的性能问题,ESBuild会分析依赖链,将多模块的import集成到一个模块中去,减少 http 请求数。例如引入lodash-es包的合并前后对比:</p> <p><img src="/images/picgo/20230703002715.png" alt="" /></p> <h4>补齐import路径</h4> <p>浏览器只支持完整相对路径/绝对路径形式引入模块,对于裸模块、省略了文件后缀名的模块,预构建阶段会对路径进行补齐和重写。例如引入lodash包:</p> <pre><code>import _ from "lodash"; </code></pre> <p><img src="/images/picgo/20230703002852.png" alt="" /></p> <h4>强缓存</h4> <p>依赖包的HTTP请求会被Vite设置为 <code>Cache-Control: max-age=31536000,immutable</code> 进行<strong>强缓存。</strong></p> <p><img src="/images/picgo/20230703002952.png" alt="" /></p> <h3>2 源码转换</h3> <p>对于源码:JSX、CSS 或者 Vue SFC等,Vite会对其进行转换,以 <a>原生 ESM</a> 方式提供源码。</p> <h4>Vite对vue文件的处理</h4> <p>对于.vue文件:Vite会使用vue-compiler将其转为js,通过设置Content-Type:text/javascript,让浏览器将.vue文件识别为js文件并解析。<img src="/images/picgo/20230703000005.png" alt="" /></p> <h4>Vite对css的处理</h4> <p>对于css文件:Vite会将浏览器.css文件的HTTP请求设置Content-Type:text/javascript,然后把css文件的内容替换为一段js代码,这段js代码的逻辑就是将对应的css代码作为 <code>&lt;style&gt;</code>标签插入到html文件中,并且支持css的热更新功能。<img src="/images/picgo/20230703003133.png" alt="" /></p> <p>CSS代码分割:Vite 会自动地将一个异步 chunk 模块中使用到的 CSS 代码抽取出来并为其生成一个单独的文件(而不是将所有的 CSS 抽取到一个文件中),这个 CSS 文件将在该异步 chunk 加载完成时自动通过一个 <code>&lt;link&gt;</code> 标签载入,该异步 chunk 会保证只在 CSS 加载完毕后再执行,避免发生 <a>FOUC</a> 。</p> <h4>Vite对css模块化的处理</h4> <p>将所有.module.css后缀的文件视为模块化css,例子:</p> <pre><code>Foo.module.css文件: .footer{ width: 100px; height: 100px; background-color: rosybrown; } Bar.module.css文件: .footer{ width: 100px; height: 100px; background-color: rosybrown; } </code></pre> <p>对其css代码中的所有类名进行 <strong>哈希转换</strong>,创建<strong>映射对象</strong>:</p> <pre><code>&lt;script setup&gt; import css from "@/styles/modules/Bar.module.css"; console.log('Bar.module.css映射对象', css); &lt;/script&gt; </code></pre> <p>&lt;!-- <img src="image/Vite/1686193428140.png" alt="1686193428140" /> --&gt;</p> <p>然后将原始css文件中的代码抹除,替换成一段JS脚本,这段脚本会将上述的映射对象 默认导出:</p> <p>&lt;!-- <img src="image/Vite/1686193624774.png" alt="1686193624774" /> --&gt;</p> <p>这段脚本的逻辑是将哈希转换后的css代码,作为 <code>&lt;style&gt;</code>标签插入html中:</p> <p>&lt;!-- <img src="image/Vite/1686193719848.png" alt="1686193719848" /> --&gt;</p> <h4>Vite对less和scss的处理</h4> <p>Vite 也同时提供了对 <code>.scss</code>, <code>.sass</code>, <code>.less</code>, <code>.styl</code> 和 <code>.stylus</code> 文件的内置支持。没有必要为它们安装特定的 Vite 插件,但必须安装相应的预处理器依赖:</p> <pre><code># .scss and .sass npm add -D sass # .less npm add -D less # .styl and .stylus npm add -D stylus </code></pre> <p>Vite调用各个css预处理器将.scss .less转换为css代码后,对css代码的处理同上述【Vite对css的处理】</p> <h4>协商缓存</h4> <ul> <li>源码的HTTP请求会被Vite设置为 <code>304 Not Modified</code> 进行<strong>协商缓存</strong>。</li> </ul> <h3>3 静态资源处理</h3> <h4>尽量遵循 ESM 方式提供静态资源</h4> <p>Vite 尽量避免直接处理静态资源,而是选择遵循 ESM 方式提供服务,例如引入静态资源图片 <code>import img from 'xxx.png'</code> ,执行后会返回解析后的 URL,供浏览器直接请求:</p> <ul> <li>常见的图像、媒体和字体文件类型会被自动检测为资源,可以通过<a><code>assetsInclude</code> 选项</a>配置文件后缀名。</li> <li>代码中引入的静态资源,会返回解析后的公共路径:</li> </ul> <pre><code>import imgUrl from './img.png' document.getElementById('hero-img').src = imgUrl </code></pre> <ul> <li> <p>Vue SFC <code>&lt;template&gt;</code>中的资源引用,会被自动转换为import语句。</p> </li> <li> <p>资源体积小于 <a><code>assetsInlineLimit</code> 选项值</a> (默认4KB)会被转换为内联的 base64 data URL。</p> </li> <li> <p>在 CSS 中引用的 <code>url()</code>,也是同样的处理方式。</p> </li> <li> <p>如果需要显式引入一个资源的url,可以加 <code>?url</code>后缀:</p> <pre><code>import workletURL from 'extra-scalloped-border/worklet.js?url' CSS.paintWorklet.addModule(workletURL) </code></pre> </li> <li> <p>如果需要将资源引入为字符串,可以使用 <code>?raw</code> 后缀:</p> <pre><code>import shaderString from './shader.glsl?raw' </code></pre> </li> <li> <p>public目录:对于不会被源码引入、保持原文件名不加hash的文件,可以放在项目根目录下public目录中,开发时必须<strong>直接通过“/”根路径访问</strong>,打包时也会被完整复制到根目录下。</p> </li> <li> <p>支持JSON的具名导入(解构导入)</p> </li> </ul> <h4>使用 <code>new URL(url, import.meta.url)</code>:</h4> <p><a>import.meta.url</a> 是一个 现代浏览器支持的 ESM 的原生功能,会暴露当前模块的 URL。将它与原生的 <a>URL 构造器</a> 组合使用,在一个 JavaScript 模块中,通过相对路径我们就能得到一个被完整解析的静态资源 URL:</p> <pre><code>const imgUrl = new URL('./img.png', import.meta.url).href document.getElementById('hero-img').src = imgUrl </code></pre> <p>在dev server使用上述方法,可以借助浏览器的原生能力,而不需要Vite做处理。</p> <p>对于生产构建时,Vite 会进行必要的转换保证 URL 在打包和资源哈希后仍指向正确的地址。</p> <h2>Vite打包功能</h2> <h3>打包入口</h3> <p>默认情况下,以 <code>&lt;root&gt;/index.html</code> 作为打包入口,并生成能够静态部署的应用程序包。</p> <p>MPA多页应用:在 <code>build.rollupOptions.input</code>数组中,定义多个html入口即可。</p> <h3>hash</h3> <p>打包后的资源文件名有hash,与文件内容一一对应(文件内容更新才会更新hash值,便于控制浏览器缓存)。</p> <h3>浏览器兼容性</h3> <p>Vite不支持低版本浏览器:</p> <ul> <li>默认情况下 Vite 只处理语法转译,且 <strong>默认不包含任何 polyfill</strong> 。</li> <li>默认情况下,Vite 的目标是 <a>支持原生 ESM</a>、<a>支持原生 ESM 动态导入</a> 和 <a>import.meta</a> 的浏览器:Chrome &gt;=87,Firefox &gt;=78,Safari &gt;=14,Edge &gt;=88</li> <li>可以通过 build.target 配置项指定构建目标,最低支持 es2015。</li> <li>可以通过插件 <a>@Vitejs/plugin-legacy</a> 支持传统浏览器,最低支持到IE 11</li> </ul> <h3>rollup配置</h3> <p>Vite基于Rollup工具打包,可以通过 <code>build.rollupOptions</code> 直接调整底层的 <a>Rollup 选项</a>。</p> <h3>base路径</h3> <p>如果需要 在嵌套的服务器路径下部署项目,可以指定 <a><code>base</code> 配置项</a>。</p> <h3>build watch</h3> <p>可以使用 <code>Vite build --watch</code> 来启用 rollup 的监听器,文件变化时重新构建。</p> <h3>预加载优化</h3> <p>Vite 会为入口 chunk 和它们在打包出的 HTML 中的直接引入自动生成 <code>&lt;link rel="modulepreload"&gt;</code> 指令,实现预加载优化。</p> <h2>Vite配置文件</h2> <h3>配置文件的语法提示</h3> <p>Vite的配置文件是 <code>Vite.config.js</code>,可以直接写成:</p> <pre><code>export default {} </code></pre> <p>但是,可以利用 <code>defineConfig</code>获得语法提示和类型约束:</p> <pre><code>import { defineConfig } from "Vite"; export default defineConfig({}) </code></pre> <p>也可以利用IDE和jsdoc支持,来获得语法提示</p> <pre><code>/** @type {import('vite').UserConfig} */ export default { // ... } </code></pre> <h3>不同环境配置</h3> <p>类似于webpack.dev.config、webpack.prod.config</p> <p>Vite在配置文件提供环境区分:</p> <pre><code>export default defineConfig(({ command, mode, ssrBuild }) =&gt; { if (command === 'serve') { return { // dev 独有配置 } } else { // command === 'build' return { // build 独有配置 } } }) </code></pre> <p>可以采用更具有扩展性的方式:</p> <pre><code>import { defineConfig } from "Vite"; import ViteBaseConfig from "./Vite.base.config"; import ViteDevConfig from "./Vite.dev.config"; import ViteProdConfig from "./Vite.prod.config"; // 策略模式 const envResolver = { serve: ()=&gt;Object.assign({}, ViteBaseConfig, ViteDevConfig), build: ()=&gt;Object.assign({}, ViteBaseConfig, ViteProdConfig) } export default defineConfig(({ command, mode, ssrBuild }) =&gt; { return envResolver[command](); }); </code></pre> <h3>环境变量</h3> <p>Vite内置了<a>dotenv</a>库:支持读取 <code>.env</code>文件。</p> <pre><code>.env # 所有情况下都会加载 .env.local # 所有情况下都会加载,但会被 git 忽略 .env.[mode] # 只在指定模式下加载 .env.[mode].local # 只在指定模式下加载,但会被 git 忽略 </code></pre> <p>Vite会解析<code>.env</code>文件中的所有环境变量注入到node端 <code>process.env</code>对象中; 解析其中<code>Vite_</code> 前缀的环境变量,注入到客户端的 <code>import.meta.env</code>对象中。</p> <p>但是 Vite.config.js执行时,默认是不加载 <code>.env</code> 文件的,因为这些文件需要在执行完 Vite 配置后才能确定加载哪一个,举个例子:Vite.config.js中的 <code>envDir</code> 选项会影响到.env的加载。</p> <p>如果需要提前在Vite.config.js中获取环境变量,可以使用 Vite 的 <a>loadEnv</a> 函数来加载指定的 <code>.env</code> 文件:</p> <pre><code>export default defineConfig(({ command, mode, ssrBuild }) =&gt; { // 根据mode加载.env文件,默认是.env.development和.env.production,可以在Vite命令后通过--mode配置 // process.cwd()指定env文件目录是当前执行node脚本所在的目录 // 第三个参数是变量前缀,设置为''会加载所有环境变量,而不管是否有 `Vite_` 前缀。 const env = loadEnv(mode, process.cwd(), '') console.log(env); }); </code></pre> <h3>路径别名</h3> <pre><code>resolve:{ alias: { '@': path.resolve(__dirname,'../', 'src') } } </code></pre> <p>当使用文件系统路径的别名时,要始终使用绝对路径。相对路径的别名值会原封不动地被使用,因此无法被正常解析。</p> <h3>css配置</h3> <p><a>配置项 css.modules </a>定义了CSS modules 的行为,会被传递给 <a>postcss-modules</a>。</p> <ul> <li><code>css.modules.localsConvention</code>:配置了对css模块类名转换后,映射对象中key的写法,camelCase驼峰,dashes中划线</li> </ul> <p><a>配置项目 css.preprocessorOptions </a>指定了传递给 CSS 预处理器的选项。文件扩展名用作选项的键。每个预处理器支持的选项可以在它们各自的文档中找到:</p> <ul> <li><code>sass</code>/<code>scss</code> - <a>选项</a>。</li> <li><code>less</code> - <a>选项</a>。</li> <li><code>styl</code>/<code>stylus</code> - 仅支持 <a><code>define</code></a>,可以作为对象传递。</li> </ul> <p><a>配置项 css.postcss </a>与postcss.config.js文件的起同等作用。</p> <h3>proxy代理配置</h3> <p>通过<code>server.proxy</code>为开发服务器配置自定义代理规则。</p> <p>相关配置内容继承自 <a>http-proxy</a>。</p> <h2>Vite插件</h2> <h3>Vite插件作用是什么</h3> <p>Vite在不同的生命周期中取调用不同的插件,以达到不同的目的。</p> <h3>使用插件</h3> <p>可选的插件:<a>官方插件</a>、<a>社区插件</a>、<a>部分兼容Vite的rollup插件</a></p> <p>例子:引入并使用插件 <a>Vite-aliases</a> (自动根据项目目录生成 路径别名配置)</p> <p><code>npm i Vite-aliases -D</code></p> <pre><code>// Vite.config.js import { ViteAliases } from 'Vite-aliases' export default { plugins: [ ViteAliases() ] }; </code></pre> <p>假如项目目录是:</p> <pre><code>src assets components pages store utils </code></pre> <p>会自动生成如下配置:</p> <pre><code>[ { find: '@', replacement: '${your_project_path}/src' }, { find: '@assets', replacement: '${your_project_path}/src/assets' }, { find: '@components', replacement: '${your_project_path}/src/components' }, { find: '@pages', replacement: '${your_project_path}/src/pages' }, { find: '@store', replacement: '${your_project_path}/src/store' }, { find: '@utils', replacement: '${your_project_path}/src/utils' }, ] </code></pre> <h3>插件原理 &amp; 插件开发</h3> <p>插件开发文档: https://cn.Vitejs.dev/guide/api-plugin.html</p> <h4>1 插件代码结构</h4> <p>Vite插件应该是一个“返回实际插件对象的工厂函数”:</p> <pre><code>export default function myPlugin(config) { return { name: 'xx', transform(src, id) { // 此处transform是一个rollup和Vite通用的钩子 }, } } </code></pre> <h4>2 插件钩子</h4> <p>开发插件最核心的逻辑就是搞清楚:我的插件应该在哪些Vite生命周期做哪些事情。</p> <p>因此要先了解Vite提供了哪些生命周期钩子:</p> <ul> <li> <p>通用钩子:在开发中,Vite 开发服务器会创建一个插件容器来调用 <a>Rollup 构建钩子</a>,与 Rollup 如出一辙:</p> <ul> <li>在dev server启动时被调用的钩子: <ul> <li><a><code>options</code></a> :<code>(options: InputOptions) =&gt;InputOptions | null</code>。构建阶段第一个钩子,替换或操作传递给 <code>rollup</code> 的选项对象,在 Rollup 配置完成之前运行。</li> <li><a><code>buildStart</code></a> :<code>(options: InputOptions) =&gt;void</code>。在options后被调用,可以读取到最终options值,被 rollup.rollup 方法调用,如果仅需要读取options推荐使用这个钩子。</li> </ul> </li> <li>在每个模块请求时被调用的钩子: <ul> <li><a><code>resolveId</code></a> :定义自定义解析器,可以用于定位第三方依赖项等。</li> <li><a><code>load</code></a>:定义自定义加载器。</li> <li><a><code>transform</code></a>:用于转换单个模块。类似于webpack中的loader,在Vite源码有使用这个钩子转译vue文件以及template模板。</li> </ul> </li> </ul> </li> <li> <p>Vite 独有钩子:服务于特定的 Vite 目标。这些钩子会被 Rollup 忽略。</p> <ul> <li>config:在解析 Vite 配置前调用。接收原始用户配置,可以返回一个将被deepMerge到现有配置中的部分配置对象。</li> <li>configResolved:在解析 Vite 配置后调用。使用这个钩子读取和存储最终解析的配置。</li> <li>configureServer:用于配置dev server的钩子,最常见的用例是给dev server添加自定义中间件,会在内部中间件被安装前调用。中间件API <code>server.middleware.use((req,res,next)=&gt;{})</code>。</li> <li>configurePreviewServer:用于预览服务器。用上一个用法类似。</li> <li>transformIndexHtml:转换 <code>index.html</code> 的专用钩子。钩子接收当前的 HTML 字符串和转换上下文 <code>ctx</code>。<code>ctx</code>在开发期间暴露<a><code>ViteDevServer</code></a>实例,在构建期间暴露 Rollup 输出的包。</li> <li>handleHotUpdate:自定义 HMR 行为。</li> </ul> </li> </ul> <h4>3 插件执行顺序</h4> <p>可以指定插件的enforce属性,来调整插件的执行顺序,enforce=pre/post。</p> <p>所有插件的执行顺序如下:</p> <ul> <li>Alias</li> <li>带有 <code>enforce: 'pre'</code> 的用户插件</li> <li>Vite 核心插件</li> <li>没有 enforce 值的用户插件</li> <li>Vite 构建用的插件</li> <li>带有 <code>enforce: 'post'</code> 的用户插件</li> <li>Vite 后置构建插件(最小化,manifest,报告)</li> </ul> <h4>4 区分mode执行插件</h4> <p>默认情况下插件在开发(serve)和构建(build)模式中都会调用。</p> <p>如果插件只需要在预览或构建期间有条件地应用,使用 <code>apply</code> 属性指明它们仅在 <code>'build'</code> 或 <code>'serve'</code> 模式时调用</p> <pre><code>function myPlugin() { return { name: 'build-only', apply: 'build' // 或 'serve' } } </code></pre> <h2>Vite 对 TS的支持</h2> <ul> <li>Vite 天然支持引入 <code>.ts</code> 文件。</li> <li>Vite 使用 <a>ESBuild</a> 将 TypeScript 转译到 JavaScript,约是 <code>tsc</code> 速度的 20~30 倍。</li> <li>Vite只负责转译ts代码,不负责类型检查。(Vite默认类型检查已经被你的 IDE 或构建过程处理了。)(原因是类型检查会影响Vite的速度:转译在每个文件的基础上进行,与 Vite 的按需编译模式完全吻合。相比之下,类型检查需要了解整个模块图。把类型检查塞进 Vite 的转换管道,将不可避免地损害 Vite 的速度优势。)</li> </ul> <p>Vite不负责类型检查,怎么获得更多类型检查提示?</p> <ul> <li>开发时,在项目中使用ts,并添加tsconfig.json配置,就可以依赖IDE自带的ts检查。</li> <li>开发时,可以在一个单独的进程中运行 <code>tsc --noEmit --watch</code>,可以获得更多IDE提示。</li> <li>打包时,可以这样运行 Vite 构建命令: <code>tsc --noEmit &amp;&amp; Vite build</code>,如果检查到类型错误,会报错并停止打包。</li> <li>也可以使用<a>Vite-plugin-checker</a>插件,会将ts类型错误抛到浏览器中。</li> </ul> <h2>Vite性能优化</h2> <h3>分包策略</h3> <p>把一些不会经常更新的依赖,单独打包:通过配置 <code>build.rollupOptions.output.manualChunks</code> 来自定义 chunk 分割策略:</p> <pre><code>({ manualChunks: (id) =&gt; { if (id.includes("node_modules")) { return "vendor"; } }, }); </code></pre> <p>或者直接使用Vite4中内置的 <code>splitVendorChunkPlugin</code> 插件,会自动拆分vender chunk:</p> <pre><code>// Vite.config.js import { splitVendorChunkPlugin } from "vite"; export default defineConfig({ plugins: [splitVendorChunkPlugin()], }); </code></pre> <h3>gzip压缩</h3> <p>使用 <a>Vite-plugin-compression</a> 插件,打包后会生成静态资源的压缩文件,后缀是.gz,直接提供给浏览器去解压缩。由于消耗浏览器资源,只针对大的文件进行压缩;</p> <p>这种方式与nginx的gzip压缩区别在哪?nginx上的资源是以原始文件形式存在的,当返回给浏览器的时候再进行压缩,浏览器收到压缩文件再解压缩。是动态压缩,会消耗服务器资源。如果提前压缩好.gz文件,可以节省服务器压力。</p> <h3>动态导入</h3> <p>动态导入也是es原生支持的特性。</p> <p>例如使用动态导入引入一个异步组件4:</p> <pre><code>import { defineAsyncComponent } from "vue"; const Bar = defineAsyncComponent(() =&gt; import("@cmp/Bar/index.vue")); </code></pre> <p>打包后,Bar组件的代码会被单独打包为一个chunk,在使用到Bar组件时浏览器会按需加载这个chunk。</p> <h3>Glob导入</h3> <p>Vite 支持使用特殊的 <code>import.meta.glob</code> 函数从文件系统导入多个模块:<code>const modules =import.meta.glob('./dir/*.js')</code>。</p> <p>匹配到的文件默认是懒加载的,通过动态导入实现,并会在构建时分离为独立的 chunk。</p> <h3>避免单屏拥有过度数目的依赖</h3> <p>举个例子:lodash-es是lodash为了支持构建工具tree-shaking而诞生的包,包中导出了600多个模块,如果我们在vite项目中不小心写了以下代码:</p> <p><code>import * as lodash from 'lodash-es';</code></p> <p>这将会导致dev server模式下,页面出现严重卡顿,因为浏览器会将这600多个子模块全部作为HTTP请求,进而导致了严重的HTTP请求并发问题。</p> <p><img src="/images/picgo/vite.gif" alt="" /></p> <p>如上动态演示,这些请求都会阻塞DOM的渲染,降低开发效率。</p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/vite/#post-comment/</comments>
</item>
<item>
<title>长安的荔枝:古装版社畜求生记</title>
<link>https://www.scarsu.com/chang_an/</link>
<guid isPermaLink="true">https://www.scarsu.com/chang_an/</guid>
<description>见微知著,从小人物的视角体味历史与政治</description>
<pubDate>Mon, 12 Jun 2023 00:00:00 GMT</pubDate>
<content:encoded><blockquote> <p>一骑红尘妃子笑,有人知是荔枝来。</p> </blockquote> <p><img src="/images/picgo/lizhi.jpg" alt="封面" /></p> <p>《长安的荔枝》是马伯庸写的小说,他以大唐天宝14年为历史背景,以一位长安九品小吏李善德为主角,叙述了他完成从岭南运送新鲜荔枝到长安这一任务的故事。</p> <p>故事的开端,李善德 受领导设计,接手了这个“无法完成的”差事:要在六月一日杨贵妃生日之前,从岭南运送新鲜荔枝到长安。而荔枝保鲜期只有三天、从岭南到长安五千里路程。</p> <p>他恐惧、绝望到想与妻子和离 交代后事,遂又接受了两位好友的安慰和出谋划策,决心奔赴岭南,放手一搏。</p> <p>经过种种努力、多次试验和数据分析,他终于找到了保鲜的最佳方法、最优的运送路径,在自己的一次亲身试验中,成功将新鲜荔枝从岭南送到长安,就在他沉浸于喜悦之中、准备安排最终运送细节时,他又被不同部门来回踢皮球、差点被人抢功,经人引导下,投靠上了卫国公杨国忠,才得到各部门的配合。在最终的运送过程中,他又遭遇了几次意想不到的危机、感受到了身不由己的无奈、失去朋友信任的悲痛、对皇权贵势下百姓苦难的愤懑。</p> <p>整个故事读下来,有几处令我印象深刻的点。</p> <ol> <li>不要随意接手自己不清楚的任务、不要签署未确认过的文件、不要在不清醒状态做决策。荔枝使的任务已经被多个部门踢来踢去踢到了李善德的部门,由于有一天他请假不在,于是领导和同事统一意见踢给他,在酒局上珍肴美酒下肚、几句奉承话入耳,李善德便接下了这个任务。</li> <li>学会“和光同尘”。李善德在岭南研究出运送方法后,险些被岭南官员杀害,原因就是这个任务以往都没有人完成,一旦李善德完成,其他人就有了“办事不力”的罪名。如果能让出部分功劳,“归功于xx通力配合”,情况就能转变。</li> <li>学会“借势”,规矩是约束弱者的。李善德照规矩办事,却处处碰壁,而靠着卫国公杨国忠的银牌,却畅通无阻。强者制造规则、智者利用规则、弱者遵守规则。</li> <li>不要随便许诺。胡商苏谅在李善德多次试验中提供了大量资金帮助,李善德答应了让苏的商队接下运送荔枝的差事,不曾想这根本不由李善德说了算,于是只能毁诺于苏谅,丢失了朋友、丢失了信任。</li> <li>有时候小人物只是大人物博弈的棋子。李善德以为,是皇帝为取悦杨贵妃才要岭南的荔枝,而自己这个荔枝使是任务完成与否的核心人物,直到最后才发现,整个事件不过是高力士为了打压鱼朝恩,设下的局。</li> <li>不要小看政治背后的复杂和黑暗。李善德以为,皇帝和朝廷会承担这几斤荔枝带来的巨额费用,没想到,最终的人力、物力竟然来源于对百姓提高税赋、增加徭役,甚至其中还有差价不知进了谁的口袋;为了荔枝保鲜,需要砍下荔枝树干运送,荒废一颗荔枝树,最初要的十斤荔枝只需要砍一棵树,但是为了保证层层运送不出差错、无人担责,最终要砍下10棵树,这其中10倍的损耗令人唏嘘。</li> </ol> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/chang_an/#post-comment/</comments>
</item>
<item>
<title>极简学习法:精准输入-深度消化-多元输出</title>
<link>https://www.scarsu.com/minimal_learning_method/</link>
<guid isPermaLink="true">https://www.scarsu.com/minimal_learning_method/</guid>
<description>学习一切知识,都可以遵循【精准输入-深度消化-多元输出】这三个步骤</description>
<pubDate>Sun, 11 Jun 2023 00:00:00 GMT</pubDate>
<content:encoded><h2>简介</h2> <ul> <li>书名:《极简学习法》</li> <li>作者:廖恒</li> <li>出版时间:2022-4-10</li> <li>ISBN:9787559659385</li> <li>豆瓣链接:https://book.douban.com/subject/35856498/</li> <li>豆瓣评分:7.3⭐</li> </ul> <p><img src="/images/picgo/minimal_learning_method.png" alt="" /></p> <h2>优势</h2> <ul> <li>极简闭环:学习一切知识,都可以遵循【精准输入-深度消化-多元输出】这三个步骤</li> <li>追求精准:从目标倒推输入内容</li> <li>直击本质:选择最本质的东西去学习。</li> <li>举一反三,知识迁移</li> <li>麦肯锡的“MECE”原则,英文全称是 Mutually Exclusive Collectively Exhaustive,中文意思是“相互独立,完全穷尽”。也就是说,对于一个重大的议题,要做到不重叠、不遗漏的分类。这是一种非常重要的方法论</li> </ul> <h2>1 精准输入</h2> <ul> <li><strong>倒推</strong>思维,学习“决定结果的知识”。确定自己的目标是什么,推演实现目标的过程,制定可实现的计划 <ul> <li>eg TED 演讲者分享了一个方法:在年初写"年终总结":今年我完成了 xx 目标,我完成这个目标做的具体步骤,如果写不出来步骤,说明这是无法实现的计划。</li> <li>SMART 法则: <ul> <li>Specific 具体的</li> <li>Measurable 可量化的</li> <li>Attainable 可达到的</li> <li>Relevant 有相关性的(目标之间)</li> <li>Time-bound 有时限的</li> </ul> </li> </ul> </li> <li>紧盯目标,拒绝借口 <ul> <li>选适合自己的学习材料</li> <li>考试学习:把握考纲、教材,将其所有知识点串起来形成知识体系,最好自己可以画出思维导图</li> <li>从一而终,长期、系统性、持续性学习</li> </ul> </li> <li>追求本质:学<strong>基石</strong>之作 <ul> <li>财经作家欧盛在一篇文章中谈道:“任何复杂事物的背后,都有简洁的可以用一句话或者几句话说明的规律。这些规律,便是<strong>本质</strong>。”</li> <li>古希腊哲学家亚里士多德曾说:“在每个系统探索中存在<strong>第一性原理</strong>。第一性原理是基本的命题和假设,不能被省略和删除,也不能被违反。”</li> <li>牛顿只用了三大定律,就解释了日月星辰的旋转、潮汐涨落现象以及各类力学现象;欧几里得只用了几条定理,就解释了万千形状的组合。</li> <li>学基石之作:比如, <ul> <li>你要学经济学,就可以直接看曼昆的《经济学原理》;</li> <li>你要学营销,就可以看“营销教父”菲利普·科特勒的《营销管理》;</li> <li>你要学习管理,最好先看管理学泰斗彼得·德鲁克的《卓有成效的管理者》。</li> </ul> </li> <li>还有一些基石之作,是某一篇<strong>开创这一领域的论文</strong>,例如,“信息论之父”香农在 1948 年 10 月发表于《贝尔系统技术杂志》上的论文:“A Mathematical Theory of Communication”(《通信的数学理论》),就是现代信息论的开端,自此开创了信息论这门伟大的学科。即使几十年过去了,信息论这一领域的研究,核心还是基于他在这篇论文中提出的理论进行展开的。</li> </ul> </li> <li>新知输入,做好"夹心饼":当你学完后,要记得及时复习,这样效果才会更佳,一方面是消灭“假明白”,另一方面是防止遗忘,加深理解。</li> </ul> <h2>2 深度消化,彻底搞懂知识</h2> <ul> <li>培养钝感力:正确处理学习的<strong>挫败感</strong> <ul> <li>日本作家渡边淳一有一本书叫《钝感力》,在这本书中,他提出了“钝感力”这个词。按照渡边淳一自己的解释,“钝感力”可直译为“迟钝的力量”,即<strong>从容面对生活中的挫折和伤痛,坚定地朝着自己的方向前进</strong>,它是“赢得美好生活的手段和智慧”。</li> <li>其实,成功的人几乎都有一个共同的特质,那就是拥有很强的“钝感力”。他们一方面很自信,相信自己可以;但更重要的另一面,他们不在意追求自己目标的路上遇到的困难和打击,哪怕头破血流也要死磕到底。这也印证了中国的一句俗话:“明知山有虎,偏向虎山行。"</li> <li>和“<strong>逃避式学习</strong>”恰恰相反,这是“<strong>不达目的不罢休式的学习</strong>”</li> </ul> </li> <li>无条件自信:破除“畏难情绪”,你就能学懂一切 <ul> <li>我接触的每一个顶级学霸原本都有自己的偏科,有些弱在语文,有些弱在数学,有的弱在其他科目。而且特别有意思的是,很多学霸对自己擅长的科目,并没有什么学习方法,可以说就是有天赋,不用怎么学就能拿高分。这就是他们的优势科目。所以,他们在学习的时候,会把大部分时间放在自己的弱势科目上,最终通过自己的各种办法,把弱势科目的成绩提上来。因此,顶级学霸通常是对自己的弱势科目有学习方法,因为这是他们花了心思,想了办法,最终把成绩提上来的科目。对这些科目的学习,他们是非常有心得的。所以,如果你想求得好的语文、英语的学习方法,你可以去向一个考上清华的理科生请教,他的方法,可能对你来说更有帮助。</li> <li><strong>学霸是哪科不行学哪科,学渣是哪科不行就哪科不学</strong>;学霸是瞄着偏科上,学渣是躲着偏科走。学习成绩差的人之所以不愿学偏科,是因为心中对偏科存有恐惧,从骨子里面接受了自己就是学不好某一科的现实,认定自己这辈子都不可能学好了。或者是想学好,但是觉得自己实在是差得太多,觉得完全无从下手,不可能赶上来了。人一旦被“畏难情绪”左右,就会干脆选择放弃。</li> </ul> </li> <li>精准自查,找出自己的知识漏洞 <ul> <li><strong>承认自己的错误</strong>,可谓是人最难做到的事之一。很多学习能力差的人,并不是真的学习能力差,而是他们不能正视自己学习过程中的问题,选择了掩耳盗铃,从而失去了真正学好的机会。</li> <li>方法 1.源头自查:用清单自测,列出要学的东西,看自己都学会了吗?</li> <li>方法 2.结果自查:按输出物自查,分析考卷、错题、作品</li> <li>方法 3.他人帮测:找高手帮助诊断,找学员尝试教授自己的知识</li> </ul> </li> <li>真正拿下,彻底学懂一切 <ul> <li>72 小时之内开始做 <ul> <li>理财畅销书《小狗钱钱》一书中,讲到了做事的“<strong>72 小时法则</strong>”。书中说:“<strong>当你决定做一件事情的时候,你必须在 72 小时之内真正开始行动,否则你很可能永远不会再做了。</strong>”</li> <li>把已知应用到未知,找知识连接:任何事物的学习都是相通的,当你自查出没有学明白的部分时,你就可以问自己,这部分知识和自己已经掌握的哪些知识有关,是否可以用到这部分知识的学习上。太阳底下没有新鲜事,万事万物都是有联系的,而且很多事物的底层逻辑是相通的,当你用已知的知识去理解新知识时,你就能很快找到突破口,后面的事情,就变得简单了。</li> <li>从哪里开始不重要,开始本身才重要</li> </ul> </li> </ul> </li> <li>深度专注,一次攻克一个难点 <ul> <li>1.要主动探索,而不是被动接受,明确自己的学习目的</li> <li>2.沉下心来,排除一切干扰:每个人在学习时的干扰源是不一样的。你要学会主动屏蔽这些干扰源。具体而言,我认为有“物理隔绝和琐事隔绝”这两种方法。 <ul> <li>物理隔绝:就是在<strong>时间和空间上与干扰源隔开</strong>。比如上文提到的那个喜欢在酒店的房间里工作的朋友,采用的就是空间隔绝;作家郝景芳早起写作采用的就是时间隔绝。</li> <li>琐事隔绝:这是被很多人忽略的,这里我专门提出来。当你要深度专注学习时,那些影响你精力的但又必须要做的琐事,要么让别人帮你做,要么你就干脆不管,比如你担心手机干扰你,干脆把手机放得离你远远的。</li> </ul> </li> <li>3.集中发力,一次解决一个问题:你专注去攻克一个问题时,你能学得深,想得多,学得透</li> </ul> </li> </ul> <h2>3 多元输出,学以致用</h2> <ul> <li>表达型输出,<strong>费曼学习法</strong>的三种应用 <ul> <li>讲给不懂得人听,试图教会他</li> <li>讲给自己听,先讲 录下来 自己再听</li> <li>写给自己看,比语言表述更缜密</li> </ul> </li> <li>解题型输出,高效<strong>刷题</strong>: <ul> <li>刷超出自己舒适区一些范围的题目,不要太难也不要太简单,</li> <li>专题刷题:复习知识-一刷-总结规律-二刷</li> </ul> </li> <li>考试输出,科学抢分 <ul> <li>尝试了解出题人思维:越是大型的考试 出题标准越严格 出题人必须严格按照这些标准来出题,看到一道题要知道这道题想考你什么知识点</li> <li>仔细分析参考答案的结构思路、得分点、学科术语,找出规律,总结答题模板</li> </ul> </li> <li>现实应用,<strong>33 原则</strong> <ul> <li>学会知识后,至少用 3 次</li> <li>抓住本质,举一反三:将知识迁移到其他的 3 个知识点</li> </ul> </li> <li><strong>刻意练习</strong> <ul> <li>刻意练习的三个关键要点:<strong>目标、突破、反馈</strong>:首先确定你想要通过练习达到的目标,在练习的过程中不断突破自己的能力边界,并有导师或教练对你的表现给予反馈,一步步精进,最终达成目标</li> <li>一、有目标的练习:首先要有明确的练习目标,就是你在练习时最终要达到什么样的结果。树立明确的目标,能有效地指导你的练习,也能帮你一步步拆解自己的练习步骤,让你的练习可以落地并最终实现。</li> <li>二、一点点突破能力边界:如果你想让自己在数学考试中考满分,就需要做一些高难度的试题,而不是一直待在舒适区,仅仅去做那些简单的数学题,那样你的数学水平永远都不会提高。</li> <li>三、练习过程中要有反馈。</li> <li>进入“突破 → 练习 → 反馈 → 改进 → 练习”这样的循环中,不断精进自己,最终做到对一件事情的精通。</li> </ul> </li> </ul> <h2>改变学习状态</h2> <ul> <li><strong>找到源动力</strong>,爱上学习:用自己的梦想倒推定计划、梦想可视化 随时提醒自己目标、自我奖励</li> <li>不要迷恋自律,<strong>养成习惯</strong>更重要:任何人的自律都有有限性,养成习惯 利用身体本能 让习惯变成生活的一部分 才更长久可靠。</li> <li><strong>拒绝拖延</strong>:谁都会拖延,不要加大心理压力;用一个小仪式开启任务;《少有人走的路》例子,先难后易</li> </ul> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/minimal_learning_method/#post-comment/</comments>
</item>
<item>
<title>高效能人士的七个习惯:以原则为核心</title>
<link>https://www.scarsu.com/7_habbits/</link>
<guid isPermaLink="true">https://www.scarsu.com/7_habbits/</guid>
<description>树立原则、改变思维、养成习惯;产出与产能的平衡;</description>
<pubDate>Sun, 28 May 2023 00:00:00 GMT</pubDate>
<content:encoded><h2>来源</h2> <ul> <li>书名:《高效能人士的七个习惯》 (The 7 Habits of Highly Effective People)</li> <li>作者:[美] 史蒂芬·柯维 (Stephen R. Covey)</li> <li>出版时间:2018-5-1</li> <li>ISBN:9787500695356</li> <li>豆瓣链接:https://book.douban.com/subject/5325618/</li> <li>豆瓣评分:8.6⭐</li> </ul> <p><img src="/images/picgo/20230528151746.png" alt="" /></p> <h2>本书的中心思想:以原则为中心从内而外造就自己</h2> <h3>先改变思维方式</h3> <p>我们的思维方式,无论正确与否,是我们的态度与行为的根本。</p> <p>要改变现状,首先要改变自己;要改变自己,先要改变我们对问题的看法。</p> <p>如果一个人无法改变自己的思想构造,就永远无法改变现实,也永远不可能取得进步。</p> <p>比起为改变态度和行为所做出的努力,正确的思维方式对于个人和人际关系效能的影响要大得多。</p> <p>**“思维转换(Paradigm Shift)”**一词由托马斯·库恩(Thomas Kuhn)在他的经典之作《科学革命的结构》(The Structure of Scientific Revolutions)一书中最先提出。库恩在书中阐释:</p> <blockquote> <p>科学研究的每一项重大突破,几乎都是首先打破传统,打破旧思维、旧模式才得以成功。</p> </blockquote> <h3>以原则为中心的思维方式</h3> <p>原则如灯塔,是不容动摇的自然法则。</p> <p>正如塞西尔·B.德米尔(Cecil B.deMille)在他执导的电影《十诫》(The Ten Commandments)中所揭示的:</p> <blockquote> <p>“我们不可能打破法则,只能在违背法则的时候让自己头破血流。”</p> </blockquote> <p>一个人的思维方式越符合原则或自然法则,越能正确而高效的生活。</p> <p>短期的方法与技巧只能治标不治本,应该只关注带来长期效应的自然法则和原则。</p> <h3>循序渐进是成长的自然法则</h3> <p>人的一生包含了许多成长和进步阶段,必须循序渐进。</p> <ul> <li>依赖期</li> <li>独立期</li> <li>互赖期</li> </ul> <p>自然的成长过程不容违背、忽略或缩短,那只会让你平添失望和挫败感。</p> <p>如果学生不肯发问,不肯暴露自己的无知,不肯让老师知道他的真正水平,那么绝对学不到东西,也就不能有长进。而且伪装实非长久之计,总有被拆穿的一天。</p> <p>承认自己的无知往往是求知的第一步。梭罗曾说:“如果我们时时忙着展现自己的知识,将何从忆起成长所需的无知?”</p> <h3>书名中的效能是指什么?</h3> <p>效能在于<strong>产出与产能的平衡</strong>。</p> <p>对于人来说,产能是人的健康、精神状态、思想水平,不能以损害健康为代价去一味的追求"产出",而是要寻求产出与产能的平衡。</p> <p>人的三类资产都要追求产出与产能平衡:</p> <ul> <li>物质资产,急功近利常常会毁掉宝贵的物质资产。保持产出与产能的平衡会帮助你更有效地利用物质资产。</li> <li>金融资产,我们最宝贵的金融资本就是赚钱的能力。如果不能持续投资以增进自己的产能,眼光就会受到局限,只能在现有的职位上踏步。</li> <li>人力资产,一味重视产出会导致糟糕的健康状况、耗损的机器设备、透支的银行存款或破裂的人际关系。</li> </ul> <h3>思想决定行动,行动决定习惯</h3> <p>如上所述,要先养成以原则为中心的思维方式,才能影响到日常的每一个决策和行为,长期一致性的行为最终才能成为习惯。</p> <p>习惯有三个要素,缺一不可:</p> <ul> <li>知识:要知道做什么、为什么做</li> <li>技巧:要知道如何做</li> <li>意愿:想要做</li> </ul> <h2>本书的7个习惯</h2> <p>书中的7个习惯,符合成长规律的三个阶段:依赖期-独立期-互赖期,若下[成熟模式图]所示:</p> <p><img src="/images/picgo/20230528154320.png" alt="成熟模式图" /></p> <h3>“个人领域”的三个习惯:</h3> <ol> <li>积极主动</li> <li>以始为终</li> <li>要事第一</li> </ol> <p>养成这个三个习惯,可以大幅提高你的自信心,你将更能认清自己的本质、内心深处的价值观以及个人独特的才干与能耐。</p> <p>秉持自己的信念而活,就能产生自尊自重与自制力,并且内心平和。</p> <p>你会以内在的价值标准,而不是旁人的好恶或与别人比较的结果,来衡量自己。这时候,事情对错与别人是否发现无关。</p> <h3>“公众领域”的三个习惯:</h3> <ol> <li>双赢思维</li> <li>知己解彼</li> <li>统合综效</li> </ol> <p>当你接受“公众成功”中的三个习惯时,修复和重建破裂的人际关系的意愿和能量将被激发。</p> <p>关系会更上一层楼,变得更加深厚、坚固,历久弥新且经得起考验。</p> <h3>1积极主动</h3> <p>依据原则及价值观行事,而非情绪或外在环境来下决定。</p> <p>为自己过去、现在及未来的行为负责、对自己的人生负责。</p> <p>个人行为取决于自身的抉择,而不是外在的环境。</p> <p>人类应该有营造有利的外在环境的积极性和责任感,养成主动改变环境的观念:对于可控的事情要勇敢改变自己,对于间接可控的事情要共情、施加自己的影响,对于不可控的事情要泰然处之、不被其左右。</p> <p>只有消极的人才会一直紧盯别人的缺点、环境问题、超出自己能力范围的事情不放,作为自己消极行为的挡箭牌,任由"感觉"去左右自己的行为,怨天尤人、装受害者。</p> <h3>2以始为终</h3> <p>要以原则为中心:</p> <ul> <li>养成原则第一的思维方式,即在做决策时要知道什么最重要。</li> <li>只要心中秉持着恒久不变的真理,就能屹立于动荡的环境中。</li> <li>因为一个人的应变能力取决于他对自己的本性、人生目标以及价值观的不变信念。</li> </ul> <p>要自我领导:</p> <ul> <li>明确自己的原则、目标、价值观。</li> <li>以他人为中心的人没有内在的安全感,自我价值变化无常,受制于他人的情绪和行为;人生方向也取决于他人的回应,时时揣摩如何反击;他们的智慧受限于以敌人为中心的偏执心理;毫无力量可言,总是被别人牵着鼻子走。</li> </ul> <p>行动之前先定结果。</p> <p>可以具象的撰写出个人/团队的**【使命宣言】**:自己要成为怎样的人、成就怎样的事、为此奠基需要哪些价值观和原则。</p> <blockquote> <p>休太长的假,看太多的电影或电视,打太多的电子游戏,长期无所事事,都等于浪费生命,无益于增长智慧,激发潜能,增进安全感或指引人生,只不过制造更多的空虚而已。</p> </blockquote> <h3>3要事第一</h3> <p>制定计划,安排优先级。</p> <p>专注于重要的事情:</p> <ul> <li>以目标为导向</li> <li>以原则为中心培养独立意识,服从自我价值观的约束。</li> <li>重要性与目标有关,凡有价值、有利于实现个人目标的就是要事</li> <li>花在第二象限(重要紧急)的时间,回报指数非常高,花在第一象限的时间只能收支平衡</li> </ul> <p>拒绝不重要事情的烦扰:</p> <ul> <li>控制感情、情绪,不被“不重要”的事情干扰</li> <li>如果内心不够坚定,很难拒绝第三、第四象限事务的诱惑</li> <li>花在第三和第四象限(不重要)的时间则是血本无归</li> </ul> <p><img src="/images/picgo/20230528155525.png" alt="" /></p> <p>学会授权</p> <ul> <li>授权是提高效率或效能的秘诀之一,可惜一般人多吝于授权,总觉得不如靠自己更省时省事。</li> <li>授权基本上可以划分成两种类型:指令型授权和责任型授权。</li> <li>责任型授权的关注重点是最终的结果。它给人们自由,允许自行选择做事的具体方法,并为最终的结果负责。</li> </ul> <h3>4双赢思维</h3> <p>与人交往 要基于互敬、寻求互惠的原则。</p> <p>人际关系的本质:</p> <ul> <li>人际关系情感账户中存储的是信任、安全感、礼貌</li> <li>投资情感账户方式:理解倾听、注意小节、信守承诺、明确期望、正值诚信、勇于致歉、无条件的爱心(鼓励个人肯定自我 追求成长)</li> </ul> <blockquote> <p>生活是合作的舞台,而不是一个角斗场</p> </blockquote> <ul> <li>分享更多的机会、财富及资源,避免敌对式竞争。</li> <li>正值诚恳的对待每个人,损人利己、损己利人皆不可取,遇到冲突时要尽量寻求对双方都有利的解决方案,利人也是利己。</li> </ul> <p>与人合作前签订双赢协议:</p> <ol> <li>确认预期目标</li> <li>确立指导方针:实现目标要坚持的原则、方法</li> <li>可用资源:人力、物力</li> <li>建立任何考核标准和时间</li> <li>根据考核制度确认奖惩</li> </ol> <p>举个例子🌰:这个协议看起来很书面化,但是可以应用在生活的方方面面,与任何人合作一件事,都可以按照这个套路来进行事前沟通:</p> <blockquote> <p>咱俩今天在一起做这个事情,目标就是把xx完成,希望我们双方遵循xx原则(尽好职责)做好这件事,可以提供的人力物力资源有xx,需要更多资源可以提出来沟通;如果事情做得好、达到xx标准,有xx奖励,如果谁做的不好、不达标,也有xx惩罚。</p> </blockquote> <h3>5知己解彼</h3> <blockquote> <p>除了物质,人类最大的生存需求源自心理,即被人理解、肯定、认可和欣赏。</p> </blockquote> <p>首先寻求诚心去了解、聆听别人,承认人与人的差异,主动倾听和理解别人的想法,而不是好为人师。</p> <p>学会移情、理解别人:人际沟通有10%靠语言,30%靠语调和声音,60%靠表情和肢体语言。</p> <p>无效沟通的典型例子:</p> <ul> <li>对别人的想法进行价值判断</li> <li>以自己的价值观对别人的隐私追根究底</li> <li>好为人师——以自己的经验提供忠告。</li> <li>自以为是——根据自己的行为与动机衡量别人的行为与动机。</li> </ul> <h3>6统合综效</h3> <p>感知、尊重、利用<strong>差异</strong></p> <ul> <li>判断和尊重人与人之间的差异,取长补短</li> <li>重视不同个体的不同心理、情绪与智能,以及个人眼中所见到的不同世界。</li> <li>缺乏安全感的人总觉得别人要按照他的想法来,殊不知人际交往最可贵的地方就在于有差异、有差异才能互补。</li> </ul> <p>统合综效的基本心态是:如果一位具有相当聪明才智的人跟我意见不同,那么对方的主张必定有我尚未体会的奥妙,值得加以了解。</p> <p>非按照我的方式,亦非遵循你的方式,而是创造第三种更好的办法。</p> <p>最优的沟通方式是大家都对事不对人、坦诚表达观点,为同一个目标集思广益。</p> <h3>7不断更新</h3> <p>不断做重复的工作并不能带来经济上的安全感,拥有财富并不代表经济独立,拥有创造财富的能力才真正可靠。</p> <p>歌德(Goethe)说:</p> <blockquote> <p>“以一个人的现有表现期许之,他不会有所长进。以他的潜能和应有成就期许之,他定能不负所望。”</p> </blockquote> <p>把玩内心兽性的人,早晚会变成真正的野兽;整天弄虚作假的人,终将失去获得真理的权利;暴虐成性的人,头脑的判断力会日益减退。</p> <p>要从四个层面自我提升:</p> <ul> <li>身体(运动 营养 压力调节)</li> <li>精神(价值观 冥想)</li> <li>智力(学习 阅读写作 想象力 规划)</li> <li>社会/情感(理解他人 影响他人 统合综效)。</li> </ul> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/7_habbits/#post-comment/</comments>
</item>
<item>
<title>月刊#12 | 2022.06-09</title>
<link>https://www.scarsu.com/monthly_12_2022_06-09/</link>
<guid isPermaLink="true">https://www.scarsu.com/monthly_12_2022_06-09/</guid>
<description>这篇文章收集了2022年6月-9月之间,我获取到的对我有用的信息,包括:新闻 读书 写作、个人成长 低消费 健康、FIRE生活 财富 技术 前端等等分类。</description>
<pubDate>Fri, 23 Sep 2022 00:00:00 GMT</pubDate>
<content:encoded><p>💡 <a>点击此链接前往notion查看</a></p> </content:encoded>
<category>信息源</category>
<comments>https://www.scarsu.com/monthly_12_2022_06-09/#post-comment/</comments>
</item>
<item>
<title>软技能2:软件开发入门世界观</title>
<link>https://www.scarsu.com/software_developer_career_guide/</link>
<guid isPermaLink="true">https://www.scarsu.com/software_developer_career_guide/</guid>
<description>软件开发是什么?软件开发者需要拥有哪些技能?软件开发有哪些方向?软件开发如何求职?</description>
<pubDate>Wed, 01 Jun 2022 00:00:00 GMT</pubDate>
<content:encoded><h2>来源</h2> <ul> <li>书名:《软技能2:软件开发者职业生涯指南》</li> <li>作者:[美] 约翰·森梅兹</li> <li>出版时间:2020-5-1</li> <li>ISBN:9787115534538</li> <li>豆瓣链接:https://book.douban.com/subject/35043940/</li> <li>豆瓣评分:8.3⭐</li> </ul> <h2>如何学习?</h2> <ul> <li>定目标;</li> <li>搜资源;</li> <li>学-做-复盘;</li> </ul> <h2>软件开发的流程?</h2> <ul> <li>理解问题、收集整理需求</li> <li>设计解决问题的方案、搭建代码架构</li> <li>写代码</li> <li>测试部署</li> </ul> <h2>软件需要哪些技能?</h2> <ul> <li>一门编程语言、数据结构与算法、框架/库/设计模式、数据库基础、源代码控制、调试与测试、构建与部署</li> </ul> <h2>学哪门编程语言?</h2> <ul> <li>考虑当前与未来的就业前景选一门主流语言,一旦你学会了一门编程语言,学习第二门语言就容易多了。</li> </ul> <h2>怎样写简历?</h2> <ul> <li>写清楚专业与技能、做过什么、如何做的、有什么成果</li> <li>针对不同岗位和需求,写不同版本简历</li> </ul> <h2>如何准备面试?</h2> <ul> <li>准备常见面试问题</li> <li>练习编程和问答类型的面试题</li> <li>理清楚自己简历上写的经历</li> </ul> <h2>如何投简历?</h2> <ul> <li>找人脉内推、找猎头推荐、网投</li> </ul> <h2>如何谈薪?</h2> <ul> <li>了解薪资范围、行情,获得一个平均薪资</li> <li>不要直接透露目前薪资,一般公司都要求保密,可以给出整包的范围</li> <li>不要直接透露期望薪资,先了解整体待遇情况,以真实期望薪资+一定比例报价,留出谈判余地</li> <li>至少有一轮还价,要毫不犹豫的还价;最多3轮还价;</li> <li>多谈几份offer</li> </ul> <h2>主流编程语言世界观</h2> <ul> <li>C语言:使用最广,古老强大,可以访问计算机内存和底层部件,面向操作系统、底层硬件、嵌入式</li> <li>C++:C的超集,常与C混用,用于扩展C的对象、类、虚拟函数等特性,广泛用于游戏开发,复杂度高</li> <li>java:年代久远,运行在虚拟机上 虚拟机可以运行在任何平台上,面向对象 语法简洁,不允许直接操作内存和计算机底层</li> <li>python:优雅简洁,用更少的代码来表示更多的语义,适合初学者,正在流行,面向对象、过程式、函数式都可以,解释型语言 无需编译</li> <li>ruby:有趣简单,面向对象的脚本语言</li> <li>javascript:1995起,web领域主流语言,解释型语言无需编译,可以嵌入浏览器执行;10天内创造出的语言 历史遗留问题多,最新的ecmascript已经修改了许多遗留问题;</li> <li>swift:用于新一代ios、osx上的语言,支持许多objective-c的许多特性、比其简洁、易用、灵活</li> <li>go:2007起,google创造的语言,和C一样面向系统,也正在被扩展到web;并发编程,无需考虑内存管理,性能强大;</li> <li>haskell:在学术界受欢迎,纯函数式编程语言+强静态类型系统,可以编写高度可预测的代码,无任何副作用;学习难度大</li> </ul> <h2>主流开发方向世界观</h2> <ul> <li>web开发: <ul> <li>是什么?开发在浏览器中显示与运行的网页</li> <li>特点?跨平台,运行环境、系统、软件类型、版本不可控</li> <li>技术?HTML代码编写网页显式内容、css代码控制内容的样式、javascript代码编写脚本逻辑;</li> <li>原理?浏览器将web代码渲染成网页;网页通过HTTP向服务器发送网络请求 获取数据;</li> </ul> </li> <li>移动端开发: <ul> <li>是什么?开发在移动设备上运行的程序(手机 平板 手表 穿戴设备 车机)</li> <li>特点?规模小,用途聚焦,容易构建,适合自由职业者,最有创业机会</li> <li>技术?ios原生开发用xcode、objective-c、swift;android原生开发用java和android sudio;跨平台开发用Cordova等;移动web开发 以web的形式制作移动程序;</li> </ul> </li> <li>后端开发: <ul> <li>是什么?所有不涉及用户交互界面的开发工作</li> <li>工作内容有哪些?检索、存储、处理数据,遵循&amp;实现业务逻辑,参与构建系统架构、基础设施</li> <li>技术?java php  ruby  .net  等后端语言,SQL语言与数据库</li> </ul> </li> <li>游戏开发: <ul> <li>特点?难度大,竞争激烈,时间金钱投入大,盈利难</li> <li>技术?游戏引擎:unity3d(最主流)、unreal;接近底层硬件的编程语言,以便获取硬件平台的最高性能:C++(最主流);数学知识:矩阵转换、向量运算等图形计算</li> <li>学习方法?复刻大量游戏,由简入难</li> </ul> </li> <li>DBA: <ul> <li>是什么?数据库管理员</li> <li>工作内容有哪些?建立 维护 监控数据库,维护数据库硬件,扩容 资源回收,定期备份与恢复数据库,建立数据库模式(数据库的空白副本),编写存储过程</li> </ul> </li> <li>DevOps: <ul> <li>是什么?开发与运维人员</li> <li>工作内容?创建构建环境 让代码在服务器中部署 运行 测试</li> </ul> </li> </ul> <h2>作为软件开发者,应该掌握的测试知识?</h2> <ul> <li>作为软件开发者,应该有软件测试的知识背景,自测发现问题修复  远比测试人员发现问题提bug修复 节省时间和精力</li> <li>有哪些测试类型? <ul> <li>黑盒测试:把软件本身看作黑匣子,只关心输入输出</li> <li>白盒测试:要了解软件内部的实现,根据代码实现来设计测试用例</li> <li>功能测试:测试系统实际功能</li> <li>验收测试/系统测试:执行一组测试以检验客户的实际需求和期望,针对系统整体运行效果的测试</li> <li>自动化测试:自动执行测试并且验证结果</li> <li>回归测试:验证系统是否按照以前的方式运行,避免新功能破坏现有的功能</li> <li>其他测试:负载、性能、恢复、安全、压力、可用性accessibility</li> </ul> </li> <li>TDD 测试驱动开发是什么?在编写任何代码前,先编写测试用例,将它作为软件应该做什么的规格说明</li> <li>单元测试是什么?编写测试程序,检查代码中"最小内聚单元"</li> </ul> <h2>源代码控制</h2> <ul> <li>是什么?跟踪软件项目里不同版本文件和源代码的方法</li> <li>作用?减少丢失代码的可能性;支持定期备份;多人协同开发;多版本管理;</li> <li>应该掌握的基础知识有哪些?代码库、checkout签出代码、历史版本、分支管理、合并版本merge、版本冲突conflict</li> <li>流行的代码控制工具?git最主流</li> </ul> <h2>CICD</h2> <ul> <li>是什么?自动化构建与持续集成</li> <li>作用?自动化提升效率、缩短反馈周期、改善质量</li> <li>典型工作流?开发者更新代码-CI软件检测到代码更新,触发自动构建,获取最新代码,编译代码 执行静态分析与单元测试-打包程序-部署</li> <li>流行的CI软件:jenkins、hudson、TravisCI、Teamcity、TFS</li> </ul> <h2>调试</h2> <ul> <li>调试是什么?在代码中寻找问题的根源、检验假设</li> <li>如何调试?重现错误,定位问题(查看日志 报错信息,思考可能的原因,验证假设,检查前置条件,分治思想,二分法排查代码,逐步缩小范围)</li> </ul> <h2>代码维护</h2> <ul> <li>在软件生涯中 维护旧代码比编写新代码要花的时间多,因此要学会维护代码</li> <li>目的?避免代码越来越糟;改善现有代码、编写可维护的代码、降低代码熵值</li> <li>如何维护?增强代码可读性,使其简洁、组织清晰,重构代码,在不改变现有功能的前提下,使现有的代码更具有可读性,写好清晰、简洁注释</li> <li>推荐资源?《代码整洁之道》、《代码大全》、《修改代码的艺术》、《重构:改善既有代码》</li> </ul> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/software_developer_career_guide/#post-comment/</comments>
</item>
<item>
<title>谈判是什么</title>
<link>https://www.scarsu.com/negotiation/</link>
<guid isPermaLink="true">https://www.scarsu.com/negotiation/</guid>
<description>谈判,看起来离我们很远,实际上处处存在,是人际交往、谈薪、撕逼、砍价、贸易… 的必备能力。</description>
<pubDate>Fri, 27 May 2022 00:00:00 GMT</pubDate>
<content:encoded><p><img src="/images/picgo/trade.png" alt="《谈判是什么》" /></p> <h2>简介</h2> <ul> <li>书名:谈判是什么 Everything Is Negotiable</li> <li>作者:(英)盖温.肯尼迪</li> <li>出版时间:2004-10-1</li> <li>ISBN:9787801441881</li> <li>封面:/images/picgo/trade.png</li> <li>豆瓣链接:https://book.douban.com/subject/1038977/</li> <li>豆瓣评分:8.6⭐</li> <li>思维导图:/images/picgo/negotiation.png</li> <li>我的笔记:https://www.scarsu.com/negotiation/</li> </ul> <p>谈判,看起来离我们很远,实际上处处存在,是人际交往、谈薪、撕逼、砍价、贸易… 的必备能力。</p> <h2>处处是谈判</h2> <ul> <li>人在社会生活的本质是价值交换,不论是金钱、物资、劳动力、时间、情感,都属于人与人交换价值的范畴</li> <li>交换的过程,必然会有谈判的存在</li> <li>在人际交往、求职面试、职场工作、生意买卖、国际贸易中,谈判更为重要</li> <li>因此,谈判是生活、工作、人际交往的必备技能</li> </ul> <h2>四种谈判风格</h2> <ul> <li>作者划分了四种谈判风格: <ol> <li>羊(懦弱)</li> <li>驴(蠢)</li> <li>狐(奸猾)</li> <li>枭(冷静正直)</li> </ol> </li> <li>作者主张,应该做枭一样的谈判者:<strong>既不欺压旁人又能取得自己想得到的结果</strong></li> </ul> <h2>谈判的本质是利益交换</h2> <ul> <li>谈判的本质,就是己方与对方的利益交换。</li> <li>谈判的艺术,就在于善于<strong>在“妥协和利益”两者之间取得平衡</strong>。</li> </ul> <h2>谈判前</h2> <ol> <li>强化决心、确定双方的谈判目标、双方的利益、双方的筹码,尤其谨记自己谈判的真正目标、不要被对方带偏</li> <li>做好谈判前准备、<strong>提前收集所有利于谈判的信息</strong>,利用这些信息去讨价还价,做筹码交换</li> </ol> <h2>谈判技巧</h2> <ol> <li>不要接受对方的第一次开价、商品标价:特价不是真的特价、特价只能证明标价的坑人程度</li> <li>己方的第一次开价可以夸张一点,留下足够的<strong>讨价还价的余地</strong>;</li> <li><strong>记牢价格公式</strong>:卖家开价&gt;卖家心理价&gt;卖家底价、买家开价&lt;买家心理价&lt;买家最高价;</li> <li>对方不愿开价:在提出己方开价后,一定要设法<strong>了解到对方的方案</strong>再做进一步的行动。</li> <li>对方否定你的提议:在对方明确提出其解决方案之前,不要另提新建议也不要修改原建议</li> <li>对方要求你让步:礼尚往来、而不是一味退让,记牢<strong>如果句式</strong><code>“如果我方可以获得xx利益,那么我方就能做出xx让步”</code>;善意让步只会让对方得寸进尺。</li> <li>对方问你是否可以砍价:不能直接回答可以,这会直接削弱谈判地位;可以略作思考后回答,我的东西因为xx肯定值这个开价,再反问对方,是否对我提供的东西不满意,让他提出建议</li> <li>对方态度强硬:应该<strong>处变不惊、乐于耐心听取对方的意见并加以充分考虑 但微笑着说不</strong></li> <li>对方威胁、恫吓、胡搅蛮缠、不尊重你:要坚定表现出:无论他怎样胡搅蛮缠,我都绝对不受影响、他绝对达不到目的,除非愿意礼尚往来、各让一步。</li> <li>掌握**谈判的杠杆、谈判的力量:**不要轻易相信对方释放的信息:卖方要避免暴露着急成交的心态和库存货源等信息;买方不要赞扬卖方的产品、可以假装有多方竞争</li> <li>受托策略:我受人所托做这个交易、我无法做出决定、我要去和xx商量、xx说低于这个价格不卖</li> <li>买方<strong>还价策略</strong>千千万:可以用一切于己方不重要 于对方重要的条件,去做利益交换;例如要买3件某款玩具,有标价,应该:先问有没有特价、再问买两件多少钱、再问买三件多少钱;例如在商店东西,售货员说无权打折,可以要求找经理谈;搭上附件,我才买;按这个价得白送一个赠品;如果总从你这里订货,可打多少折扣? 我是新(老)客户,作为见面礼(为了老交情)你总得打点折扣才是。;要是付现金打多少折扣?如果我答应向别人推荐你的产品,卖给我的能不能打点折扣? 你要是有权给我优惠,我马上就下订单。</li> <li>卖方<strong>提价策略</strong>也有千千万:不要轻易在价格上让步,而是考虑价格之外的<strong>其他因素:<strong>不要把注意力集中于</strong>价格的数目</strong>上而要放在**其提出的“形式”**上,“<strong>这种包装是这个价,那种包装是另一个价</strong>。”</li> <li>适时变通,遇到互不让步的问题,可以换其他更细节/更抽象的问题讨论</li> </ol> <h2>谈判后</h2> <p>合同一定要具体、要考虑到一切不可控的情况、及其处理方案。</p> <p>墨菲定律告诉我们:“越是坏事越易出现”。</p> <p>因此<strong>不要存有侥幸心理</strong></p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/negotiation/#post-comment/</comments>
</item>
<item>
<title>月刊#11 | 2022.05</title>
<link>https://www.scarsu.com/monthly_11_2022_05/</link>
<guid isPermaLink="true">https://www.scarsu.com/monthly_11_2022_05/</guid>
<description>这篇文章收集了2022年5月,我获取到的对我有用的信息,包括:新闻 读书 写作、个人成长 低消费 健康、FIRE生活 财富 技术 前端等等分类。</description>
<pubDate>Mon, 23 May 2022 00:00:00 GMT</pubDate>
<content:encoded><p>&lt;aside&gt;</p> <p>💡 <a>信息源分类整理 | 往期合集 | 持续更新</a></p> <p>带⭐标的是我精选出来、推荐你阅读的信息</p> <p>&lt;/aside&gt;</p> <h3>提升认知:信息输入、知识管理🧠</h3> <ul> <li>⭐认知 | <a>如何从底层杀出 / 人生翻盘指南 - 知乎</a>、<a>思维导图</a></li> <li>新闻 - <a>宇宙可能停止膨胀开始收缩</a></li> <li>新闻 - <a>科学家警告称海洋开始失去记忆</a>:稳定的海洋环境正变得更加不可预测和不稳定</li> <li>新闻 - <a>全球陷粮荒危机</a> | solidot</li> <li>新闻 - <a>美的内部电话会曝光,董事长方洪波:未来三年是前所未有的行业寒冬</a></li> <li>写作 | <a>写作最大的理由应该是,我们通过写作认识自己</a></li> <li>写作 | <a>作家和评论家YanYi给的写作建议</a></li> <li>读书 | <a>如何消化超出你“水平”的书籍并提高你的智力</a> - Medium</li> <li>读书 | <a>《原子习惯》</a>:习惯是“自我完善的复利”</li> <li>⭐读书 | <a>《内在动机》</a>:内在动机由三个要素组成: 自主(听听自己内心的声音)、 胜任(在自己舒适区边缘探索)、 联结(认识我与这个世界的关系)</li> <li>读书 | <a>什么时候是读哲学的好时候?</a> | 澎湃:赵林在《西方哲学史演讲录》中提出,当人们普遍处于亢奋的发展和拼搏状态时,哲学完全是一种累赘的文化奢侈品,而正是在人们开始转向“内卷”或者“躺平”状态时,哲学才成为一种排遣无奈和无聊、给人以精神慰藉的刚需。</li> <li>纪录片 | <a>《秃然发生》</a>:全国首档关注男性脱发的纪录片, 至今已有超过2700万观众收看</li> </ul> <h3>提升体验:身心舒适、自律极简😃</h3> <ul> <li>⭐成长 | <a>是什么让人们看上去很无聊,以及这如何影响到我们对于无聊的人的认识 - 36Kr</a></li> <li>低消费 | ****<a>年轻人如何远离消费主义陷阱?</a>****资本最擅长的三件事:一、凭空制造需求。二、用消费品划分社会层级结构。三、设法加快你的消耗速度。</li> <li>⭐健康 | <a>蔬菜水果的营养量在下降 - 奇客Solidot</a></li> <li>健康 | <a>身体健康百病不侵,ICU 医生助你抢鲜了解《中国居民膳食指南(2022)》 - 少数派</a></li> <li>饮食 | 为什么炸食物要炸两遍:低温炸熟炸透食物、高温脱水酥脆</li> <li>教育 | <a>教育部要求9月起中小学生要学煮饭</a></li> <li>生活 | <a>量化家务分工的模式</a></li> <li>人际关系 | <a>和父母最好的相处模式什么样的? - one</a></li> </ul> <h3>提升物质:专业技能、工作投资💹</h3> <ul> <li> <p>⭐财富 | <a>FIRE生活</a>:“低配版”财富自由 = 攒年支出*25的启动资金 + 每年4%的理财收益 + 辞职、恢复自由身、低物欲低消费生活;FIRE生活只是不工作了,把自己的时间完全交给爱好和其他更有价值的事情;“FIRE有两个好处,一个是如果把它作为一个奋斗目标,那就有盼头了。还有就是FIRE的重点不在于财富,而是在于自由。”</p> </li> <li> <p>财富 | <a>个人财富的六个层级 - 36Kr</a> ( <a>英文原文</a> 、<a>信息源Personal Finance Principles网站</a></p> </li> <li> <p>财富 | 拥有多少钱才能实现财富自由?100w年收益4%,月均利息收入3333¥</p> </li> <li> <p>市场 | *<strong>*<a>用「乐高」思维做成的产品是什么样的?Notion 和他的 GTM 策略</a>**</strong></p> </li> <li> <p>行业 | 这个“五一“假期,有草地的地方就有帐篷,<a>露营之后火什么?</a>:家庭园艺消费市场、舞台剧 话剧 脱口秀等演艺市场(中产阶级所追求的精致是一种生活的美好,但并不是奢侈的享受。)</p> </li> <li> <p>行业 | <a>谈谈我对 web 3.0 的看法 - 掘金</a>:web 1.0 与 web 2.0 数据中心话,存储在平台的服务器、web 3.0 数据去中心化,不受平台拥有,存储在某些去中心化的应用里面</p> </li> <li> <p>职业 | <a>真实的公务员世界</a></p> </li> <li> <p>职业 | <a>陪诊师、跑腿业务</a></p> </li> <li> <p>网络 | <a>计算机网络常用知识总结 - 掘金</a></p> </li> <li> <p>低代码 | <a>电商系统 低代码 开源项目</a></p> </li> <li> <p>低代码 | 阿里开源<a>LowCodeEngine、</a><a>demo地址</a></p> </li> <li> <p>技术 | <a>线上突然出 bug 怎么找? - V2EX</a></p> </li> <li> <p>前端 | <a>开源wx小程序</a></p> </li> <li> <p>前端 | <a>JavaScript 框架的四个时代 - pzuraq | blog</a></p> </li> <li> <p>前端 | <a>Building a JavaScript Bundler - Christoph Nakazawa</a></p> </li> <li> <p>前端 | <a>掘金 5.11 月影 贺师俊 最新JS标准&amp;ES2022直播回放</a></p> </li> <li> <p>前端 | <a>纯CSS实现 3D slinky效果</a> <img src="https://i0.wp.com/css-tricks.com/wp-content/uploads/2022/05/giphy.gif?resize=500%2C375&amp;ssl=1" alt="https://i0.wp.com/css-tricks.com/wp-content/uploads/2022/05/giphy.gif?resize=500%2C375&amp;ssl=1" /></p> </li> <li> <p>前端 | <a>使用CSS text-shadow实现复杂的hover效果</a></p> </li> <li> <p>前端 | <a>微前端架构</a> - Medium</p> </li> <li> <p>前端 | <a>我是高级前端开发人员吗?</a> - Medium</p> </li> <li> <p>前端 | <a>专业人士如何处理 JavaScript Promise</a> - Medium</p> </li> <li> <p>前端 | <a>前端埋点方案</a></p> </li> </ul> </content:encoded>
<category>信息源</category>
<comments>https://www.scarsu.com/monthly_11_2022_05/#post-comment/</comments>
</item>
<item>
<title>月刊#10 | 2022.04</title>
<link>https://www.scarsu.com/monthly_10_2022_04/</link>
<guid isPermaLink="true">https://www.scarsu.com/monthly_10_2022_04/</guid>
<description>这篇文章收集了我2022年4月获取到的对我有用的信息,包括:信息源 书籍 播客、工具、健康 疫情 时间管理、职场 技术 前端等等分类。</description>
<pubDate>Thu, 28 Apr 2022 00:00:00 GMT</pubDate>
<content:encoded><p>💡 <a>信息源分类整理 | 往期合集 | 持续更新</a></p> <hr /> <h3>提升认知:信息输入、知识管理🧠</h3> <ul> <li>新闻 | <a>中国网络媒体抖音、头条、小红书先后宣布拟展示帐号IP属地</a>:更真实有序的网络言论氛围</li> <li>信息源 | 反复推荐过多次的happy xiao的博客改了域名:<a>coke.do - 简短实用的效率方法,健康习惯,思维模式</a>,每周都会分享一些好的想法、信息</li> <li>信息源 | <a>博客TA :Total Annarchy</a> - 华尔街日报畅销书作者ANN HANDLEY的无政府主义博客,关于写作、营销</li> <li>信息源 | <a>国家智慧教育平台</a>:中小学、职业教育、高等教育 免费高质量资源</li> <li>书籍 | <a>《乌合之众》</a>+<a>《娱乐至死》</a>+<a>《美丽新世界》</a>+<a>《1984》</a>四本结合看:“媒体是现代社会的独裁者”、”人一到群体中,智商就严重降低”</li> <li>书籍 | <a>《纳瓦尔宝典:财富和幸福指南》</a></li> <li>书籍 | <a>《大国空巢:反思中国计划生育政策》</a>:了解中国社会人口、老龄化现状</li> <li>播客 | 知晓有我:从女性视角出发探讨社会现象(小宇宙App可听</li> <li>播客 | 霞光里FM:《三联生活周刊》出品(小宇宙App可听</li> <li>播客 | 螺丝在拧紧:单向空间出品(小宇宙App可听</li> <li>播客 | 随机波动:三位女性媒体人的一档泛文化播客(小宇宙App可听</li> <li>播客 | 放学以后:探寻日常生活之外的可能性(小宇宙App可听</li> <li>播客 | 故事FM:真实的女性故事自有万钧之力(小宇宙App可听</li> <li>话题 | <a>人生唯一确定的就是不确定的人生 - 罗翔</a></li> <li>话题 | <a>道法术器</a>:学校就是打造社会工具的地方、“有时候有些观念知识不是你真正需要的,而是这个世界少数掌握话语权的人想要你知道的,但这不一定是真相”</li> <li>话题 | 言论自由:<a>李敖2005年北京大学演讲</a></li> <li>话题 | <a>怎样让别人觉得自己很靠谱?</a>:明确能力边界、帮助对方明确任务的规划和想法、不要完美主义,先把事情做出去、学会邀功</li> <li>想法 | 新闻自由是灾难最大的救助者</li> <li>想法 | 尊重他人命运,放下助人情节、你的建议如果唤不起别人的改变,那不如说句好话结个善缘、禁止🈲好为人师</li> <li>想法 | <a>弱者如何以小博大</a>:1.快,先起步。2.差异化</li> <li>想法 | <a>谈判前要包装自己</a>:要懂得给自己造势</li> <li>想法 | <a>表达、抓逻辑漏洞、不要被挑起情绪、不要陷于对攻击自己的无关的问题的辩解之中</a></li> </ul> <h3>提升效率:用 好工具、用好 工具🔨</h3> <ul> <li>工具 | <a>Auto.js</a>:Android平台上支持Node.js的JavaScript自动化工具</li> <li>工具 | <a>Parsec</a>:轻量级、即开即用的远程连接工具</li> <li>工具 | <a>Thud</a>:一款用ionic+angular开发的、开源、无广告的Android 新闻 App</li> <li>工具 | <a>叮咚抢菜-派送时段监听及推送工具</a></li> </ul> <h3>提升体验:身心舒适、自律极简😃</h3> <ul> <li>健康 | 据<a>《柳叶刀》医学期刊</a>称,步行几乎对身体内所有的细胞都有好处;能够带来益处的步数大约是 7000步(老年人) - 9000 步(年轻人),超过推荐的次数后,死亡风险就不再降低。</li> <li>健康 | <a>在线问诊平台横评</a>:当下的在线问诊平台是资本的大饼</li> <li>健康 | <a>程序员延寿指南</a>:稳健的活得更久、降低66.67%全因死亡率</li> <li>疫情 | <a>“躺平”抗疫</a>维护的是既得利益者的财产,牺牲的是大众以及弱势群体的健康、甚至生命,而我们这些普通人,早晚一天都是弱势群体的一员。</li> <li>疫情 | <a>首批新冠感染幸存者</a>:每一天看似平淡的生活,其实都是最大的幸福。</li> <li>心理学 | <a>自卑的本质 - one</a>:接受自己的不好、承认问题的难度、想办法解决问题</li> <li>心理学 | <a>如何提高情绪阈值</a>:避免悲观 即刻努力、放大心胸 面向未来、持续学习 保持健康</li> <li>生活 | 在线小工具:<a>选择食材 ⇒ 推荐食谱</a></li> <li>游戏 | <a>汉兜</a> 、<a>词影</a>:国内版Wordle(在国外大火的游戏),玩家有十次机会猜一个四字词语(一般是常见成语)。每次猜测后,通过拼音、音调和汉字的颜色标识与答案的区别。</li> <li>环保 | <a>科学家在活人血液以及肺部发现塑料微粒</a>,/样本取自 13 名接受手术的患者的组织,其中 11 例发现了微塑料。最常见的是用于塑料包装和吸管的聚丙烯,以及用于瓶子的 PET。这些颗粒可以在人体内传播,并且可能滞留在器官中。</li> <li>时间管理 | <a>如何高效利用下班后的时间?- 少数派</a>:**可用时间 = 24 小时 - 工作时间 - 通勤时间 - 休息时间 - 花在必要事项上的时间:**从 996 的工作换到 965;搬到离公司更近的地方;从社交网络抽离;提升睡眠效率减少睡眠时间;</li> </ul> <h3>提升物质:专业技能、工作投资💹</h3> <ul> <li>自媒体 | 写作技巧:尽可能写的更具体 - 文案大师 <a>Ann Handley 的邮件</a></li> <li>商业 | 美剧<a>《亿万》</a>金融、财富、信息差:财富的本质就是洞察力的变现</li> <li>商业 | <a>微软是如何做到市值$10T的</a>:2000 年代的 Windows 公司,2010 年代成为 Office 公司,并正在成为 2020 年代的云公司</li> <li>商业 | <a>金融战历史</a>:”不创造财富,也不以土地占领为目标,而是依仗资本实力建立各色武装实力去偷猎、围猎他国财富,其实都属广义金融战范畴,与当今更加隐秘、更加高超的金融战异曲同工,不过是时代不同、表象不同而已。“</li> <li>行业 | IC Insights 的数据显示,2021 年中国占了全球半导体市场份额的 <a>4%</a>,美国占据了一半以上的份额。</li> <li>职业 | **<a>Topworker跨境客</a>:**全国最大的、优质的跨境自由职业者社群</li> <li>职业 | <a>Toptal</a>: 全球精英自由职业者平台(需要英语好</li> <li>职业 | <a>TalentOrg</a>:互联网行业的远程工作社区(不需要有好的英文能力也可以胜任,招聘多语言产品经理</li> <li>职业 | <a>前端私活</a></li> <li>求职 | <a>Show Me Bug</a>:技术面试的云端IDE,提供实时共享的编程环境</li> <li>求职 | <a>如何判断一个求职者的职业水平</a>:反向思考自己如何提升求职成功率</li> <li>技术 | Nginx替代方案:<a>Caddy2</a> 开源 自动化https 比nginx配置简单</li> <li>技术 | <a>22种设计模式目录</a></li> <li>前端 | 前端架构:<a>前端架构设计模式</a></li> <li>前端 | 前端架构:<a>前端代码的三种设计模式</a>:组件模式、compose组合模式、<strong>Membrane模式</strong></li> <li>前端 | 项目管理:<a>从零到一建立前端规范</a></li> <li>前端 | 性能优化:<a>webpack优化</a></li> <li>前端 | 性能优化:<a>虚拟列表</a></li> <li>前端 | 性能优化:<a>得物团队H5秒开优化</a></li> <li>前端 | 补齐知识体系:React知识点<a>脑图</a></li> <li>前端 | 补齐知识体系:<a>ajax fetch axios区别</a></li> <li>前端 | 补齐知识体系:<a>分析HTTP TCP区别</a></li> <li>前端 | 补齐知识体系:CSS <a>calc()函数</a>,可以计算 长度值、角度、时间、百分比、数值</li> <li>前端 | 补齐知识体系:css3 animation暂停/恢复:<code>animation-play-state: paused/running;</code></li> <li>前端 | 补齐知识体系:<a>CSS Functions脑图</a></li> <li>前端 | 补齐知识体系:5个好用的现代JS特性 <ul> <li>用<code>Object.hasOwn()</code>代替<code>key in obj</code>(包含原型链)和<code>obj.hasOwnProperty</code>(对于非obj容易报错)</li> <li>用<code>#</code>声明私有属性</li> <li>数字分隔符<code>6000_000_000</code></li> <li>用<code>?.</code>简化&amp;&amp;和三元运算符 <ol> <li><code>obj?.prop</code> 对象属性</li> <li><code>obj?.[expr]</code> 对象/数组属性</li> <li><code>func?.(...args)</code> 执行函数</li> </ol> </li> </ul> </li> <li>前端 | 学习借鉴:<a>年包70w+的前端技术专家offer是如何拿到的</a></li> <li>前端 | 开发工具:<a>Javascript运算符搜索引擎</a></li> <li>前端 | ECMAScript新提案:通过复制更改数组,提案了四个新的数组方法<code>.toReversed()</code>、<code>.toSorted()</code>、<code>.toSpliced()</code>、<code>.with()</code>,前三种方法相对应的原始方法.reverse() .sort() .splice() 均会更改原数组,<code>.with(index, value)</code>方法替换了原始的修改数组元素的方式<code>arr[index]=value</code></li> <li>前端 | ECMAScript新提案:<a>类型注解(TypeScript 在未来可能被纳入 ECMAScript 中)</a></li> <li>前端 | 函数式编程:<a>函数组合compose、管道符、pipe函数</a></li> <li>前端 | 实际场景与方案:<a>Vue API 统一管理</a></li> <li>前端 | 实际场景与方案:用<a>责任链模式</a>解决一系列校验问题、避免大量<code>if、else</code></li> <li>前端 | 实际场景与方案:<a>前端常见实际问题&amp;解决方案</a></li> <li>前端 | 项目实例:<a>koa2+vite+ts+vue3+pinia前端SSR项目</a></li> <li>前端 | 项目实例:<a>Angular 13 Example App + Angular CLI + i18n + GraphQL + TypeScript</a></li> </ul> </content:encoded>
<category>信息源</category>
<comments>https://www.scarsu.com/monthly_10_2022_04/#post-comment/</comments>
</item>
<item>
<title>纯CSS实现无限循环轮播</title>
<link>https://www.scarsu.com/infinite_scroll_by_css/</link>
<guid isPermaLink="true">https://www.scarsu.com/infinite_scroll_by_css/</guid>
<description>无JS代码实现无限循环轮播、鼠标悬浮时暂停动画、鼠标移出时继续动画</description>
<pubDate>Fri, 22 Apr 2022 00:00:00 GMT</pubDate>
<content:encoded><h2>原理</h2> <p><img src="/images/picgo/infinite-scroll.png" alt="原理" /></p> <h2>demo代码</h2> <p>html</p> <pre><code>&lt;div class="wrap"&gt; &lt;div class="slide-dom"&gt; &lt;div class="itemA"&gt;A&lt;/div&gt; &lt;div class="itemB"&gt;B&lt;/div&gt; &lt;div class="itemA"&gt;A&lt;/div&gt; &lt;div class="itemB"&gt;B&lt;/div&gt; &lt;/div&gt; &lt;/div&gt; </code></pre> <p>css</p> <pre><code>@keyframes infinite-slide { 0% { transform: translateX(0); } 100% { transform: translateX(-50%); } } .wrap { overflow-x: visible; background: #eee; width: 200px; height: 300px; margin: 0 auto; padding: 100px 0; } .slide-dom { width: max-content; animation: infinite-slide 10s linear infinite; } /* 鼠标悬浮时暂停动画 */ .slide-dom:hover { animation-play-state: paused; } .itemA { display: inline-block; width: 200px; height: 100px; background: pink; } .itemB { display: inline-block; width: 200px; height: 100px; background: yellow; } </code></pre> <h2>效果</h2> <p><a>demo在线地址</a></p> <p><img src="/images/picgo/demo.gif" alt="preview" /></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/infinite_scroll_by_css/#post-comment/</comments>
</item>
<item>
<title>前端字体性能优化</title>
<link>https://www.scarsu.com/web_font_optimize/</link>
<guid isPermaLink="true">https://www.scarsu.com/web_font_optimize/</guid>
<description>字体文件过大、FIOT(flash of invisible text)字体闪现问题</description>
<pubDate>Mon, 11 Apr 2022 00:00:00 GMT</pubDate>
<content:encoded><h2>问题1:字体文件过大,解决方案:<code>Fontmin - 字体子集化</code></h2> <h3>介绍</h3> <p>Fontmin是一个纯JS字体子集化方案,用于压缩字体文件。</p> <p>依赖node环境。</p> <p>其原理是扫描项目中的文字,将用到的字从字体文件中单独拿出来组成一个子集字体文件。</p> <p>可以达到大幅度减小字体文件尺寸的效果。</p> <h3>相关资源</h3> <ul> <li><a>Fontmin官网</a></li> <li><a>开源仓库</a></li> <li><a>文档</a></li> </ul> <h3>安装</h3> <pre><code>npm install --save-dev fontmin </code></pre> <h3>使用</h3> <pre><code>const fs = require("fs"); const Fontmin = require("fontmin"); //扫描文件目录 const scanFolder = (dir, done) =&gt; { let results = []; fs.readdir(dir, (err, list) =&gt; { if (err) { return done(err); } let i = 0; (function iter() { let file = list[i++]; if (!file) { return done(null, results); } file = dir + "/" + file; fs.stat(file, (err, stat) =&gt; { if (stat &amp;&amp; stat.isDirectory()) { scanFolder(file, (err, res) =&gt; { results = results.concat(res); iter(); }); } else { results.push(file); iter(); } }); })(); }); }; //Fontmin根据文字内容生成压缩后的字体子集 const generateFinalHTML = (finalString) =&gt; { const fontmin = new Fontmin() .src('static/fonts/*.ttf') // 需要压缩的所有字体文件 .dest('static/fonts/') // 压缩后文件存储路径 .use( Fontmin.glyph({ text: finalString, hinting: false, }) ) .use( Fontmin.ttf2woff({ deflate: true, }) ); fontmin.run((err) =&gt; { if (err) { throw err; } }); }; //获取目录下所有文件的文字内容 scanFolder("dist", (n, results) =&gt; { let set = new Set(); results.forEach((file) =&gt; { const result = fs.readFileSync(file, "utf8"); const currentSet = new Set(result); set = new Set([...set, ...currentSet]); }); generateFinalHTML(Array.from(set).join("")); }); </code></pre> <h2>问题2:FOIT(Flash of Invisible Text )字体闪现问题</h2> <h3>问题描述</h3> <p>浏览器在加载字体时,默认不展示文本内容,在现代浏览器中,FOIT会导致这种现象出现至多3秒。</p> <p>如果有文字混搭(有的字体需要加载,有的字体不需要)那么用户可能就会发现“网页只显示部分字体”的情况,用户体验很差。</p> <h3>解决步骤1:<code>font-display:swap</code> :未加载到字体时,优先显示替代字体,而不是空白(<a>MDN文档</a>)。</h3> <p><code>font-display</code>属性决定了一个@font-face在不同的下载时间和可用时间下是如何展示的。</p> <pre><code>@ font-face { font-family: ExampleFont; src: url(/path/to/fonts/examplefont.woff)format('woff'), url(/path/to/fonts/examplefont.eot)format('eot'); font-weight: 400; font-style: normal; font-display: fallback; } </code></pre> <h3>解决步骤2:<code>preload</code>:预加载字体文件,提前加载字体。</h3> <pre><code>&lt;link rel="preload" type="font/woff" href="/fonturl" as="font" crossorigin="true"&gt; </code></pre> <h3>解决步骤3:<code>document.fonts.ready</code> <a>接口</a>:浏览器处理完成字体加载后的回调(加载成功或者失败都会触发回调)</h3> <pre><code>document.fonts.ready.then(() =&gt; { // 字体加载完成后的逻辑 this.fontLoaded = true; }); </code></pre> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/web_font_optimize/#post-comment/</comments>
</item>
<item>
<title>月刊#9 | 2022.03</title>
<link>https://www.scarsu.com/monthly_9_2022_03/</link>
<guid isPermaLink="true">https://www.scarsu.com/monthly_9_2022_03/</guid>
<description>提升格局的纪录片、工具、前端、女性觉醒</description>
<pubDate>Thu, 31 Mar 2022 00:00:00 GMT</pubDate>
<content:encoded><p>💡 <a>信息源分类整理 | 往期合集 | 持续更新</a></p> <hr /> <h3>提升认知:信息输入、知识管理🧠</h3> <ul> <li>话题 | <a>迄今为止看到的 对女性最诚挚的祝福</a></li> <li>书籍推荐 | <a>女性主义入门书《成为波伏瓦》</a>:“有伦理的爱情必须是对等而互惠的,爱人与被爱的人都必须有意识,是自由的,努力拥抱彼此生活中的价值所在。而且,当他们的爱涉及性时,他们都必须是性的主体,而不是客体。”</li> <li>纪录片 | <a>天地玄黄 (豆瓣)</a>:从远古到现在,从猿猴到人类,从荒无人烟的沙漠到震撼人心的宗教活动现场,从广袤天地带来的感动到婴孩单纯的笑脸给予的幸福,<strong>祝福与我们共同存在在这颗蔚蓝地球上的一切</strong></li> <li>纪录片 | <a>积极心理学 (豆瓣)</a>:哈佛幸福课,幸福感是衡量人生的唯一标准,是所有目标的最终目标</li> <li>纪录片 | <a>地球脉动 - 电影 - 豆瓣搜索</a>:BBC纪录片,从南极到北极,从赤道到寒带,从非洲草原到热带雨林,再从荒凉峰顶到深邃大海,难以数计的生物以极其绝美的身姿呈现在世人面前。</li> <li>纪录片 | <a>但是还有书籍 (豆瓣)、</a><a>但是还有书籍 第二季 (豆瓣)</a>:在阅读多样化、碎片化的当下,记录这个时代形形色色的爱书之人,捕捉和书有关的那些精彩故事</li> <li>纪录片 | <a>人生第一次 (豆瓣)</a>:央视网系列人文纪录片《人生第一次》旨在通过蹲守拍摄,观察不同人群在人生重要节点的“第一次”:第一次上学、第一次上班、第一次走进军营,许多“第一次”串联起我们人生的重要节点,“初来乍到,请多关照”。</li> <li>纪录片 | <a>人生七年 - 电影 - 豆瓣搜索</a>:采访来自英国不同阶层的十四个七岁的小孩子,他们有的来自孤儿院有的是上层社会的小孩。此后每隔七年,艾普特都会重新采访当年的这些孩子,倾听他们的梦想,畅谈他们的生活。人生的轮回从这十四个七岁的孩子真实生活开始,他们天真无邪的脸上写满对生活的憧憬和渴望。<strong>“七岁看老”</strong>,在这童言无忌的问与答中,人生七年又七年,震撼上演。(截至2022年,从7UP,到63UP,已经拍摄了9部)</li> <li>纪录片 | <a>女人 Woman(豆瓣)</a>:走访50个国家,纪录2000名女性对自己的评价,构成了一幅巨大且撼动心灵的女性“自画像”。</li> </ul> <h3>提升效率:用 好工具、用好 工具🔨</h3> <ul> <li>工具 | <a>WIS微思博客</a>:多款在线智能工具、自定义地图空间可视化工具</li> <li>工具 | <a>超级简历</a>:免费 快速创建简历、海量模板</li> <li>工具 | <a>Tunefind</a>:电影和电视音乐查询网</li> <li>工具 | <a>zlibrary</a>:免费 电子书 搜索 下载</li> <li>工具 | <a>slidesgo</a>:海量 免费 PPT资源 下载</li> <li>工具 | <a>古诗文网</a>:古诗文经典传承</li> <li>工具 | <a>all to all</a>:在线 文档音视频图片 格式转换</li> </ul> <h3>提升物质:专业技能、工作投资💹</h3> <ul> <li>前端 | 一个Canvas3D动效<a>网页</a>案例</li> <li>前端 | <a>docx to html在线转换网站</a>(常用于网站隐私政策、用户协议等页面)</li> <li>行业 | <a>2022年的互联网行业</a></li> </ul> </content:encoded>
<category>信息源</category>
<comments>https://www.scarsu.com/monthly_9_2022_03/#post-comment/</comments>
</item>
<item>
<title>黄金投资新时代:黄金是永恒的硬通货</title>
<link>https://www.scarsu.com/gold/</link>
<guid isPermaLink="true">https://www.scarsu.com/gold/</guid>
<description>本书作者的两个重点:1.国际货币市场不久会崩溃;2.作者建议投资者趁早配置10%的流动资产投资实物黄金或者实物黄金基金。</description>
<pubDate>Wed, 30 Mar 2022 00:00:00 GMT</pubDate>
<content:encoded><h2>简介</h2> <p><img src="/images/picgo/20230709103730.png" alt="《黄金投资新时代》" /></p> <ul> <li>书名:黄金投资新时代</li> <li>原作名: The New Case for Gold</li> <li>作者:[美]詹姆斯·里卡兹 James Rickards</li> <li>译者:许余洁 吴海军</li> <li>出版时间:2016年4月</li> <li>ISBN:9787508693743</li> <li>封面:/images/picgo/20220331171131.png</li> <li>豆瓣链接:https://book.douban.com/subject/30353151/</li> <li>Amazon链接:https://www.amazon.com/New-Case-Gold-James-Rickards/dp/1101980761/</li> <li>思维导图:/images/picgo/20220331171755.png</li> </ul> <p>《黄金投资新时代》一书深入浅出地论述了黄金即货币的观点:当货币秩序紊乱时,黄金将起到重要的作用,即使并非单纯的定锚作用,也是重建货币体系中各国谈判的重要筹码。</p> <p>作者梳理历史,发现在面临国际货币体系失序和复杂的金融市场时,黄金的表现仍然非常稳健,拥有黄金是抵御当前经济环境和不稳定货币体系的保险和保障。</p> <h2>黄金即货币</h2> <h3>黄金是人类共识的财富资本</h3> <p>黄金是唯一具有作为货币所需的全部必要特性(稀缺性、延展性、惰性、耐用性和均匀性)的元素,可以作为可靠并且实用的价值贮藏物。</p> <p>黄金的历史1:18世纪经典的金币<strong>金本位</strong>在英国诞生以来,英镑、美元等信用货币先后依靠黄金的天然信用成为世界货币,黄金成为社会财富价值标准。</p> <p><img src="/images/picgo/20220401142123.png" alt="金本位" /></p> <p>黄金的历史2:二战即将结束时,多国遭受重创,金融和货币体系皆处于崩溃边缘。然而,美国却成为这次战争的最大受益者。大量黄金流入,令美国当时拥有世界黄金总储备量的大约75%。</p> <p>为了加强各国经贸合作,重建国际货币秩序,1944年7月,美国邀请44国政府代表共同确立了<strong>布雷顿森林体系</strong>:规定美元与黄金挂钩,<strong>每35美元兑换1盎司黄金</strong>,其他国家的货币与美元挂钩,只能通过美元同黄金发生联系。美元因此成为了国际货币体系的中心。</p> <p><img src="/images/picgo/20220401142259.png" alt="布雷顿森林体系" /></p> <p>黄金的历史3:19世纪末,美国关闭黄金与美元挂钩的窗口,把“黄金无用论”推上了巅峰。</p> <p>黄金的历史4:2008年国际金融危机以来,关注黄金又成为世界资本市场上的潮流。俄罗斯等多国央行增储黄金。</p> <p><img src="/images/picgo/20220401104259.png" alt="全球黄金储备分布" /></p> <p>图片来自<a>WGC-世界黄金协会</a>,在图中可以看到,全球黄金总储存量约19万吨,其中:</p> <ul> <li>黄金首饰约9万吨</li> <li>私人投资金约4万吨</li> <li>各国央行官方储备金约3.5万吨</li> <li>其余黄金约2.6万吨</li> </ul> <p>由金本位制度、到美元-黄金的布雷顿森林体系,到“非货币化”,再到当下社会对黄金的重视,足以说明:<strong>30多年来的黄金非货币化其实是人类的一次试错过程。</strong></p> <p>如今,包括美元在内的世界范围内的<strong>信用货币的信任危机</strong>在不断加深。黄金已经进入一个新的价值(价格)重估阶段。</p> <h3>黄金是“M小于0”(M-Subzero)货币</h3> <p>货币由3部分组成:交易的媒介、价值的储存和记账的单位。</p> <p>从技术层面讨论关于广义或者狭义的货币供应,如M3、M2、M1、M0等范畴。</p> <ul> <li>M0(货币)= 流通中的现金,M0也被称为“基础货币”,即流通于银行体系之外的现金(消费、终端市场</li> <li>M1(狭义货币)= M0 + 企业活期存款(现实购买力</li> <li>M2(广义货币) = M1 + 准货币(居民储蓄款 + 定期存款 + 其他存款)(投资和中间市场</li> <li>M3 = M2 + 金融债券 + 商业票据 + 大额可转让定期存单等</li> </ul> <p>作者把黄金称为“M小于0”(M-Subzero),因为<strong>即使经济学家们不予认可,黄金也是纸币背后真正的基础货币</strong>。</p> <h3>美联储不愿承认的事实:美元依赖黄金</h3> <p>“美联储”一般是指联邦储备银行体系,由12个独立的地区性联邦储备银行组成,每个银行都由该地区的私人银行所拥有。</p> <p>如果只考虑美联储的证券投资组合,美联储在2013年已濒临破产:</p> <ul> <li>表面上看,美联储并没有破产和资不抵债。在撰写本书时,美联储的资产负债表显示总资产约为4.49万亿美元,总负债约为4.45万亿美元,总资本(资产减负债)约为400亿美元。</li> <li>但是,美联储杠杆率很高(约合114∶1),杠杆放大了资本账户收益及损失的影响。美联储资产的损失只需要达到1%就可以彻底抵销其资本。</li> </ul> <p>然而,考虑到美联储隐藏的黄金资产,它从来没有资不抵债:</p> <ul> <li>美国财政部持有的黄金数量约为8000吨,大致相当于美联储在其资产负债表中所称的黄金数量——也是8000吨左右。</li> <li>隐形资产(黄金券)为美联储资本账户增加了3000亿美元,使得美联储的杠杆比率从114∶1降至一个更加合理的比例——13∶1,与大多数资本雄厚的银行的资本比率类似。</li> </ul> <p>美元决定了人们对全球金融体系的整体信心,对美元的信心依赖于美联储资产负债表的偿付能力,而这种偿付能力最终却依赖于黄金。</p> <p>这就是为什么虽然各国央行和政府都公开贬低黄金的重要性,但仍然将黄金储存在它们的保险库中。</p> <p><img src="/images/picgo/20220401142723.png" alt="" /></p> <h2>黄金是复杂经济局势下的保险</h2> <h3>作者为何判断国际货币市场不久会崩溃</h3> <p>作者在分析世界经济状况和经济崩溃的可能性时,使用了复杂性模型。然而,美联储却使用随机均衡模型。</p> <p>然而,经济并非一个均衡的体系,而是一个复杂的体系:</p> <ul> <li>由于网络自身的特性,网络之中存在着相互连接、相互作用和溢出效应的现象,这些现象导致了网络的复杂性。</li> <li>在一个复杂的系统中,如果你试图使用均衡模型实施策略,那么必定会错误百出。</li> <li>例如,2007年美国房地产崩溃,但是尽管平时美国房地产市场与日本股票市场本身没有关联,但美国住房贷款市场的困境导致日本股票市场同时大幅下滑。</li> <li>总而言之,全球经济状况 就如同复杂的网络系统,盘根错节,十分复杂</li> </ul> <h3>过去30年来,经济出现了极度的金融化</h3> <p>传统上,金融被用来促进贸易、生产制造业和商业的发展,它支持其他业务活动的开展,但<strong>金融业本身并不是目的所在</strong>。</p> <p>在2008年经济危机时期,美国经济中金融业约占股票市值的17%,占GDP的17%。对于一个促进性的行业来说,它的比例是巨大的,合理的比例应该是5%。</p> <p>这表示我们更倾向于从金融交易,而非从制造业、建筑业、农业和其他实体形式的生产中获得财富。</p> <p><strong>银行家用来提取财富的手段增加了复杂性,却没有增加价值</strong></p> <p>金融业本身并不能创造财富,它利用内部信息和政府补贴从其他行业中获取财富,这是一种寄生或所谓的“食利者”活动。</p> <p>在金融引发下一次经济危机之前,应该控制它的无序发展,控制措施包括分拆大银行、禁止大部分金融衍生品、限制货币供应等。</p> <p><img src="/images/picgo/20220401143508.png" alt="" /></p> <h3>美联储及其政策具有不可靠性</h3> <p>美联储是私人银行所有权与政府监管的不寻常混合体:</p> <ul> <li>在区域性的储备银行层面,联邦储备银行是私有的,美联储的下一层所属机构由位于全美主要经济中心的12家地区联邦储备银行组成。其中包括纽约联邦储备银行、波士顿联邦储备银行,以及费城,旧金山和达拉斯等联邦储备银行。这些区域储备银行并不属于美国政府所有。</li> <li>但整个系统的控制权仍掌握在由美国总统任命并经美国参议院确认的理事会中。</li> </ul> <p><img src="/images/picgo/20220401143955.png" alt="" /></p> <p>美联储执行政策普遍失败:</p> <ul> <li>美联储可以通过公开市场操作直接控制所谓的“政策利率”,也就是<strong>联邦基金利率</strong>,美联储通过调节这一利率来达到一个目的——保持美国最大限度的就业和物价稳定。</li> <li>如果<strong>加息</strong>,这一利率升高,银行在给企业或个人放贷时的利率也水涨船高,此举可以减少货币供给量,降低通胀,从而给经济降温。</li> <li>反之,如果<strong>降息</strong>,银行放贷的利率就会降低,借钱成本更低,将刺激企业和个人贷款,一般来讲,整体经济得到刺激,变得更加活跃。</li> <li>自2008年以来,美联储已有15个不同版本的政策去调控利率,按照作者的原话“这并不是一个训练有素而严谨的实验,美联储只是走一步算一步,随着时间的推移对此加以弥补。”</li> </ul> <h3>个人投资者的最保险的投资就是黄金</h3> <ul> <li>互联网金融战争</li> </ul> <p>2013年8月22日,纳斯达克停业了半天。4年后,媒体报道了原因:俄罗斯政府向纳斯达克操作系统植入了攻击病毒。</p> <p>因此互联网金融战争威胁的存在,是拥有黄金的另一个原因,因为黄金不是数字化的,不能被黑客攻击或抹除。</p> <ul> <li>现金之战</li> </ul> <p>除了货币战争和金融战争之外,美国还出现了针对现金的战争。这种对自由使用现金权利的攻击,是在经济不确定时期考虑投资实物黄金的另一个理由。</p> <p>一个完全数字化的系统正在为负利率的经济体系铺路;取消现金也使得强制保释、征收和冻结账户变得更加容易。</p> <p><strong>从金币到黄金担保支持的纸币,再到法定货币,之后到数字货币的整个过程,已经花费了大约100年的时间。在此过程中的每一个步骤,都让政府更容易征收你的财富。</strong></p> <p>因此黄金作为一种实物财富,有保值的效果,并且可以不受其他形式的货币数字化的影响。</p> <h3>无论是通货膨胀、还是通货紧缩,黄金都是保值的</h3> <p>通货膨胀的情况下,物价上涨,金价上涨,黄金的保值是显而易见的。</p> <p>通货紧缩的情况下,如果黄金的名义价格下跌,那么其他商品的名义价格下跌更多,如果以实际价格来衡量,黄金仍然是保值的。</p> <h3>美元霸权力量减弱</h3> <ul> <li>世界对美元的信心正在减弱:</li> </ul> <p>自2010年以来,美国政府实际上已经放弃了稳健的美元。当年1月,美国结束了自1980年以来盛行的稳健美元政策。一项旨在鼓励通货膨胀和名义增长的货币贬值政策开始实施。廉价的美元策略引发了一场货币战争。</p> <p>世界各地有许多活动旨在削弱美元作为全球储备货币的地位。我们有太多的贸易伙伴和金融投资伙伴已经对美元失去了信心,并对美国利用美元的地位来维持赤字和印钞补缺的方式感到不满。</p> <p>外资银行也正在尽快摆脱美元体系。</p> <ul> <li>多个国际力量都希望结束国际货币体系中的美元霸权:</li> </ul> <p>俄罗斯、伊朗、中国都先后遭到过美国的经济制裁;</p> <p>2014年 俄罗斯和中国、伊朗分别签署了石油贸易协议;</p> <p>俄罗斯本身是石油出产国,但是俄罗斯同意购买伊朗的石油;由于美国的制裁,伊朗还不能轻易地在公开市场上出售石油;因此俄罗斯可以进口伊朗的石油,担当伊朗向其他国家出售石油的中间人;</p> <p>而中国与瑞士进行了货币互换;因此中国向俄罗斯购买石油后,可以用瑞士法郎支付给俄罗斯;俄罗斯可以通过其他国家转换瑞士货币;</p> <p>这样的贸易链接,完全跳过了美元。</p> <h2>金价起伏,但是黄金的价值永恒不变</h2> <h3>黄金的“价格”</h3> <p><img src="/images/picgo/20220401144229.png" alt="1970年来的黄金价格" /></p> <p>黄金的美元价格的“上涨、下跌”,其实意味着美元货币价值的“下跌、上涨”。</p> <p>作者对黄金投资者的建议:应该关注的是黄金的重量,而不是黄金的价格。</p> <p>实物金价会遭到来自纸黄金市场的压制,但实际上,<strong>实物金比纸黄金价值更高</strong>:</p> <ul> <li>黄金的衍生品——期货、掉期、ETF、租赁、远期和未分配黄金构成纸黄金市场。</li> <li>纸黄金市场很可能有实物黄金市场的百倍之大,如果一直有双向市场、价格行为不混乱、人们愿意不断滚动契约、人们不坚持实物交割,杠杆化的纸黄金系统就可以有序运转。</li> <li>实物金价会遭到来自纸黄金市场的压制,但是如上所述,纸黄金市场存在过高的杠杆、意味着过高的风险,一旦黄金实物交割的任何意外中断都可能引发买盘恐慌、金价暴涨。</li> </ul> <h3>操纵金价的力量</h3> <p>金价操纵是千真万确存在的。在没有相关消息的情况下,当我们看到金价大幅下跌时,我们可以合理推断出黄金市场正在被人操纵着。</p> <p>操纵金价的途径有很多,例如抛售实物金、纸黄金操纵、对冲基金操纵、租赁未分配远期合约,或是以上途径的组合操纵。</p> <p>美联储希望美元走弱:</p> <ul> <li>美元贬值会导致进口成本上升,这有助于美联储实现其通胀目标</li> <li>美元疲软原则上意味着黄金价格上涨</li> <li>美联储希望金价有条不紊的上涨,但不希望金价无序增长,因此需要操纵金价走低。</li> </ul> <p>中国希望金价走低:</p> <ul> <li>中国拥有数万亿美元的美国国债</li> <li>如果美国达到它所希冀的通货膨胀率,美元走低,中国持有的美国国债就会贬值</li> <li>但是美元走低,黄金就会涨价,持有的黄金价值会更高。</li> <li>因此持有美国国债和黄金是保护中国财富的一种对冲方式。</li> </ul> <h3>对抗操纵?</h3> <p>如上所述,复杂莫测的原因导致实物黄金的“价格”起起伏伏,实物金投资者应该如何对抗操纵?</p> <p>作者的建议是:</p> <ul> <li>任何金价控制都需要实物黄金;实物黄金是有限的;对金价的操纵控制是有极限的。最终,价格控制者的实物黄金将消耗殆尽,或通货膨胀预期的变化将导致金价飙升,甚至连政府都无法控制。</li> <li>因此无需对抗操纵,即使金价起伏,实物金的价值也是永恒不变的。</li> <li><strong>投资者应该忽略金价的起伏,长期购买和持有黄金,以在突如其来的金融震荡和恐慌情况下达到财富保值的效果。因为我们的目标不是通过交易头寸来快速获利,而是财富长期保值。</strong></li> </ul> <h2>如何投资黄金</h2> <p>作者的建议是:<strong>现在就投资黄金,将流动资产的10%配置为黄金,并将其妥善存放在安全的地方</strong>。</p> <p>除此之外,我总结了国内投资者购买实物金的几种途径:</p> <ul> <li>上海金交所,但此渠道已经对个人买家关闭(2022年,金交所已经取消了个人用户注册,各大银行的代理交易通道也被关闭了)</li> <li>各大金店实物金,溢价较高(例如2022年4月1日金交所大盘价394,四大珠宝品牌中谢瑞麟、周生生、周大福金条价是502,首饰金价是512,还要另外收几十~上百每克的工费)</li> <li>银行实物金,大多数基础投资金条价格是大盘价+10~30元/g工费</li> <li>各大电商平台黄金卖家,出售大盘价格+5元/g工费的实物金、金条、板料</li> </ul> <h2>关于黄金的有趣知识</h2> <ul> <li>自人类文明以来,开采了约<strong>18.72万</strong>吨黄金</li> <li>世界海洋中的含金量被预估为<strong>1.5万吨</strong></li> <li>世界上**90%**的黄金已经被开采</li> <li>被开采的黄金中,有**49%**被用于首饰</li> <li>已被开采的所有黄金,可以装进一个<strong>21立方米</strong>的箱子中。</li> <li>黄金的熔点是<strong>1064摄氏度</strong></li> <li>国外通常使用盎司Oz作为单位衡量黄金的重量,<strong>1Oz=31.103g</strong></li> <li>伦敦金交所的标准交易金条重量是<strong>400盎司</strong></li> <li>中国上海金交所的标准交割金条重量是<strong>1kg</strong></li> </ul> <p><a>以上数据来源: www.gold.org</a></p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/gold/#post-comment/</comments>
</item>
<item>
<title>月刊#8 | 2022.02</title>
<link>https://www.scarsu.com/monthly_8_2022_02/</link>
<guid isPermaLink="true">https://www.scarsu.com/monthly_8_2022_02/</guid>
<description>书单、自我管理、心理、健康、工具、经济、投资、前端开发</description>
<pubDate>Mon, 28 Feb 2022 00:00:00 GMT</pubDate>
<content:encoded><p>💡 <a>信息源分类整理 | 往期合集 | 持续更新</a></p> <hr /> <h3>提升认知:信息输入、知识管理🧠</h3> <ul> <li>书单 | <a>2021年读了162本书,向你推荐这些 - 36Kr</a></li> </ul> <h3>提升体验:身心舒适、自律极简😃</h3> <ul> <li>自我管理 | <a>个人生活的数字化与可视化表达</a></li> <li>健康 | <a>适当的咖啡因可以降低身体内的“坏”胆固醇</a></li> <li>心理 | <a>如何提升内心的充实感</a></li> <li>厨艺 | <a>程序员在家做饭指南</a></li> </ul> <h3>提升效率:用 好工具、用好 工具🔨</h3> <ul> <li>工具推荐 | <a>生产力开发工具</a></li> <li>浏览器插件 | <a>omni:书签、历史、tab页管理</a></li> <li>文章 | <a>快速打字是一项高杠杆技能</a></li> <li>打字 | <a>在线打字训练TIPP10 Online Typing Tutor</a></li> <li>打字 | <a>打字速度测试Typing Test · Improve your WPM speed</a></li> <li>打字 | <a>打字训练 Typing Practice</a></li> <li>打字 | <a>在线打字竞速游戏 TypeRacer</a></li> <li>打字 | <a>在线打字训练 Monkeytype</a></li> </ul> <h3>提升物质:专业技能、工作投资💹</h3> <ul> <li>投资 | <a>黄金市场分析 &amp; 投资黄金的几种方式</a></li> <li>经济 | <a>为什么美联储一提加息,市场就慌了? - 知乎</a></li> <li>经济 | <a>出国劳务在日本打工到底有多累? - 知乎</a>:现代奴隶制度</li> <li>经济 | <a>1993 年左右发生的人民币大贬值是怎么回事? - 知乎</a></li> <li>经济 | <a>《爱情公寓》中唐悠悠用 18 张信用卡相互还债保持平衡的方式科学吗? - 知乎</a></li> <li>职场 | <a>十年内远程工作会普及吗?</a></li> <li>开发 | <a>开发者路线图</a></li> <li>前端 | <a>State of avaScript 2021</a></li> <li>前端 | <a>如何阅读ECMAScript标准</a></li> <li>前端 | <a>vue-naive-admin</a>:Vite+Vue3+NaiveUI+Pinia后台管理模板</li> <li>前端 | <a>baidu/amis: 前端低代码框架,通过 JSON 配置就能生成各种页面。</a></li> <li>前端 | <a>tencentyun/TUIChorus: 腾讯云TRTC针对直播、语聊、视频通话等推出的低代码解决方案~</a></li> <li>前端 | <a>技术周报·为什么说 WebAssembly 是 Web 的未来 - 掘金</a></li> <li>前端 | <a>字节的一个小问题:npm 和 yarn不一样吗? - 掘金</a></li> <li>前端 | <a>我的前端性能优化知识体系 - 掘金</a></li> <li>前端 | <a>解释Twitter的前十行代码 - CSS Tricks</a></li> <li>前端 | <a>7篇Web性能的新文章 - CSS Tricks</a></li> <li>前端 | <a>DOM中,Node和Element的区别</a>:Object&gt;EventTarget&gt;Node&gt;Element&gt;HTMLElement&gt;HTMLDivElement</li> <li>前端 | <a>用Vercel一键部署静态网站</a></li> <li>前端 | <a>微前端落地</a></li> </ul> </content:encoded>
<category>信息源</category>
<comments>https://www.scarsu.com/monthly_8_2022_02/#post-comment/</comments>
</item>
<item>
<title>高敏感是种天赋:HSP自救指南</title>
<link>https://www.scarsu.com/hsp/</link>
<guid isPermaLink="true">https://www.scarsu.com/hsp/</guid>
<description>敏感是与生俱来的特质,肯定自己的独特、感受更多、想象更多、创造更多</description>
<pubDate>Fri, 25 Feb 2022 00:00:00 GMT</pubDate>
<content:encoded><p><img src="/images/picgo/20220215104940.png" alt="《高敏感是种天赋》" /></p> <h2>简介</h2> <ul> <li>书名:《高敏感是种天赋》</li> <li>原名:《Highly Sensitive People in an Insensitive World》</li> <li>作者:[丹麦]伊尔斯·桑德</li> <li>ISBN:9787559608710</li> <li>豆瓣链接:https://book.douban.com/subject/27125070/</li> <li>思维导图:/images/picgo/2022HSP.png</li> </ul> <p><code>HSP</code>是<code>Highly Sensitive People</code>,高敏感人群。</p> <ul> <li>如果你无法长时间待在热闹的环境</li> <li>如果你被人指责过于敏感</li> <li>如果你因为对信息过于敏感,以致于大脑“硬盘”很快就被填满、意识失去秩序</li> <li>如果你因为高度共情,而常常被别人的情绪影响</li> <li>如果你拥有过度的责任感、总是努力避免给他人带来不便或痛苦、甚至常常自责</li> <li>如果你即使独处也能拥有丰富的内心世界</li> <li>如果你行事谨慎、提前考虑好每个细节,想象所有可能的风险,并准备好对应的解决方案</li> </ul> <p>如果以上的特征之一与你相符,那么我推荐你看看这本书。</p> <p>我从前常常产生自我怀疑:是否自己过于敏感?</p> <p>看完了作者在本书中介绍的<code>HSP</code>的特质,才认知到自己是高敏感人群的一员。</p> <p>本书的作者是心理治疗师,丹麦奥胡斯大学神学硕士,硕士论文以卡尔•荣格与索伦•克尔凯郭尔为主要研究方向。</p> <p>书中的<code>HSP</code><strong>如何自处、如何自我疗愈、如何应对人际交往</strong>等方法,让我受益良多。</p> <h2>如何判断自己是否高敏感</h2> <h3>发达的神经系统</h3> <p>高敏感人群拥有发达的神经系统,听觉、视觉、触觉、嗅觉等感官可能较敏感,能感知更多的信息。</p> <p>因此,高敏感人群可以感知到事物细微的差别,并对信息进行更深入的加工。</p> <p>我们拥有活跃的想象力和丰富的内心世界,这意味着我们从外部世界接收和感知到的信息,会触发大脑里各种概念、想法并建立联结。</p> <p>这也会导致我们的大脑“硬盘”很快就被填满,不堪重负。</p> <h3>高度共情,容易受别人的情绪影响</h3> <p>能给予别人共情式的倾听;</p> <p>在帮助和照顾他人方面十分尽心;</p> <p>对别人的情绪也非常敏感;</p> <p>但是,并不擅长将自己从他人的痛苦中抽离出来</p> <h3>拥有强烈的责任感</h3> <p>许多高度敏感型人都有着强烈的责任感,认为自己需要承担整个世界的责任。</p> <p>研究显示,与一般4岁左右的儿童相比,抑制性(敏感性)的儿童更少欺骗他人、破坏规则或者做出自私的行为。</p> <p>高度敏感型人总是努力避免给他人带来不便或痛苦。他们也花更多精力去维持与他人的关系。</p> <p>但是,有时学着后退一步,让他人负责,使之从错误中汲取教训或许会更好。</p> <h3>拥有更加丰盛的内在世界</h3> <p><code>HSP</code>享受宁静的生活,独自一人时,很少感到孤独无聊,甚至享受其中。</p> <p>敏感者们的意识和无意识之间的间隔太过无力,无意识的意念和想法很容易在他们进行创作或者编织梦想时闯入大脑,变得清晰可见。</p> <p>有时候能思如泉涌,并不需要特别激励。这股天生的动力可谓是价值连城的财富,当然,前提是你懂得如何利用它。</p> <h3>谨慎</h3> <p><code>HSP</code>倾向于提前考虑好每个细节,想象所有可能的风险,并准备好对应的解决方案。</p> <p>这虽然会降低你出错的概率,但是,它也会降低你对事物的接受速度。</p> <p>可能使你长期处于担心焦虑的状态</p> <h3>附录2:敏感度指数测试</h3> <p><a>https://weread.qq.com/web/reader/95e323805dfeb195e2928b1k1c3321802231c383cd30bb3</a></p> <h2>高敏感是与生俱来的</h2> <p>有些人生而敏感,其敏感性是与生俱来的,遗传因素比环境和教养的影响更大。</p> <p>研究表明,这些高敏感人群的比例是20%。</p> <ul> <li>敏感不是缺陷,相反,它可以丰富你的人格。</li> </ul> <p>高度敏感型是不同特质的复杂结合体:<strong>尽责、创造、积极向上、易受影响、共情,敏感的感觉</strong>和<strong>脆弱的神经系统</strong>等等。</p> <p>这些特质会给敏感型人的生活带来些许麻烦,但也会是创造性、专注力和同理心之源。</p> <blockquote> <p>高度敏感可以极大地丰富我们的人格特点……只有在糟糕或者异常的情况出现时,它的优势才会转变成明显的劣势,因为那些不合时宜的影响因素让我们无法进行冷静的思考。 没有比把高度敏感归为一种病理特征更离谱的事。如果真是这样,那世界上25%的人都是病态的了。</p> <p>——荣格(C.G. Jung)</p> </blockquote> <p>因此,作为<code>HSP</code>,我们应该客观看待自己,可以将<strong>敏感</strong>一词,视为中性词,不贬不褒。</p> <ul> <li>我们天生比别人拥有更敏感的感官、神经,如果妥善利用,<strong>敏感</strong>就是我们天生的优势。</li> <li>在糟糕的环境中,我们比别人更容易感到疲惫,如果我们知道这一点,并合理安排自己的生活,也可以最大程度的避免糟糕的体验。</li> </ul> <h2>HSP应该如何自处</h2> <h3>了解自己、接纳自己、爱自己</h3> <p>正如前文所说,高敏感是与生俱来的。</p> <p>我们应该客观地看待自己和周围的世界。</p> <p>和过去和解、和自己和解。意识到并理解自己的敏感性,选择让自己最舒服的方法。</p> <blockquote> <p>你越是接受自己是一个什么样的人,你越不需要花太多精力去让自己适应</p> </blockquote> <p>关切自己,同情自己,给予自己支持和鼓励。</p> <p>学着接受自己,肯定自己的独特、感受更多、想象更多、创造更多。</p> <h3>停止内耗、跳出恶性循环</h3> <p>典型的高度敏感型的人都存在低自尊问题,并且尝试通过设定高标准来弥补自己的缺点。</p> <p>也因此容易陷入恶性循环:</p> <p><img src="/images/picgo/20220216162847.png" alt="恶性循环" /></p> <p>跳出恶性循环的方法,就是做真实的自己,接纳自我、正视自我,<strong>设定与自身能力相匹配的目标</strong>。</p> <p>为自己设定一些可实现的目标:</p> <ul> <li>比如早早起床、做顿早饭。</li> <li>简单的事就可以为自己带来积极的体验。</li> <li>列出一份心愿清单,当感觉心情低落时,找点清单上的事情做,完成它们会带来极大的快乐。</li> </ul> <h3>合理处理冲突、愤怒、内疚、羞耻</h3> <ul> <li> <p>愤怒有害无利,冷静下来</p> <p>当愤怒值达到顶峰时将其发泄出来并不是件好事;</p> <p>如果你的愤怒给别人带来伤害,你也会感到痛苦,无法忽视内心强烈的自责感。这会刺痛你的神经,使你受困于内疚和自责的牢笼。</p> <p>清楚地说出“不”“我不想做”或者“我不能接受”常常比直接表达愤怒更有效。</p> <p>在冲突中,叫停、休战,确定重新沟通的时间,各自冷静</p> </li> <li> <p>共情,发现愤怒背后的需求</p> <p>愤怒常常只是人们保护自己的盔甲。愤怒之下,往往隐藏着许多其他脆弱的情感。</p> <p>发现隐藏在愤怒背后的情绪、根源。</p> </li> <li> <p>明确边界</p> <p>认真观察,勇于表达,最后不带偏颇地讲出自己感知到的信息。</p> <p>为自己设置界限,明确要求对方停止对你做出的行为。</p> </li> <li> <p>转愤怒为悲伤</p> <p>愤怒往往出现在期望未被实现或者需求未被满足之时。</p> <p>与愤怒不同的是,悲痛的优势在于它可以唤起别人的同情,得到别人的支持。</p> <p>可能的话,放下未得到满足的期望,启动悲伤程序,引导对方与你共情。</p> <p>从“应该”到“希望”,从愤怒到悲伤。</p> </li> <li> <p>合理内疚</p> <p>内疚其实是一种<strong>面向自己的愤怒</strong>,可以视为一种对自己的无能为力和悲伤情绪的防御方式。</p> <p>如果你的内疚感和你的行为所带来的影响之间是成比例的,那么你的内疚就是合理的。</p> <p>如果你对那些你并没有产生任何实质性的影响或者根本无法人为控制的事感到内疚,那么这种内疚感就是多余的。</p> <p>如果是合理的内疚,对承受方 表达歉意、做出补偿,及时消除内疚感。</p> <p>如果是不合理的内疚,那就勇敢直面生活的不确定性和自己的无能为力,打破“非黑即白”的世界观;详尽列举出糟糕状态的所有原因,找出只属于自己责任的那部分。</p> </li> <li> <p>及时止损,远离不健康的人际关系</p> <p>有时候,人际关系不顺利,并不是自己的问题。</p> <p>如果尝试过上述方法后,仍然不起作用。</p> <p>那么应该重新思考一下,你们的关系给你们双方带来了什么?是否要继续维持你们的关系?</p> </li> </ul> <h3>精神断舍离</h3> <ul> <li>清晰地设定边界、表达不满</li> <li>留出独处时间</li> <li>减少信息刺激的输入</li> <li>做一些疗愈的事情</li> <li>给自己适当的独处时间</li> <li>向伴侣表达明确需求:希望ta尊重你的敏感型人格</li> </ul> <h2>人际交往的技巧</h2> <h3>高质量互动</h3> <p>在高质量的互动下,情感的交流就会代替信息刺激,给高敏感人群更好的体验。</p> <p>如果自己是倾听者,要给予对方反馈,适当表达自己。</p> <p>如果自己是表达者,要寻找方法获得对方回应,例如提问对方如何看待你、分享想法和感受、进一步追问等。</p> <h3>掌控对话:设定对话界限</h3> <p>设置好对话的界限,当人际交流中感到疲惫、不适时,将注意力返回到自己身上,避免在对话中被信息吞噬。</p> <h3>掌控对话:控制聊天深度</h3> <p>不同的聊天深度适合不同的场景。</p> <p>深入的聊天,引人入胜,可以带来情感的体验。</p> <p>想要很深度的聊天,有两个技巧:</p> <ol> <li>沉默,可以在无形之中增加对话的深度。</li> <li>从泛泛而谈转变到具有针对性的交流。</li> <li>追问。</li> </ol> <p>浅聊,适合初识、短时间的交际场景,有时候,需要及时避免对话变得更深,在必要的时候能成功地将深入的对话带回到表面,轻松地结束对话;</p> <p>浅聊的技巧:使用一些概括性或者解释性的语言(俗称糊弄、敷衍😂</p> <h3>掌控对话:灵活切换于对话的四个层次</h3> <ul> <li>层次1:短对话。</li> </ul> <p>短对话的优点是,你很容易开始一个话题,结束一个话题也非常轻松。如果你对你们的对话并不满意,你也可以很快从对话中脱身</p> <p>适合不熟悉的人,作为互相认识的敲门砖。</p> <p>结识一个新的人方法,就是建立你和ta之间的纽带</p> <p>可以直接直接讲讲自己当前的感觉,包括味觉、嗅觉、听觉、视觉</p> <p>重要的不是你说了什么,而是你说话的语气,让对方感受到你们还有进一步交流的空间</p> <ul> <li>层次2:角色层次,寻找共同兴趣。</li> </ul> <p>根据某个特定角色来展现自己,例如介绍自己的职业、家庭</p> <p>寻找共同的兴趣,交换信息、想法、意见,讨论政治、家庭以及其他有意思的东西</p> <p>从第1层次到第2层次,可以延长每个话题的停留时间。例如:对食物的一点意见就可能将话题切换到对食谱的探究;对天气的简单点评也可能发展到对气候的讨论。当然,你也可以提出一个新的话题。</p> <p>达成一致,定下约定。</p> <ul> <li>层次3:情感层次,让对方踏入你的秘密空间。</li> </ul> <p>分享一些个人经历,将对方带入到你的秘密空间</p> <p>聊一些自己关于人和事的经历和感受</p> <p>分享你的童年、婚姻、同事关系和家庭关系、流言蜚语、八卦新闻</p> <p>分享自己的内心世界</p> <ul> <li>层次4:坦诚相待。</li> </ul> <p>先确认对方是否真的想跟你进行如此深入的对话</p> <p>讨论两者之间的关系:我和你,此时此刻,是如何看待对方的。</p> <p>例如:我想跟你聊一聊我们之间的感觉。可以吗?我很想跟你聊一聊此刻我对你的感觉。你愿意听吗?我想知道你对我的感觉。你愿意告诉我吗?</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/hsp/#post-comment/</comments>
</item>
<item>
<title>月刊#7 | 2022.01</title>
<link>https://www.scarsu.com/monthly_7_2022_01/</link>
<guid isPermaLink="true">https://www.scarsu.com/monthly_7_2022_01/</guid>
<description>2021年度书单、纪录片推荐、播客、职场、行业、前端、家居、种草、工具</description>
<pubDate>Mon, 31 Jan 2022 00:00:00 GMT</pubDate>
<content:encoded><p>💡 <a>信息源分类整理 | 往期合集 | 持续更新</a></p> <hr /> <h3>认知提升 | 读书 | 信息源 | 知识管理 🧠</h3> <ul> <li>【话题】每个人的缺点,都会在与最亲近的人相处时放大显现。</li> <li>【话题】<a>我们一生中不同阶段需要放弃的东西</a> - 《少有人走的路》</li> <li>【话题】<a>为什么有些垂直技术领域看不到好文章</a> - <a>余杭子曰</a></li> <li>【TED演讲】读书是为了什么 <a>思维导图</a> - <a>余杭子曰</a></li> <li>【文章推荐】<a>happy xiao:2021改变我人生的那些文章</a></li> <li>【知识管理】<a>一个信息流管理方案</a>:RSS、Inoreader、简悦、Obsidian、Notion</li> <li>【播客】<a>有趣的中文播客推荐?</a></li> <li>【播客】<a>全种类播客推荐</a></li> </ul> <h3>纪录片 | 电视节目 📺</h3> <ul> <li>央视纪录片<a>《基金》</a>,基金投资必看</li> <li>我们究竟有多轻,上下五千年 - 央视纪录片<a>《国家宝藏》</a></li> <li>电视节目<a>《锵锵行天下》</a>,窦文涛深度聊天</li> <li>电视节目<a>《很高兴认识你》</a>,在疗愈时光里与生活对话</li> <li><a>《但是还有书籍》</a>纪录片,快时代里的阅读指南</li> <li>为情所困<a>《梁永安爱情问答》</a></li> <li>拓展知识边界、开阔心胸和格局,访谈节目<a>《十三邀》</a></li> <li>拖延、焦虑<a>《某某与我》呼兰篇</a></li> <li>内耗严重、身心俱疲、找不到人生目标与意义<a>《梁永安从“小镇做题家“到”窄人“》</a></li> <li>【财富】电视节目<a>《隐姓亿万富翁》</a>,亿万富翁再现如何从贫穷汉到价值百万公司的总裁</li> <li>【财富】电影<a>《金钱与我》</a>,消费节流的方法</li> <li>【财富】纪录片<a>《富哥哥穷弟弟》</a>,相同背景走出的不同人生</li> <li>【财富】纪录片<a>《金钱通解》</a>,经济骗局</li> <li>【财富】纪录片<a>《成为沃伦巴菲特》</a></li> <li>【财富】纪录片<a>《无节制消费的元凶》</a>,资本主义的三大毒药:性开放、成功学、消费主义。</li> </ul> <h3>2021年度书籍榜单 📔</h3> <ul> <li><a>kindle电子书2021年度榜单(中国)</a>: <ul> <li>蛤蟆先生看心理医生</li> <li>被讨厌的勇气</li> <li>三体</li> <li>消失的13级台阶</li> <li>百年孤独</li> <li>别想太多啦</li> <li>绝叫</li> <li>活着、无人生还</li> <li>毛泽东选集</li> </ul> </li> <li><a>2021微信阅读年度书单</a>: <ul> <li>《疫苗竞赛》</li> <li>《狂人日记》(2月觉醒年代热播)</li> <li>《棉花帝国》(3月H&amp;M发布声明抵制新疆棉)</li> <li>《切尔诺贝利的午夜》(4月日本决议投放核废水)</li> <li>《袁隆平的世界》(5月袁隆平逝世)</li> <li>《人口大逆转》(6月“三孩政策”)</li> <li>《漫画百年党史·开天辟地1921-1949》(7月中共建党100周年)</li> <li>《无规则游戏:阿富汗屡被中断的历史》(8月塔利班在时隔20年后重新掌控阿富汗)</li> <li>《论中国》(9月孟晚舟在加拿大被拘1028天后回归祖国)</li> <li>《血战长津湖》(10月电影《长津湖》拿下年度票房冠军)</li> <li>《罪与罚》(11月陀思妥耶夫斯基诞辰200周年)</li> <li>《煤气灯效应》(12月王力宏婚变事件让“gaslighting”这个词进入公众视野)</li> </ul> </li> </ul> <h3>自我管理 | 心智提升 | 意识秩序 | 极简低消 | 健康生活 😃</h3> <ul> <li>【时间管理】<a>人与人的差距,是由第3个8️⃣小时创造的</a></li> <li>【健康】<a>2021跑步总结 - 来自一位365天全勤跑步的大佬</a></li> <li>【种草&amp;排雷】<a>2021 你买的最值和最不值的东西是? - V2EX</a></li> <li>【2022年初Flag大赏】<a>大家 2022 年的第一个挑战是什么? - V2EX</a></li> <li>【维权】<a>一次12315维权经历</a></li> <li>【家居】<a>强弱电箱遮丑案例</a></li> </ul> <h3>用 好工具 | 用好 工具 🔨</h3> <ul> <li>【App - 你我当年】:修复模糊照片</li> </ul> <h3>技术 | 职场 | 财富 💹</h3> <ul> <li>【职场】<a>年终总结怎么写?</a></li> <li>【行业】<a>成功转型的初创公司列表</a></li> <li>【行业】<a>下一个 10 年,将会发生的 12 个趋势</a></li> <li>【行业】<a>2022年,互联网10大关键词</a></li> <li>【行业】<a>2021全球最受欢迎域名榜单,Tiktok取代Google成为第一</a></li> <li>【前端】<a>ES2016-ES2021知识点</a></li> <li>【前端】<a>前端监控系统设计 - 掘金</a></li> <li>【前端】<a>2022 年需要关注的几个前端技术 - 掘金</a></li> <li>【前端】<a>CSS-Based Fingerprinting | CSS-Tricks - CSS-Tricks</a></li> <li>【前端】<a>Defensive CSS | CSS-Tricks - CSS-Tricks</a></li> <li>【前端】<a>浅析我们为什么要上Vue3? - 掘金</a></li> <li>【前端】<a>下一代CSS:@container</a></li> <li>【前端】<a>web components组件库</a></li> <li>【前端】<a>css + svg 实现极光特效</a></li> <li>【前端】<a>低代码行业现状简析-凹凸实验室 京东</a></li> <li>【前端】<a>对2D图片实现3D效果</a></li> <li>【前端】<a>腾讯UI套件: TDesign</a>(支持vue2、3、react、angular;并内置于设计工具<a>pixso</a>中</li> <li>【前端电子书】:<a>给不耐烦的JS程序员看的ES2022</a> - The ECMAScript 2022 edition of “JavaScript for impatient programmers”</li> <li>【前端】<a>如何在产环境debug</a>:global search、添加本地sourceMap、local overrides</li> </ul> </content:encoded>
<category>信息源</category>
<comments>https://www.scarsu.com/monthly_7_2022_01/#post-comment/</comments>
</item>
<item>
<title>少有人走的路:心智成熟的旅程</title>
<link>https://www.scarsu.com/the_road_less_traveled/</link>
<guid isPermaLink="true">https://www.scarsu.com/the_road_less_traveled/</guid>
<description>自律就是解决人生问题最主要的工具,也是消除人生痛苦最重要的方法。爱是自律的原动力。</description>
<pubDate>Tue, 25 Jan 2022 00:00:00 GMT</pubDate>
<content:encoded><h2>简介</h2> <p><img src="/images/picgo/less-road.png" alt="《少有人走的路:心智成熟的旅程》" /></p> <ul> <li>原名:The Road Less Traveled</li> <li>作者:[美]M.斯科特·派克</li> <li>ISBN:978-7-5158-1979-2</li> <li>豆瓣链接:https://book.douban.com/subject/35442753/</li> <li>思维导图:/images/picgo/less-road-note.png</li> </ul> <p>在这本书中,作者结合“自律、爱”等话题,阐明了如何在人生这一场艰辛之旅中,经历一系列艰难乃至痛苦的转变,促进心智成熟,最终达到自我认知的更高境界。</p> <h2>人生苦难重重</h2> <p>人生苦难重重————这是作者写在正文中的第一句话。</p> <p>前段时间看了<a>《逆商》</a>、<a>《心流》</a>这两本书,作者都有着类似的观点。</p> <p>《心流》中说:宇宙初创之时,就没有以人类的安逸舒适为念;自然选择出的基因和生理机制只是服务于人类生存繁衍,没有增加幸福快乐的考虑。</p> <p>《逆商》中说:人生就是要面对一个又一个逆境。</p> <p>本书作者说:<strong>人生就是一个不断面对问题解决问题的过程</strong>。</p> <blockquote> <p>人生苦难重重。这是个伟大的真理,是世界上最伟大的真理之一。</p> <p>它的伟大之处在于,一旦我们领悟了这句话的真谛,就能从苦难中解脱出来,实现人生的超越。</p> <p>只要我们真正理解并接受了人生苦难重重的事实,那么我们就会释然,再也不会对人生的苦难耿耿于怀了。</p> </blockquote> <p>回避问题和逃避痛苦的倾向,是人类心理疾病的根源。</p> <h2>自律</h2> <p>自律就是解决人生问题最主要的工具,也是消除人生痛苦最重要的方法。</p> <blockquote> <p>所谓自律,就是主动要求自己以积极的态度去承受痛苦,解决问题。</p> </blockquote> <p>心灵在承受痛苦和解决问题的过程中,会不断地成长和成熟。</p> <p>所以,自律是人们心灵进化最重要的手段和工具。</p> <h3>自律原则1:推迟满足感</h3> <p>不贪图暂时的安逸,先苦后甜,重新设置人生快乐与痛苦的次序。</p> <p>不逃避问题,不拖延:</p> <ul> <li>问题拖得越久,就越是积重难返。</li> <li>问题带来痛苦,尽早的直面问题,把满足感向后推迟,放弃暂时的安逸或是程度较轻的痛苦,去体验程度较大的痛苦,这才是对待问题和痛苦最明智的办法。</li> </ul> <p>对自我价值的认可也是自律的基础:</p> <ul> <li>当一个人觉得自己很有价值时,就会采取一切必要的措施来照顾自己。</li> <li>自律是自我照顾,自我珍惜,而不是自暴自弃、贪图安逸。</li> </ul> <h3>自律原则2:承担责任</h3> <p>必须面对属于自己的问题,而不是推卸责任。</p> <p>过度承担责任、或者推卸责任,都是心理疾病:</p> <ul> <li>神经官能症患者为自己强加责任;</li> <li>人格失调症患者不愿承担原本属于自己的责任。</li> </ul> <p>自己承担责任,就可以掌控自己的自由:</p> <ul> <li>把自己的责任推给别人、让别人为自己负责,实则是逃避自由</li> <li>作为成年人,我们一生都充满选择和决定的机会。接受这一事实,就会变成自由的人;无法接受这种事实,就会永远觉得自己是个牺牲品。</li> </ul> <h3>自律原则3:忠于事实</h3> <p>认清事实,才能认清自己的位置:</p> <blockquote> <p>我们对现实的观念就像是一张地图,凭借这张地图,我们才能了解人生的地形、地貌和沟壑,指引自己的道路。</p> <p>如果地图准确无误,我们就能确定自己的位置,知道自己要到什么地方,怎样到达那里;</p> <p>如果地图信息失真,漏洞百出,我们就会迷失方向。</p> </blockquote> <p>要不停探索、接受新信息:</p> <blockquote> <p>大多数人过了中年,就自认为地图完美无缺,世界观没有任何瑕疵,甚至自以为神圣不可侵犯,而对新的信息和资讯缺乏兴趣。</p> <p>只有极少数幸运者能继续努力,他们不停地探索、扩大和更新自己对于世界的认识,直到生命终结。</p> </blockquote> <p>不要逃避现实,不要让过去的信息成为现在的“心结”:</p> <ul> <li>抱着残缺的人生地图不放,与现实世界处处脱节,这是不少人的通病,也是造成诸多心理疾病的根源。心理学家把这种情形称为“移情”。</li> <li>把产生和适用于童年时期的那些感知世界、对世界做出反应的方式,照搬到成年后的环境中,尽管这些方式已经不再适用于新的环境。</li> <li>逃避现实的痛苦是人类的天性,只有通过自律,我们才能逐渐克服现实的痛苦,及时修改自己的地图,逐步成长。</li> </ul> <p>要不断自我反省,并主动接受挑战:</p> <ul> <li>验证自己是否知行合一</li> <li>接受外界的质疑和挑战,以确定我们的地图是否与事实符合</li> </ul> <p>保持诚实,但有选择地表达意见和想法:</p> <ul> <li>要完全忠于事实,就需要一辈子保持诚实。我们必须确保我们的言语能够准确地表述出我们所认知的事实。</li> <li>敢于面对事实的人,能够心胸坦荡地生活,不必面临良心的折磨和恐惧的威胁。</li> </ul> <h3>自律原则4:保持平衡</h3> <p>确立富有弹性的约束机制:</p> <ul> <li>例如:不但要有生气的能力,还要具备克制脾气的能力。</li> </ul> <p>学会放弃:</p> <ul> <li>要让心智成熟,就得在彼此冲突的需要、目标和责任之间保持微妙的平衡,这就要求我们不断自我调整。保持平衡的最高原则就是“放弃”。</li> <li>失去平衡远比放弃更为痛苦</li> <li>我们一生中不同阶段需要放弃的东西: <blockquote> <p>无需对外界要求作出回应的婴儿状态</p> <p>无所不能的幻觉</p> <p>完全占有父亲或母亲(或二者)的欲望</p> <p>童年的依赖感</p> <p>自己心中被扭曲了的父母形象</p> <p>青春期的自以为拥有无穷潜力的感觉</p> <p>无拘无束的自由青年时期的灵巧与活力</p> <p>青春的性吸引力</p> <p>长生不老的空想</p> <p>对子女的权威</p> <p>各种各样暂时性的权力</p> <p>身体永远健康</p> <p>最后,自我以及生命本身</p> </blockquote> </li> </ul> <p>兼容并包:</p> <ul> <li> <p>既要肯定自我以保持稳定,又要放弃自我以腾出空间,接纳新的想法和观念,实现自我平衡。</p> </li> <li> <p>消除熟悉的过去,追求新鲜的未来</p> <blockquote> <p>面对陌生的人、事、物,我需要让昔日的经验、当前的需求和未来的期待一并出席,共同对我的需求和现实状况进行评估,做出恰当的判断和决定。</p> <p>为了体验新鲜事物的独特性,我必须以包容一切的姿态,说服既有的成见和观念暂时退位,让陌生、新奇的事物进入感官世界。</p> </blockquote> <blockquote> <p>不然的话,人生的每一分每一秒,都将是过去经验的一再重复。</p> </blockquote> </li> </ul> <h2>爱</h2> <p>爱是自律的原动力,把爱和自律结合起来,才能拥有幸福的人生。</p> <p>作者对爱的定义是:<strong>为了促进自己和他人心智成熟,而不断拓展自我界限,实现自我完善的一种意愿</strong>。</p> <p>爱的目的:</p> <ul> <li>实现自我完善</li> <li>拓展自我界限</li> <li>真正的爱是一种扩展自我界限的体验,对外界投入的精神越多,自我边界就会得到越多扩展</li> </ul> <p>真正的爱有以下特征:</p> <ul> <li> <p>爱是一个长期、渐进的过程。</p> </li> <li> <p>爱情不是是永恒的。</p> </li> <li> <p>依赖不是爱</p> <p>只想获取却不愿付出,心智就会永远停留在不成熟的状态,这只会对人生构成限制和束缚,给人际关系造成破坏,让别人跟着遭殃,而不是促进别人的心灵成长。</p> </li> <li> <p>爱在某种意义上是自私的,最终追求的是自我完善。</p> <blockquote> <p>我们真心去爱某个人,是因为我们自己需要去爱别人;</p> <p>我们生儿育女,是因我们自己想要孩子;</p> <p>我们爱自己的孩子,是因为我们渴望自己成为充满爱心的父母。</p> </blockquote> </li> </ul> <p>如何爱:</p> <ul> <li> <p>爱不是无原则的自我牺牲。</p> <p>真正意义上的爱,既是爱自己,也是爱他人。不爱自己的人,绝不可能去爱别人。</p> </li> <li> <p>爱不是感觉,是实际行动。</p> <p>爱是行为,爱意味着我们要不断付出努力,去跨越原来的界限。爱不能停留在口头上,而要付诸行动;爱不能坐享其成,而要真诚付出。</p> </li> <li> <p>爱的对象,也可以是事物、活动</p> <p>培养某种爱好,是自我滋养的有效手段。要学会自尊自爱,就需要自我滋养。</p> </li> <li> <p>爱需要充分投入、付出关注</p> <p>爱,最重要的体现形式,就是关注。我们爱某个人,一定会关注对方,细心照料对方,进而帮助对方成长。</p> <p>关注的主要途径是“倾听”,暂时放下个人的想法和欲望,把注意力放在别人身上</p> <p>充分投入是情感的基础;投入、做出承诺并遵守,可以给别人带来安全感</p> </li> <li> <p>爱需要勇气</p> <p>勇气,并不意味着永不恐惧,而是面对恐惧时能够坦然行动,克服畏缩心理,大步走向未知的未来</p> <p>人生是一场冒险。你投入的爱越多,经受的风险也就越大。</p> <p>敢于追求独立自主、摆脱依赖性。</p> <blockquote> <p>人生唯一的安全感,来自于充分体验人生的不安全感。</p> </blockquote> </li> <li> <p>保持诚实、谦虚、自省,尽力避免指责、冲突、傲慢</p> <p>我们常常以爱的名义去指责所爱的人。可是,大多数批评只是出于一时的冲动、不满和愤怒,不但没有启发和教育意义,反而会使局面更加混乱。</p> <p>保持诚实和谦虚,勤于自省,指责别人之前,先质疑自己是否“绝对正确”。</p> <p>该批评、指出错误时,也不能退缩。</p> </li> <li> <p>爱的前提是独立</p> <p>爱的重要特征之一在于,爱者与被爱者都不是对方的附属品。</p> <p>付出真爱的人,应该永远把爱的对象视为独立的个体,永远尊重对方的独立和成长。</p> <p>有的父母不尊重孩子独立的人格,只把子女当成自我的延伸。子女就像他们昂贵的衣服、漂亮的首饰、修剪齐整的草坪、擦拭一新的汽车一样,代表着他们的社会地位和生活水平。父母的这种自恋情结,看上去没什么大不了,但其实有着惊人的破坏力。</p> <p>婚姻是分工与合作并存的制度,夫妻双方需要奉献和关心,为彼此的成长付出努力。理想婚姻的基本目标,是让双方同时得到滋养,推动两颗心灵的共同成长。双方都有责任照顾后方营地,都要追求各自的进步,都要攀登实现个人价值的人生巅峰。</p> </li> </ul> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/the_road_less_traveled/#post-comment/</comments>
</item>
<item>
<title>月刊 | 信息源分类集合页</title>
<link>https://www.scarsu.com/monthly_all/</link>
<guid isPermaLink="true">https://www.scarsu.com/monthly_all/</guid>
<description>分类整理 每月收集的信息源</description>
<pubDate>Sat, 01 Jan 2022 00:00:00 GMT</pubDate>
<content:encoded><p><a>【月刊】分类集合页 https://scarsu.notion.site/b4ea0fb5a9ad4131b031205a8d2929f2 </a></p> </content:encoded>
<category>信息源</category>
<comments>https://www.scarsu.com/monthly_all/#post-comment/</comments>
</item>
<item>
<title>心流:最优体验心理学</title>
<link>https://www.scarsu.com/psychology_flows/</link>
<guid isPermaLink="true">https://www.scarsu.com/psychology_flows/</guid>
<description>利用积极心理学,提升幸福感和效率。</description>
<pubDate>Sat, 25 Dec 2021 00:00:00 GMT</pubDate>
<content:encoded><h2>前言</h2> <p><img src="/images/picgo/Snipaste_2022-01-18_18-01-41.png" alt="思维导图" /></p> <p><a>《心流:最优体验心理学》</a>的作者是心理学理论之父、积极心理学奠基人米哈里•契克森米哈赖。</p> <p>他在30年前,在大量案例研究基础上,开创性地提出了“心流”的概念。</p> <p>“心流”是指一个人完全沉浸在某种活动当中,那种全神贯注、投入忘我的状态。</p> <p>这种状态下,你甚至感觉不到时间的存在,在这件事情完成之后我们会有一种充满能量并且非常满足的感受。其实很多时候我们在做自己非常喜欢、有挑战并且擅长的事情的时候,就很容易体验到心流,比如爬山、游泳、打球、玩游戏、阅读、演奏乐器还有工作的时候。</p> <h2>人类不幸福的原因</h2> <p>作者之所以提出“心流”理论,离不开对“幸福”的研究。</p> <ul> <li>宇宙初创之时,就没有以人类的安逸舒适为念。</li> </ul> <p>大马哈鱼溯江而上,产卵后便死去。自然选择筛选出的这种机制为了繁衍连母体的生命都要牺牲,快乐在其中怎么能算得上重要的追求呢?</p> <p>人类性交快感为何这么短促?因为只要完成配种就够了。</p> <blockquote> <p>寻求快乐是基因为物种延续而设的一种即时反射,其目的非关个人利益。</p> </blockquote> <p>进食的快乐是为确保身体得到充足营养,性爱的快乐则是鼓励生殖的手段,它们实用的价值凌驾于一切之上。对异性的性趣只不过是肉眼看不见的基因的一招布局,完全在操纵之中。</p> <blockquote> <p>自然选择出的生理机制只是服务于人类生存繁衍,没有增加幸福快乐的考虑。</p> </blockquote> <ul> <li>空虚感、内在秩序的缺失(作者称之为<strong>精神熵</strong>)</li> </ul> <p>人类与动物的最大差别在于神经系统过于发达。</p> <p>感知和摄取更多的信息,无疑有利于人类生存。对外部情况不感知,当然更危险,但<strong>感知更多往往也更苦恼</strong>。</p> <p>动物中除了人以外,都不会自作自受,它们的进化程度还不足以感受沮丧和绝望,只要没有外来的冲突干扰,它们就能保持和谐,体验到人类称为心流的那种圆满。</p> <p>常言说:无知无畏。反之,多知多畏,多知多忧。于是焦虑增长。刚巧一切平安的时候呢?神经系统过于发达的人类偏偏又会感到枯燥无聊。</p> <p><strong>内在秩序的缺失</strong>,表现在某些人所谓的存在焦虑或存在恐惧等主观状况上。基本上,它是一种对生存的恐惧,一种生命没有意义、不值得继续的感觉。</p> <p>人类有一个超大的意识系统。意识系统需要秩序,其无序时人们会焦虑、烦躁。</p> <p>米哈里提出了<code>精神熵</code>:资讯对人们意识中的目标和结构的威胁,将导致内心失去秩序,处在混乱状态,内心一片混乱,熵值非常高。</p> <p>心流就是让内心的意识更有规律、更有秩序,是降熵的过程。</p> <ul> <li>永无止境的欲望</li> </ul> <p>世上大多数人的人生目标都很简单:平安地活着,养育一儿半女;如果可能的话,再加上那么一点儿舒适与尊严。</p> <p>只要基本的生存问题解决了,充足的食物和舒适的居所就立刻显得微不足道,新需求、新欲望会立即出现。</p> <p>生活越改善而越不满足的矛盾表明,<strong>提高生活品质是一件永远没有尽头的苦役。</strong></p> <p>设立新目标也没什么不好;但问题就在于一般人总把所有心力放在新目标上,不能享受现在,也因此与<code>知足</code>的快乐绝缘。</p> <p>外貌、金钱、权力、地位、财富,人类想追求的太多,却无人能达到完美。在无法同时满足太多要求的挫折之下,有些人干脆投降认输,躲进自己的小天地:培养一种高雅的嗜好、沉溺于酒精、消费、性欲、毒品。</p> <p>古代帝王的生活,比起现代人的生活品质,不值一提。</p> <p>但是尽管人类的物质力量增强了几千倍,在改善体验的内涵上却不见得有何长进。</p> <h2>如何应对不幸福:心流</h2> <p>上述总结了人类不幸福的原因,针对这几个原因,作者提出了“心流”理论。</p> <p>心流即一个人完全沉浸在某种活动当中,无视其他事物存在的状态。</p> <p>“心流”是改善体验,提升幸福感的关键。</p> <p>我们对自己的观感、从生活中得到的快乐,归根结底直接取决于心灵如何过滤与阐释日常体验。我们快乐与否,端视内心是否和谐,而与我们控制宇宙的能力毫无关系。</p> <p>只有学会掌控心灵的人,才能决定自己的生活品质;具备了这种能力,也就相当于接近幸福的境界了。</p> <p>最优体验有赖于时时刻刻用意识控制周遭事物,而要达到这种境界,唯有靠个人的努力与创意。</p> <p>心流是意识和谐有序的一种状态,在这种状态下,注意力集中,意识有了秩序,上述的“不幸福的原因”,自然就不存在了。</p> <h2>心流如何形成</h2> <h3>提高控制意识的能力</h3> <ul> <li>每个人都有控制意识的自由。</li> </ul> <p>我们通常将意识<em>化资讯为秩序</em>的那股力量称为“意图”。</p> <p>先天遗传或后天得来的意图,会按目标的高低排定重要性。政客可能认为政治改革比生命重要、普通人很根据身体的需要认为健康、长寿、美食、舒适生活更重要、英雄、圣人、疯子、罪犯也都会在其意识中排列出最重要的目标......这一切都证明了,<strong>意识可以遵循不同的目标与意图发展,每个人都拥有控制主观现实的自由。</strong></p> <ul> <li>意识是有限的</li> </ul> <p>神经系统在特定的时间内能处理的资讯极为有限。</p> <p>思绪必须井然有序,否则就会混乱。</p> <blockquote> <p>现阶段的科学知识已可以估计出中枢神经系统处理资讯的速限。大致而言,我们顶多能同时应付七组资讯,诸如分辨声音、影像、情绪或思想中可辨识的弦外之音等。由一组转换到另一组,至少需要1/18秒。从这些数字可以算出,大脑1秒钟顶多能处理126比特的资讯,1分钟是7560比特,1小时则大约50万比特。**一生若以70年计,每天有16小时的清醒时刻,一生中可处理的资讯便是1850亿比特。**这就是生活的全部——所有的思想、记忆、感觉与行动。这个数字听起来似乎很庞大,其实则不然。</p> <p>光是听懂他人说的话,就需要每秒钟处理40比特的资讯,意识的有限由此可见一斑。假设大脑的极限是每秒钟126比特,那么同时理解三个人的话,在理论上是可能的,但这样一来,我们就得把其他思想和感觉摒除在意识之外。比方说,我们就无法注意到说话者的表情,也不能考虑他们说话的动机,或注意他们的穿着打扮。</p> </blockquote> <ul> <li>意识使用率决定生活品质</li> </ul> <p>很多人没有充分发挥处理资讯的能力。大多数人在每天约占1/3的闲暇时间里,都尽可能避免用脑子,其中一半时间以上是消磨在电视机前。</p> <p>每个人一生中能处理的资讯有限,所以准许哪些资讯进入意识就显得格外重要。实际上,这就决定了生活的内涵与品质。</p> <ul> <li>注意力是“精神能量”</li> </ul> <p>控制意识最明显的指标就是能随心所欲地集中注意力,不因任何事情而分心。</p> <p>注意力负责从数以百万计位的资讯中挑出相关的资讯,以及从记忆中抽取相关的参考数据,然后评估事件,采取正确的对策。</p> <p>应用注意力的方式足以决定人生的外观与内涵。</p> <p>注意力除了决定某些事物能否进入意识外,还要带动其他心灵活动——回忆、思考、感觉、做决定,所以应该把注意力视为一种<strong>精神能量</strong>。</p> <p>它是完成工作不可或缺的能量,在工作中会耗损。我们通过这种能量的应用,创造自我;也通过应用的方式,塑造记忆、思想和感觉。</p> <p>注意力是一种受我们控制、随我们使用的能量变化而改变,也是改善体验品质的最重要的工具。</p> <ul> <li>生活的品质取决于控制意识的能力。</li> </ul> <p>痛苦与快乐都属于可意识的范围,而且只在意识中存在。</p> <p>一个人可以不管外界发生什么事,只靠改变意识的内涵,使自己快乐或悲伤</p> <p>“人害怕的其实是自己对事物的看法,而非事物本身。”</p> <p>生活的品质取决于控制意识的能力。</p> <h3>自寻目标与乐趣</h3> <p>集中注意力是造就心流的关键。而凝聚注意力需要一个目标。目标从何而来呢?</p> <p>在传统社会中,为百姓们提供人生目标的是社会权威:国王、主教、政府。他们提供的目标有:<strong>宗教、道德、阶级习俗、爱国主义</strong>。</p> <p>最后到来的一个目标提供者是商人,他们宣扬的是<strong>消费</strong>。</p> <p>这些目标渐渐失效,不再吸引众生。</p> <p>原因之一是,这些目标设置的动机是维护社会秩序、或者是鼓吹者自身的利益,更有利于宣讲者或统治阶层。</p> <p>社会将我们塑造成拼命工作与储蓄的公民、商人哄骗我们将辛苦赚来的钱消费、灰产与地下组织提供禁忌的快乐.....这些种种,都是为了剥削我们的精力,以满足其私欲或目标。</p> <p>因此,我们应该从<strong>社会制约</strong>与<strong>本能冲动</strong>下,解放意识,培养独立意识:</p> <ol> <li> <p>克服现代生活的焦虑与沮丧,从社会环境中独立出来,不再以社会的奖赏为念,试着以自己所能控制的奖赏取而代之。要在别人用以利诱我们的目标之外,另行建立一套自己的目标。</p> </li> <li> <p>不要屈服于出于人性和基因的本能反应,不要被肉体的欲望牵着鼻子走,控制本能的冲动。享受自然的乐趣并没有什么不好,但我们应该认清事实真相,在必要的时候,按照自己内心的优先顺序,做自己的主人。</p> </li> </ol> <h3>自寻乐趣</h3> <p>睡眠、休息、食物与性,都属于恢复“均衡”的体验,在肉体需求引起精神熵以后,重整意识的秩序。</p> <p>它们并不能带动心灵的成长,也不能增加自我的复杂性。换言之,享乐虽有助于维持意识的秩序,却无法在意识中创造新秩序。</p> <p>一味追求财富、地位、权力,未必能使人更快乐。唯有从每天的生活体验中创造乐趣,才能真正提升生活品质。</p> <p>改善生活品质的主要策略有两种:一是使外在条件符合我们的目标;二是改变我们体验外在条件的方式,使它与我们的目标相契合。</p> <p>如果要控制体验品质,就必须学习从每天的生活中创造乐趣。</p> <h3>有即时反馈,挑战要与能力匹配</h3> <p>所有心流活动,不论涉及竞争、投机还是其他形式的体验,都有一个共同点:它带来一种新发现、一种创造感,把当事人带入新的现实。</p> <p>简单地说,它把自我变得更复杂,自我因而成长,这就是心流活动的关键。</p> <p><img src="/images/picgo/picgo20211221151532.png" alt="意识复杂程度随心流体验渐增" /></p> <blockquote> <p>字母A代表艾利斯,一个正在学打网球的男孩,图形显示艾利斯学打网球的四个阶段。</p> <p>刚开始的时候,艾利斯不懂任何技巧,他唯一的挑战就是把球打过网去,这是A①。</p> <p>这种挑战没什么了不起,但艾利斯还是可能打得很愉快,因为难度正适合他粗浅的技巧。这时他很可能感受到心流,但为时不会太久。经过一段时间的练习,他的技巧进步了,他开始厌烦只是把球打过网去的动作(A②),</p> <p>或者他也可能碰到比他熟练的对手,使他发现球场上还有比高吊球更难应付的挑战——这时,他对自己拙劣的表现产生了焦虑(A③)。</p> </blockquote> <p>总而言之,可以造就心流的活动中必有挑战,且挑战应该是动态的。</p> <ul> <li>当挑战与你的技能匹配时,就有了心流。</li> <li>当挑战的目标大大高过你的技能时,将产生焦虑,那么就要提高技巧和能力,或者降低挑战目标。</li> <li>当你的技能高过设定的目标,继续持续这种活动将产生厌倦,那么就提高目标和挑战的难度,以求挑战和心流的持续。</li> </ul> <p>正是在技巧提高、目标上调的过程中,当事者感受到了成长的乐趣。</p> <h3>学会独处,屏蔽外界的干扰</h3> <p>一个人若能从独处中找到乐趣,必须有一套自己的心灵程序,不需要靠文明生活的支持——亦即不需要借助他人、工作、电视、剧场规划他的注意力,就能达到心流状态。</p> <p>一方面,独处是建立自己的内心系统的必要经历。</p> <p>另一方面,有了自己内心的系统,更能够适应因偶然原因陷入的孤独的处境中。</p> <h2>人生的意义:追寻人生的心流</h2> <p>如果一个人决心实现一个困难的目标,所有其他目标都是为这个大目标而存在,他就会投入所有精神能量,培养实现这一目标所需的技巧,那么所有的行动与感受就会形成蔚为和谐的整体,人生各个不同的部分也会契合无间。不论过去、现在,还是未来,每种活动都深具意义。在这种情形下,一个人的生命就有了意义。</p> <h3>培养方向感</h3> <p>每个人刚开始都只想到求生、保持身体及其基本目标的完整性,这时人生的意义很简单——就只是求生、求舒适、求享乐而已。</p> <p>当身体的安全得到充分保障后,一个人就可以扩张意义系统,包容家人、邻居、宗教或种族等团体的价值观。这一步骤虽然通常会要求个人认同传统的标准与规范,但仍能提升个人的复杂性。</p> <p>下一步发展又回到个人主义的反省。个人再次转向内心,从自我寻求权威与价值标准的新基础。他不再盲目认同,开始发展独立自主的善恶观念。这时人生的主要目标变为追求成长、进步和实现潜能。</p> <p>前面各步骤都已臻至圆熟,第四步才能展开,这是最后一次脱离自我,认同他人及宇宙共同的价值观。在这个阶段,极端个人化的人——就像修行功德圆满,听任河水控制船行方向的佛陀——终于心甘情愿让自己的利益融入大我的利益之中。</p> <h3>下定决心</h3> <p>在为一个目标投下大量精神能量之前,应该先提出几个基本问题:</p> <ul> <li>我真的想做这件事吗?</li> <li>做这件事会有乐趣吗?</li> <li>在可预见的将来,我仍然能从中得到乐趣吗?</li> <li>我和其他人,必须为它付出的代价值得吗?</li> <li>完成这件事以后,我还会喜欢自己吗?</li> </ul> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/psychology_flows/#post-comment/</comments>
</item>
<item>
<title>月刊#6 | 2021.08-12</title>
<link>https://www.scarsu.com/monthly_6_2021_08-12/</link>
<guid isPermaLink="true">https://www.scarsu.com/monthly_6_2021_08-12/</guid>
<description>本文包含从2021年8月到12月,五个月之间,我收集到的信息和信息源,共16个类目:前端、开发与科技、话题、极简与低消费、Grow Up With You 指路人系列、读书、信息源、知识管理、Notion、有趣的网站、职场、投资理财与副业、种草、工具、设计与创作、生活与健康。</description>
<pubDate>Tue, 21 Dec 2021 00:00:00 GMT</pubDate>
<content:encoded><h3>前端</h3> <ul> <li><a>政采云 | 如何写前端技术文档</a></li> <li><a>State Of CSS 2021</a></li> <li><a>V8编译浅谈</a></li> <li><a>前端面试八股文合集</a></li> <li><a>一个Three.js实例 | 3D看鞋</a></li> <li><a>文件下载9种场景</a></li> <li><a>在网页中实现裸眼3D</a></li> <li><a>Web Workers 2021现状分析</a></li> <li><a>微前端落地,悬着的心终于放下了</a></li> <li><a>如何搭建适合自己团队的构建部署平台</a></li> <li><a>中国计算机学会的前端会议,前端的发展与未来</a></li> <li><a>你真的了解package.json吗?</a></li> <li><a>前端零成本建站</a></li> <li><a>petite-vue</a> | 6KB 轻量迷你基本版 vue</li> <li><a>awesome-javascript</a> | 优秀前端库合集</li> <li><a>前端性能优化 | 9大策略和6大指标</a></li> <li><a>B站五面面经(附过程、答案)</a></li> <li><a>字节跳动的B面<em>详细解读</em>最新资讯_热点事件_36氪</a></li> <li><a>webpack 最佳实践-微医前端团队</a></li> <li><a>ES6复盘知识点</a></li> <li><a>如何成为优秀的大前端Leader</a></li> <li><a>滴滴前端博客</a>(核心成员<a>黄轶</a>)</li> <li><a>尤雨溪是怎么发布 Vue.js 的?</a></li> <li><a>上传文件夹的API</a> <code>HTMLInputElement.webkitdirectory</code></li> <li><a>前端异常监控和容灾</a></li> <li><a>css houdini</a> :js in css</li> <li><a>Vue3 源码中实用的基础工具函数</a></li> <li><a>http2 &amp; 前端</a></li> <li><a>每个前端都需要知道这些面向未来的CSS技术</a></li> <li><a>Github | Javascript进阶问题列表</a> - 39.8k star</li> </ul> <h3>开发 | 科技</h3> <ul> <li>“技术为业务而服务,不同的场景需要不同的工具,我们的任务就是找到最合适的工具并用好它。”</li> <li>知乎 | <a>探索Notion的实现</a></li> <li>少数派 | <a>2021:树莓派入坑指南</a></li> <li>树莓派实验室 | <a>用树莓派制造一个像样的 NAS</a></li> <li>树莓派实验室 | <a>Raspberry Pi中文资讯站,提供丰富的树莓派使用教程和DIY资讯</a></li> <li>开源 | <a>google面试算法题训练</a></li> <li>开源 | <a>MojoJS-Animation</a>:开源强大、轻量、易用的JS动画引擎</li> <li>政采云 | <a>你需要知道的项目管理知识</a></li> <li>字节 | <a>如何写开发设计方案</a></li> <li>文章 | <a>10款lowcode开发平台</a></li> <li>资源 | <a>编程电子书</a></li> <li>开源 | <a>可视化编程</a></li> <li>科技 | <a>研究人员教会培养皿中的脑细胞打乒乓球</a></li> <li>科技 | <a>双足机器人 Atlas 在表演流畅的跑酷</a></li> <li><a>Google代码审查指南</a>、 <a>中文版</a></li> <li><a>Google开发语言风格指南</a> - 29.4k star</li> <li><a>Google软件工程经验</a>、<a>中文版</a></li> </ul> <h3>话题🎙️</h3> <ul> <li>公开目标 | 公开之后就会有社会压力,你会感受到别人在看你。其实没有人会看,但这会让你对自己多一个旁观的视角,让你能好好审视自己。</li> <li>自省 | ”在愚昧之峰狂欢,在信息孤岛独舞,在一滩死水里永世长存“以此提醒不要太固执、太自信、太墨守成规、<a>邓宁-克鲁格效应</a></li> <li>吃苦 | 高级的吃苦能力,不是单纯的忍受贫穷、耗费体力,是一种自控能力。长时间聚焦于一件事情,没有无效社交 没有无意义的消费 没有娱乐生活 忍受孤独。</li> <li>视频推荐 | <a>不要活在别人的评价体系中</a> - 小唯up</li> <li>视频推荐 | <a>社恐自救指南</a>: be yourself is cool enough、别人怎么对待你,是你自己交给别人的 - 小唯up</li> <li>视频推荐 | <a>HSP自救指南</a>:接纳自己、停止过度共情、精简社交 - 小唯up</li> <li>文章 | <a>46 六个对我影响最大的效率习惯</a></li> <li>文章 | <a>如何提升自己的幽默感?</a></li> <li>文章 | <a>我们为什么爱郑渊洁?</a>:犀利有度、幽默加持</li> <li>文章 | <a>为什么你需要一个自己的网站</a>:拥有品牌和属于自己的听众、回避审查、掌握数据、避免骚扰、长期经营,享受长远复利</li> <li>文章 | <a>外圆内方</a> 、<a>思维导图</a></li> <li>少数派 | <a>每年更新一次遗嘱、数字遗产保护</a></li> <li>少数派 | <a>如何追求精力充沛的生活</a></li> <li>少数派 | <a>DPS 周刊 01 - 如何努力?</a></li> <li>少数派 | <a>目标这个 Flag,是对自己的承诺</a></li> <li>性别差异 | <a>中华人民共和国妇女权益保障法(修订草案)</a></li> <li>性别差异 | <a>韩国作家孙雅兰演讲《性别歧视的代价&amp;逆向性别歧视》</a></li> </ul> <h3>极简 | 低消费🛒</h3> <ul> <li>极简主义 | <a>在极简中寻找平衡</a></li> <li>理性消费 | 自问“这种东西你买了你不觉得亏吗”</li> <li>低消费主义 | 承认并管理<a>生活方式的膨胀</a></li> <li>低消费主义 | <a>豆瓣低消费研究所小组</a>创建人小松悠:买东西不是为了快乐,我所认为的消费就是正常的因需购买”</li> </ul> <h3>Grow Up With You 指路人系列🤝(世上没有任何一人是绝对善恶,请择善而从</h3> <ul> <li><a>两个站在时代风口的首富:世界首富马斯克、”中国新首富”币安赵长鹏</a></li> <li><a>TomKeeper</a></li> <li><a>v站一位前端前辈的简历</a></li> <li><a>于航</a></li> <li><a>掘金前端卷王</a>(年终总结都卷到提前一个月发😅</li> </ul> <h3>读书📔(开卷有益</h3> <ul> <li><a>《心流》| 最优体验心理学</a></li> <li><a>《高敏感是种天赋》 | HSP人群必读</a></li> <li><a>书单 | 豆瓣2021年度图书榜单</a></li> <li><a>书单 | 看了十张年度书单,我挑选出这 16 本不容错过的好书 - 少数派</a></li> <li><a>书单|澎湃新闻编辑们推荐的2021年度十大好书</a></li> <li><a>书单 | 2020 多抓鱼鲜鱼榜</a></li> </ul> <h3>信息源📑</h3> <ul> <li><a>掘金八大分类百强文章可视化分析</a></li> <li><a>抖音数据</a></li> <li>国外社区 | <a>顶流论坛Reddit、优质内容平台Medium、国外版知乎问答社区Quora</a></li> <li><a>国内外行业报告查询网站集合</a></li> <li>播客 | <a>一派·再读 Feed</a></li> </ul> <h3>知识管理📑</h3> <ul> <li><a>Cubox 6.0 | 全能网络收藏夹、语音、视频、速记 - 少数派</a></li> <li><a>一个文科博士生的资料管理、阅读和笔记系统-基于 DEVONthink 3,Obsidian - 少数派</a></li> <li><a>一个“阅读工作流”例子</a> | 信息源-&gt;稍后阅读-&gt;划线批注-&gt;临时笔记-&gt;永久笔记(知识库)-&gt;回顾系统-&gt;创作输出</li> <li><a>一个(自动化)信息流管理的案例</a></li> </ul> <h3>Notion📑</h3> <ul> <li>Notion 2.11 更新日志 <a>What's New?</a> (sync block、ifttt api、<a>https://www.integromat.com/en/integrations/notion</a>)</li> <li><a>Notion (Beta) works better with IFTTT</a></li> <li><a>Request page data for Next.js from the Notion API | egghead.io</a></li> </ul> <h3>有趣的网站🪀</h3> <ul> <li>解压 | 声音视觉动效网站<a>Patatap</a> 、 <a>初音未来版</a></li> <li><a>镜像式炫光生成器</a></li> <li><a>乐器模拟器</a></li> <li><a>io游戏站</a></li> <li><a>茶杯狐</a></li> <li><a>小霸王其乐无穷</a></li> <li><a>随机带你去一个没用的网站</a></li> </ul> <h3>职场💼</h3> <ul> <li><a>如何应对变相裁员</a></li> <li><a>如何看一个人有没有领导力</a></li> </ul> <h3>投资 | 理财 | 副业💰</h3> <ul> <li>投资理财 | <a>普通人如何有效投资理财? - 少数派</a></li> <li>远程工作 | <a>UpWork:打字、翻译、客户支持、开发</a></li> </ul> <h3>种草🛍️</h3> <ul> <li><a>编程工作适合用什么鼠标? - V2EX</a></li> <li><a>腾讯云羊毛 :云开发Webify个人网站扶持</a></li> <li>Ipad端 图形创作APP:Lazyshare 搭配 Procreate</li> <li>路人:联通 500M 宽带 包年 700 咸鱼租的</li> <li>路人:中国移动 300 Mbps 家庭宽带套餐,首年资费 39 元 /月,次年 30 元 /月,套餐含 5GB 4G 流量。2 年合约期。</li> </ul> <h3>工具🔧</h3> <ul> <li>小程序 | <a>极客词典</a>:中国互联网超爱读错的单词</li> <li>浏览器 | <a>管理浏览器插件的插件</a></li> <li>浏览器 | <a>ImageAssistant</a>图片助手:自动提取网页图片、批量下载、以图搜图</li> <li>Windows工具 | <a>抖音无水印下载用户视频</a></li> <li>Android | <a>Auto.js脚本 安卓设备重复性操作</a></li> <li><a>PowerToys</a>:微软官方Windows系统工具、文件管理器插件、分屏</li> <li><a>Snnedacity</a>:开源免费的音频编辑工具</li> <li><a>DataEase</a>:开源数据可视化分析工具</li> <li><a>App Star Walk 2</a>:打开AR 相机对着天空 就能识别出星空</li> <li><a>Potplayer</a>:全网最强 播放器</li> <li><a>RustDesk</a>:免费的 开源的 远程桌面软件</li> <li><a>全国移动电话卡“一证通查”</a></li> <li><a>万有导航</a></li> </ul> <h3>设计 | 创作✍️</h3> <ul> <li><a>非设计师也该学的排版知识:视觉动线 - 少数派</a></li> <li><a>用好 Keynote 和 iMovie,在 iPad 上做出有高级感的视频 - 少数派</a></li> <li><a>想做视频?这里有一份入门到进阶知识完整指南 - 知乎</a></li> <li><a>Youtube运营者必备12个工具</a></li> <li><a>图片处理App|VSCO 用了六年的照片调色 App</a></li> <li><a>手绘插画库/人物库</a></li> <li><a>图片特效生成器</a></li> <li><a>网站 | 人像转卡通</a></li> </ul> <h3>生活 | 健康🏃</h3> <ul> <li>少数派 | <a>你的家庭小药箱,从这 8 种非处方药开始</a></li> <li>体检 | <a>你该掌握的自查手段</a></li> <li>保健 | <a>提升好胆固醇, 降低坏胆固醇</a></li> <li>住房 | <a>筛选房源的第一步,读懂户型图</a></li> <li>装修 | <a>三万字装修经验「验收」</a></li> <li>服装 | <a>我们需要学习的挑选与购买</a></li> </ul> </content:encoded>
<category>信息源</category>
<comments>https://www.scarsu.com/monthly_6_2021_08-12/#post-comment/</comments>
</item>
<item>
<title>逆商:我们该如何应对坏事件</title>
<link>https://www.scarsu.com/aq_adversity_quotient/</link>
<guid isPermaLink="true">https://www.scarsu.com/aq_adversity_quotient/</guid>
<description>及时止损永远是糟糕状态下的最优选择。</description>
<pubDate>Wed, 15 Dec 2021 00:00:00 GMT</pubDate>
<content:encoded><h3>前言</h3> <p><a>豆瓣链接 - 《逆商》</a></p> <p>以前我觉得消极、积极的态度,来自于身处的环境和人的内在性格,是很难改变的。</p> <p>读了这本书之后,才意识到自己过去对待事物的消极态度,其实完全没有必要、没有意义。</p> <p>如书中所说,“我们无法选择身处的时代和环境,唯一能选择的是如何有效和积极地去应对“。</p> <p>及时止损永远是糟糕状态下的最优选择。</p> <p><img src="/images/picgo/20230709103001.png" alt="封面" /></p> <h3>逆商是什么</h3> <p>众所周知,<code>IQ</code>是<code>智商</code>,是一个人在其年龄段的智力和认知能力。</p> <p><code>EQ</code>是<code>情商</code>,是一个人认识、了解、控制情绪的能力。</p> <p>而<code>AQ</code>是<code>逆商</code>,即<code>Adversity Quotient</code>,能反映出一个人抵御、应对、战胜逆境的能力如何。</p> <h3>为什么要提升逆商</h3> <ul> <li>人生就是会面临一个又一个逆境</li> </ul> <p>从最轻微的挫折到最惨烈的悲剧都算上,你通常一天会遇到多少大大小小的难题?</p> <blockquote> <p>我和我的研究团队在1991年开始收集这个问题的答案时发现平均数量是三个。如今,这个问题的全球平均答案数是32个,而且这一数字还在上升。</p> </blockquote> <blockquote> <p>在大多数社会里,深受焦虑、无助、失眠、抑郁甚至是自杀倾向之苦的人数持续攀升。</p> </blockquote> <p>我们从出生起,就要面临各种问题:幼童时学步要面临不断地摔跤、青年时要应对各种学业课程、成年后要面临各种人际关系的矛盾、工作事务的难处、社会生活的压力。</p> <ul> <li>我们身处在逆境时代</li> </ul> <p>我们处在一个<code>RUPT</code>时代,即急速、莫测、矛盾、缠结。</p> <p>全球变暖情况持续加重、海平面持续上升;</p> <p>信息化、国际化使全球各个国家的关系越来越紧密、纠缠,经济战使经济环境变得更难预测;</p> <p>新冠病毒带来的疫情经久不衰、影响范围持续扩大;</p> <p>不论是个人健康、家庭生活、职场经济和社会,随时都可能将各种难题抛到我们面前,必须应对。</p> <ul> <li>提高逆商,那么生活的各个方面就会渐渐改善:</li> </ul> <p>提升活力、幸福感,对心理健康有益(因逆境而受伤的人容易感到无助,转而觉得抑郁);</p> <p>提升学习能力(积极的心态有益于保持冷静、充满活力的学习状态);</p> <p>提升竞争力、生产力、创造力、动力、毅力、韧性;</p> <p>提升身体健康,多项研究表明心理健康对身体健康有一定的影响,人的想法和感受与其体内的活动有着直接而显著的联系,传递人类情绪的化学物质会直接影响人类的身体健康,在压力面前表现得非常抑郁和焦虑的人,其体内的白细胞要弱得多。</p> <h3>如何提升逆商</h3> <ul> <li>告别习得性无助</li> </ul> <p>习得性无助是指将“做什么都没有用”这一想法内化,从而削弱一个人的掌控感。</p> <blockquote> <p>科学家塞利格曼做过两个实验。 在第一阶段,A组的狗被背带绑住并受到轻微电击。它们可以用鼻子去按控制杆,让电击停止。很快它们就学会这样做了。 B组的狗也是被同样的背带绑住并受到同样的电击,但它们无法让电击停止。这些狗只能忍受痛苦。 C组是对照组。C组的狗被背带绑住,但没有受到电击。</p> <p>第二天,塞利格曼进行实验的第二阶段。他将这些狗逐个放进一个叫作穿梭箱的装置里,这个箱子中间立着一块低矮的挡板。每只狗都被放到挡板的一侧并受到轻微电击。它们只需要跨越矮挡板跳到另一侧就能停止电击。 A组的狗(可以控制电击)和C组的狗(没有受到电击)很快就明白怎样跨越挡板,摆脱不适。 但B组的狗(不能控制电击)则有不同的反应,它们躺下来呜咽啜泣,没有尝试逃脱。</p> <p>塞利格曼等人发现,这些狗学会了无助,这一行为几乎摧毁了它们采取行动的干劲。 此后,科学家还发现,猫、鱼、狗、大鼠、蟑螂、小鼠和人类都能学到这一特性。</p> </blockquote> <p>不要将一件事情带来的消极情绪带入到其他事情中。</p> <ul> <li>不要扮演受害人的角色</li> </ul> <p>扮演受害者,是人类自我防御机制的一种方式。</p> <p>将责任推到外部环境,就有借口放弃掌控力、放弃自我努力。</p> <ul> <li>乐观的归因风格</li> </ul> <p>如果一个人认为逆境是永久的(“这永远不会改变”)、普遍的(“我会把所有的事搞砸”)和个人的(“这都是我的错”),那这个人就会拥有悲观的归因风格;</p> <p>如果一个人认为逆境是<code>暂时的</code>、<code>外在的</code>和<code>有限的</code>,那这个人则拥有乐观的归因风格。</p> <p>一个人的成功,很大程度上是由他归因或应对生活事件的方式所决定的。</p> <ul> <li>建设性应对逆境</li> </ul> <p>处理事情时考虑如何应对,而不是担心哪里会出问题。</p> <ul> <li>止念法</li> </ul> <p>改变潜意识的行为和习惯,在自己的消极想法和悲伤蔓延时,及时制止自己,例如:转移注意力、运动、用力拍手喊“停”、用手腕上的小皮筋弹自己一下、访问自己的初衷和目标是什么、等等...</p> <p>停止灾难化,不要因为一个逆境,就臆测“一切都完了”。</p> <p>把假设和事实区分开,停止无助的臆测,将逆境的影响范围最小化。</p> <ul> <li>放大格局</li> </ul> <p>凝视无垠的海洋或天空会让你意识到,在浩瀚的宇宙面前,自己的问题是多么地微不足道。</p> <ul> <li>LEAD法</li> </ul> <p>L= Listen,倾听自己的逆境反应:自己当下应对逆境,表现了高逆商还是低逆商?</p> <p>E= Explore,探究自己对结果的担当:我应该对结果的哪些部分担起责任?</p> <p>A= Analyze,分析证据:有什么实际证据可以表明此次困境脱离了我的掌控、一定会蔓延到生活的其他方面?</p> <p>D= Do,做点事情:搜集信息、列出行为清单,如何及时止损、如何控制此次逆境的影响范围和结果?</p> <hr /> <p>生活是艰难的,但你应对生活的方式决定了你的命运</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/aq_adversity_quotient/#post-comment/</comments>
</item>
<item>
<title>怦然心动的人生整理魔法笔记</title>
<link>https://www.scarsu.com/life_reorganize/</link>
<guid isPermaLink="true">https://www.scarsu.com/life_reorganize/</guid>
<description>整理是一个发现自己、认清自己、复盘人生的过程,你所拥有的物品会准确地诉说你做过的所有选择</description>
<pubDate>Fri, 03 Dec 2021 00:00:00 GMT</pubDate>
<content:encoded><p><img src="/images/picgo/picgo20211203174148.png" alt="封面" /></p> <h3>豆瓣链接</h3> <p><a>《怦然心动的人生整理魔法》</a></p> <h3>笔记大纲</h3> <p><img src="/images/picgo/picgo20211203173926.png" alt="笔记大纲" /></p> <h3>思维导图</h3> <p><a>文件链接</a></p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/life_reorganize/#post-comment/</comments>
</item>
<item>
<title>极简主义:如何用更少的东西过更有意义的生活</title>
<link>https://www.scarsu.com/minimalim/</link>
<guid isPermaLink="true">https://www.scarsu.com/minimalim/</guid>
<description>充满热情和自由,实现个人成长、以有意义的方式为他人做出贡献</description>
<pubDate>Fri, 22 Oct 2021 00:00:00 GMT</pubDate>
<content:encoded><h2>关于《极简主义》这本书</h2> <p><a>《极简主义》豆瓣链接</a></p> <p><img src="/images/picgo/picgo20211022184503.png" alt="《极简主义》" /></p> <p>这本书的作者是乔舒亚和瑞安,曾经是两个年薪六位数(美元)的美国职场精英,拥有香车、豪宅、昂贵服装及大量玩物。</p> <p>但是他们对这种“一周工作七八十个小时、买更多东西”的生活感到不满足、焦虑又空虚,于是开始了极简主义。</p> <p>我最初对极简主义的印象,来自于扎克伯格满衣柜的灰色同款衣服,和乔布斯平生不变的穿搭</p> <p><img src="/images/picgo/picgo20211022144109.png" alt="扎克伯格的衣服" /></p> <p><img src="/images/picgo/picgo20211022145246.png" alt="乔布斯的穿搭" /></p> <p>但是这本书介绍的极简主义,<strong>重心不是在如何扔东西、如何降低物欲,而是如何过更有意义的生活</strong>。</p> <p>答案就是关注人生中最重要的五个方面:<strong>1.健康 2.人际关系 3.热情 4.成长 5.奉献</strong></p> <h2>快乐源自内心,而不是物质财富</h2> <p>我们处在被商业营销充斥的环境:<em>各种购物app创造了接连不断的购物节,短视频app不停的推送带货直播,微博、知乎、b站、小红书充斥着商业广告;下班回家路上有各种广告牌,小区电梯有24h不间断播放的广告视频,回家开门还时不时发现门把手被塞上了小广告......</em></p> <p>商家在营造一种购物、消费就能让我们生活更幸福的假象。</p> <p>但全世界的商家、营销的根本目的是赚钱,而不是我们的幸福快乐。</p> <p>每次购物会带来些许快感,但是它会瞬间消散。</p> <p>如果要依赖物质带来快乐,随着边际效应递减,获得快乐的阈值会越来越高,我们只会走向对金钱永无止境的追逐。</p> <p><img src="/images/picgo/picgo20211022173507.png" alt="消费陷阱" /></p> <p>所以,<strong>快乐不是来自金钱、物质,而是来自于内部、来自我们的内心</strong>。</p> <p>那么如何去追寻内心的快乐呢?</p> <p>答案就是追寻有意义的生活。</p> <blockquote> <p>如果我们的短期行为和长期价值相符,那么我们就会在自己所做的所有事情中找到意义。</p> <p>矛盾的是,这种生活方式(有意识的生活)才会带领我们走向真正的幸福快乐。</p> <p>不是转瞬即逝的欢愉,而是长久的满足,来自自律、专注、觉知、目的明确的生活。</p> </blockquote> <p><strong>过有意义的生活,快乐自然而然会成为副产品</strong>。</p> <blockquote> <p>我们在这世上只有有限的时间,</p> <p>这些时间可以用来积攒金钱财富,也可以花在有意义的事情上。</p> <p>后者不一定会妨碍人们追求前者,</p> <p>但对财富永无止境的追求并不能将我们带向有意义的生活。</p> </blockquote> <h2>为有意义的生活 清除障碍</h2> <p>当我们意识到“快乐不是来自金钱、物质,而是源自内心”这个真相后,</p> <p>就能发现我们身边充斥了许多事物,也许阻碍了我们自由地追求有意义的生活。</p> <p>例如,需要大量时间却没有给生活增添相应价值的东西:</p> <ul> <li>房子(和随之而来的大笔按揭还贷)</li> <li>某些人际关系(没有为我们的生活增添价值的不健康关系)</li> <li>汽车贷款和其他大额账单、</li> <li>大笔债务、</li> <li>我们的事业</li> <li>...</li> </ul> <p>会消耗我们时间和注意力的小事:</p> <ul> <li>有线电视费、</li> <li>网费、</li> <li>其他账单、</li> <li>小额债务、</li> <li>不穿的衣服、</li> <li>没用的家居用品、</li> <li>家庭杂物、</li> <li>某些徒劳的次要关系、</li> <li>日常的开车时间</li> <li>...</li> </ul> <p>上面举了一些例子,抛弃这些对我们不重要的事物、财物,扔掉多余的东西,</p> <p>只留下我们喜欢和享受的、那些在日常生活中实实在在用得到的东西。</p> <p>当达到物质上的极简后,就会发觉自己必须去追求精神上的富足。</p> <p>摆脱混乱的身外之物,就会有足够的时间和精力,去实现有意义的人生:<strong>充满热情和自由的人生,可以实现个人成长、以有意义的方式为他人做出贡献的人生。</strong></p> <h2>健康</h2> <p>健康是生命的基础。</p> <p>虽然疾病与死亡不可避免,但是我们仍然应该在自己力所能及的范围内过着最为健康的生活。</p> <p>书中给出了具体的建议:</p> <ul> <li>不吃加工食品、包装食品、糖、甜品</li> <li>少吃麸质、面包;少喝水以外的一切饮料</li> <li>多吃自然果蔬、豆类、鱼类</li> <li>坚持运动</li> </ul> <h2>人际关系</h2> <p>人际关系能满足最基本的人类情感需求。</p> <p>不好的、不必要的人际关系会浪费我们大量的时间和精力、甚至会伤害我们的情感。</p> <p>有三种方法可以建立更好的关系:</p> <ul> <li>评估现有关系,舍弃掉不必要的,无法给你带来价值的关系。</li> <li>寻找超棒的新人际关系。确定自己寻求的是什么?想要避免的是什么?为了想要的管旭你又必须让自己改变什么?</li> <li>改造你现有的人际关系,花更多时间维护。</li> <li>改变你自己,以身作则影响身边的人、吸引同类的好的人际关系。</li> </ul> <h2>热情</h2> <p>热情,有所热爱才会感到充实。</p> <p>找到自己真正感兴趣的事物,专注地投入热情和热爱。</p> <p>找到至少三个以你的爱好谋生的人,找到正在做你想做的事情的人,向他们学习,吸收他们的知识经验,然后大步行动。</p> <h2>成长</h2> <p>成长,持续进步而不是停在原地。</p> <p>我们生命的意义:实现个人成长,为他人做出贡献。</p> <p>想要长久的幸福,就必须继续做出改变。</p> <p>你的多数改变,都是通过每天在小的方面逐渐改善积累而成的。</p> <h2>奉献</h2> <p>成长和奉献相互成就,为自己添加人生价值</p> <blockquote> <p>你越成长,就越能帮助其他人成长;而越是帮助他人成长,你自己就越能获得更多成长。</p> </blockquote> <h2>总结</h2> <p>可以通过一个简单的等式来衡量自己在五大价值的各个方面是否成功:</p> <p><code>成功 = 快乐 + 持续进步</code></p> <p>为五大价值中某个方面的现状感到快乐,而且持续地进步着,那么你在这一领域便是成功的。</p> <h2>看完书,然后做什么?</h2> <p>行动。</p> <p>从你的物品开始。</p> <ul> <li>精简你的壁橱/抽屉。</li> <li>献出时间去帮助他人。</li> <li>把你的东西捐献给慈善机构。</li> </ul> <p>从你自己开始,以身作则。</p> <ul> <li>改变你的习惯。</li> <li>改变你的消费观念。</li> <li>改变你的饮食习惯、锻炼方式。</li> <li>找回你的时间。</li> <li>追求你的爱好。</li> <li>找到你的使命。</li> </ul> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/minimalim/#post-comment/</comments>
</item>
<item>
<title>最好的告别:如何优雅地走向生命终点</title>
<link>https://www.scarsu.com/being_mortal_update_210902/</link>
<guid isPermaLink="true">https://www.scarsu.com/being_mortal_update_210902/</guid>
<description>无论我们面临怎样的局限和阵痛,我们都希望保留 我们作为自己生活篇章的作者 的自主和自由。</description>
<pubDate>Tue, 31 Aug 2021 00:00:00 GMT</pubDate>
<content:encoded><h2>我最期望的死法</h2> <p>《人生果实》是我最喜欢的纪录片,讲述了日本建筑师津端修一夫妇的隐居生活。</p> <p><img src="/images/picgo/picgo20210901143845.png" alt="" /></p> <p>片中的老夫妻一个90岁,一个87岁,他们的老年生活令我羡慕不已,种树、种菜、种花、种水果、做甜品、做饭、自给自足......</p> <p>纪录片拍到一半的时候,90的老爷爷去世了。</p> <p>像往常每个午后一样,他安详的躺在床上午休,再也没有醒来。</p> <p>以前的我总是不敢想象自己和身边人的死亡,但是纪录片看到这的时候,我就在想,既然死亡不可避免,那么希望所有人告别人世时,都能像老爷爷这样安详、体面。</p> <h2>坦然地聊聊死亡</h2> <p><strong>死亡</strong>是一个沉重的话题,但是看完《最好的告别》这本书后,也许能更加坦然的面对这个话题。</p> <blockquote> <p>死亡本身是可怕的。</p> </blockquote> <p>人类历史发展30万年,数不清的灵魂诞生、消逝,无一逃脱死亡的命运。</p> <p>现代医学再怎么发愤图强,依然无法摆脱一个很确定的结局,那就是永远也无法战胜死神。</p> <blockquote> <p>死亡的未知性更令人恐惧。</p> </blockquote> <p>谁也无法预知自己的死亡时间、死亡方式。</p> <p>中国近年死亡人口的2/3是正常死亡,其中主要包括癌症、心脑血管疾病、呼吸系统疾病、新生儿疾病、阿尔兹海默症与痴呆等;1/3是非正常死亡,其中主要包含自杀、交通事故、工伤事故、刑事案件死亡、中毒死亡、自然灾害等。</p> <p>我们都希望能像纪录片中老爷爷一样善始善终,但是也应该对衰老、疾病和意外做好心理准备。</p> <p>如果未知是令人恐惧的,那么了解衰老与死亡就是我们克服恐惧的必修课。</p> <h2>关于本书</h2> <p>《最好的告别》是一本关于死亡的书,作者是哈佛大学医学院的外科教授。</p> <p>这本书梳理了作者所处的美国社会养老的发展历程、医学界对末期病人的不当处置、医药的局限性。</p> <p>但更多地,作者详尽地说明了“善终服务”、“辅助生活”、“生前预嘱”的理念</p> <p>通过这些理念,我们能找到这些问题的答案:</p> <ul> <li>当独立、自助的生活不能再维持时,该怎么办?</li> <li>在生命临近终点时,该和医生谈些什么?</li> <li>如何优雅地跨越生命的终点?</li> </ul> <h2>衰老的真相</h2> <blockquote> <p>生命老化的故事就是身体器官走向衰竭的故事</p> </blockquote> <p>牙齿、骨头软化脆弱,心脏、血管、关节、肺部变硬,肌肉流失,器官运行速度减缓,记忆力减退,感官退化。</p> <p>饮食有限制,行动有限制,听觉、视觉、触觉减弱,还有一定可能性患上痴呆。</p> <p>外表上的变化也很明显,但相比于健康,已不是最重要的事情。</p> <blockquote> <p>衰老是我们的宿命,死亡总有一天会降临。</p> </blockquote> <p>书中说高龄老人们害怕的并不是死亡,而是那之前的种种状况——丧失听力、记忆力,失去最好的朋友和固有的生活方式。</p> <blockquote> <p>老年是一系列连续不断的丧失</p> </blockquote> <p>凭着<strong>运气和严格的自我控制</strong>(注意饮食、坚持锻炼、控制血压、在需要的时候积极治疗),人们可以在很长一段时间内掌控自己的生活。</p> <p>但是,最终所有的丧失会累积到一个点</p> <p>到这个点时,我们会有相当长的一段时间由于身体太衰老、太虚弱而<strong>无法独立生活</strong>。</p> <p>我们不愿意思考这种可能性,结果,大多数人都没有为之做好准备。</p> <h2>过度治疗</h2> <p>一个理智的人在死亡降临的时候还是无法舍弃求生的欲望</p> <blockquote> <p>拉扎罗夫,一位市政府的行政官,60多岁患上转移性的癌症。病中癌症扩散到了胸椎,对脊椎形成压迫,右腿无法动弹,大便失禁。</p> <p>癌症此时已经无法彻底治愈。医生给了两个方案:一是安宁缓和医疗;二是实施手术,切除脊椎处生长的肿瘤包块。</p> <p>尽管手术风险很高,他依然选择了手术,“别放弃我,”他说,“只要我还有任何机会,你们一定要让我尝试。”</p> <p>他的妻子死在监护室里,死的时候全身插满了管子,戴着呼吸机。</p> <p>当时,他曾经说过,他绝不想这样的情形发生在他的身上。但是,时至今日,他却坚决要求采取“一切措施”。</p> <p>从医学技术角度看,手术达到了切除肿瘤的目的,但是他一直没能从手术中恢复过来。</p> <p>他住在监护室,并发了呼吸衰竭、系统性感染,卧床不动又导致了血栓,然后,又因治疗血栓的血液稀释剂而引起了内出血。</p> <p>第十四天,他的儿子告诉医疗组,我们应该停止“治疗”了。</p> <p>医生取出了他嘴里的呼吸管,他咳了几声,眼睛睁开了一小会儿,然后又闭上了。他的呼吸变得越来越吃力,然后终止了。</p> </blockquote> <p>这是书中的真实案例,显然,故事的主人公还没有做好死亡的心理准备。</p> <p>随着现代医疗的发展,像他一样死亡在医院的人越来越多,他们希望这个世界竭尽全力地留住他,但是医疗无法战胜死亡。</p> <p>这是临终病患中最为普遍的情况,拼命抵抗,牺牲病人的生存质量,通过手术、化疗、把他们送到监护室。于是,死的时候,血管里留着化疗药物,喉头插着管子,肉里还有新的缝线。</p> <blockquote> <p>2008年,美国全国抗癌协会发表的研究表明,使用呼吸机、电除颤、胸外按压,或者在临死之前入住监护室的末期癌症患者,其生命最后一周的质量比不接受这些干预措施的病人差很多。在去世之后 6周,他们的照料者患严重抑郁的可能性大了三倍!</p> </blockquote> <p><strong>过度的技术干预</strong>增加了对逝者和家属的伤害,剥夺了他们最需要的<strong>临终关怀</strong>。</p> <h2>临终关怀</h2> <p>当一个人已经无法避免地走向死亡,任何治疗都无法阻止这一过程,甚至会伤害到当事人时,</p> <p>采取<strong>姑息疗法</strong>(不加速也不拖延死亡),只减缓疾病症状,提升病人的心理和精神状态,</p> <p>可以让生命的最后一程走得完满有尊严。</p> <blockquote> <p>临终关怀不是等死,而是好好的走到终点</p> </blockquote> <p>临终关怀并不是放弃,而是给予当事人尊严、舒适感、控制感和有质量的生命。</p> <p>除了单纯地延长生命之外,重病患者还有其他的优先考虑事项。</p> <p>调查发现,重病患者的主要关切包括<strong>避免痛苦、加强与家人和朋友的联系、意识清醒、不成为他人的负担,以及实现其生命具有完整性的感觉</strong>。</p> <p>所以,临终关怀应该做的有:</p> <ul> <li>放弃过度治疗,关注他们的疼痛感,护理、照顾他们的生活</li> <li>维护他们的尊严,尊重他们的意见和选择</li> <li>共同面对死亡,帮助他们完成最重要的心愿</li> </ul> <h2>现在能做什么</h2> <h3>正视死亡</h3> <p>在中国,我们的传统教育和思想,让我们避讳死亡的话题。</p> <p>我的外婆在2018年初头疼,查出肺癌晚期,已经脑转移,在脑部形成大大小小的肿瘤,家人们不敢告诉她真相,安慰她一定会治好。后来带她辗转医院,住院,接受放疗和药物治疗,外婆精神渐渐不清醒,我自始至终不知道,外婆是否知道自己的情况很糟糕,但直到去世,都没有人能够和外婆坦诚地聊一聊死亡。</p> <p>2018年底外婆就走了,外婆不吸烟也没有长期生活在坏空气中,无论是诊断出肺癌晚期还是去世,对我们来说都太突然了。</p> <p>那是我身边第一次有人去世,我后知后觉,但凡当时能在她还清醒时,和她聊一聊她的心愿、情绪、遗憾、对我们的期望,妈妈和小姨失去母亲的痛苦都能减轻一分,我们对外婆的遗憾也不会留存终生。</p> <h3>从死亡的视角 重新考量我们的现在</h3> <p>当你年轻、身体健康的时候,你相信自己会长生不老,从不担心失去自己的任何能力,周围的一切都在提示你“一切皆有可能”。你愿意延迟享受,比方说,花几年的时间,为更明媚的未来获取技能和资源。你努力吸收更多的知识和更大的信息流,扩大自己的朋友圈和关系网,而不是和妈妈黏在一起。当未来以几十年计算(对人类而言这几乎就等于永远)的时候,你最想要的是马斯洛金字塔顶端的那些东西——成就、创造力以及“自我实现”的那些特质。</p> <p>但如果面临死亡的境遇,你的视野会收缩,你开始觉得未来是有限的、不确定的,你的关注点开始转向<strong>此时此地</strong>,放在了日常生活的愉悦和最亲近的人身上。</p> <blockquote> <p>生活是一种技能。老年的平静和智慧是在时间历程中实现的。</p> </blockquote> <p>随着年龄的增长,我们从在意<strong>实现、拥有和得到</strong>转而懂得<strong>欣赏日常生活的愉快和亲密关系</strong>,如果我们发现这更具满足感,那么,为什么我们要等这么久才去做?为什么我们要等到老了才去做?</p> <blockquote> <p>每个早晨我都对着镜子自问, 假如今天是我生命的末日, 我还会想去做 我今天打算做的事情吗? 如果连续几天我的回答都是“No” 我就明白,我需要改变了。 记住“你即将死去”,会使你受益匪浅。</p> </blockquote> <p>这是乔布斯在斯坦福的演讲说过的话,从死亡的视角重新考量我们当下的生活,也许可以让我们找到真正想做的事情。</p> <hr /> <blockquote> <p>如果我明天死去,我也已经度过了愉快的一生。我能做的事都做了,想做的事都做了。</p> </blockquote> <p>希望在我临终前,可以说出这句话。</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/being_mortal_update_210902/#post-comment/</comments>
</item>
<item>
<title>月刊#5 | 2021.07</title>
<link>https://www.scarsu.com/monthly_5_2021_07/</link>
<guid isPermaLink="true">https://www.scarsu.com/monthly_5_2021_07/</guid>
<description>信息流管理、话题推荐、开发资源、Chrome图片工具</description>
<pubDate>Thu, 01 Jul 2021 00:00:00 GMT</pubDate>
<content:encoded><h2>【Grow Up With You】指路人系列</h2> <ul> <li><a>Mike Shakes</a>:从0开始自学一切</li> </ul> <h2>信息流管理</h2> <ul> <li><a>一个(自动化)信息流管理的案例</a></li> <li>RSS收集:大多数网站都有RSS源;没有RSS的网站可以上<a>rsshub</a>、<a>rss.lilydjwg.me</a>找;可以在Feedly中搜索;可以用 <a>feed43</a> 转一个;可以自己写个 serverless function 转下,部署在 <a>now</a> 上</li> <li><a>Feedly 工具</a>用于抓取你收集的RSS源上更新的内容</li> <li><a>笔记应用Obsidian</a>:本地化存储、工作区 文件树 管理、个人用户免费、开放丰富的插件API库、双向链接、关系图谱、思维导图。(我做为一个Notion深度用户,Obsidian对我的吸引力是本地存储和关系图谱,但是还不足以让我弃用Notion转投Obsidian,因为Notion的数据库功能对我来说很重要)</li> <li><a>播客简介&amp;推荐</a></li> </ul> <h2>话题</h2> <ul> <li>小唯UP:<a>不要活在别人的评价体系中</a></li> <li>happy xiao:<a>B级玩家</a></li> <li><a>niche</a>:细分主题、市场定位、长尾效应</li> <li><a>一次网购维权经历</a></li> <li><a>日本老人三行诗</a>:仿佛看到了我们这代人的未来</li> </ul> <blockquote> <p>逗猫棒,挥的太慢,被猫嫌弃了一脸。 ——见边千春 69岁</p> </blockquote> <blockquote> <p>那个医生,以前教我养生,竟然比我先死了。 ——森田志郎 79岁</p> </blockquote> <h2>开发</h2> <ul> <li><a>小程序 极客词典</a>:中国互联网超爱读错的单词</li> <li><a>chiphuyen / ml-interviews-book</a> :机器学习面试指南</li> <li><a>geerlingguy / internet-pi</a>: 树莓派的所有网络配置</li> <li><a>eugeneyan / applied-ml</a>: 公司的论文和技术博客,分享他们在生产中的数据科学和机器学习工作。</li> <li><a>AllThingsSmitty / css-protips</a>:收集CSS tips</li> <li><a>tuteng / Best-websites-a-programmer-should-visit-zh</a>:程序员应该访问的最佳网站中文版</li> <li><a>fent / node-ytdl-core</a>:javascript写的Youtube视频下载器</li> <li><a>webpack老项目 迁移到 Vite</a> :实战经验</li> <li><a>为你的产品量身定制一个图标</a></li> </ul> <h2>Chrome图片工具</h2> <ul> <li><a>ImageAssistant</a>图片助手:自动提取网页图片、批量下载、以图搜图</li> <li><a>Fatkun</a>:微博图片批量下载、转webp图片</li> <li><a>Octo微博相册批量下载</a>:微博用户 相册 照片原图</li> </ul> </content:encoded>
<category>信息源</category>
<comments>https://www.scarsu.com/monthly_5_2021_07/#post-comment/</comments>
</item>
<item>
<title>PodCast 播客简介与推荐</title>
<link>https://www.scarsu.com/podcast_intro/</link>
<guid isPermaLink="true">https://www.scarsu.com/podcast_intro/</guid>
<description>慢消费、轻内容</description>
<pubDate>Wed, 30 Jun 2021 00:00:00 GMT</pubDate>
<content:encoded><h3>为什么听播客</h3> <p>和博客、公众号的长文章、短文章、长视频、短视频这些互联网内容相比,有什么特点?</p> <ul> <li>没有视频和文章直观、快速,是一种<strong>慢消费</strong>内容,快进、倒退、分享不便</li> <li>不占用太多注意力、专注度,更方便在上下班通勤、做家务等场景收听</li> <li>晦涩的内容通过口语表达出来,比看书、看文章更<strong>易接收</strong></li> <li>相比于文章,更能从播者的语言中,得到他传递的情感、力量、态度,更容易和播者建立<strong>情感粘性</strong></li> <li>从生理和记忆的角度看,相比于文字,声音更能给人留下印象</li> <li>没有视频的信息量大,留有边听边<strong>自主思考和想象</strong>的空间</li> <li>比视频尺寸小,更易传输、制作、存储</li> </ul> <h3>播客工具</h3> <ul> <li><a>Android 平台有哪些优秀的播客 (podcast) 应用?</a></li> <li>IOS有原生podcast应用</li> <li>小宇宙App:自用,中文播客app,纯播客app、界面简洁、有平台推荐节目、有社交属性 加时间戳评论类似弹幕 进度条可以显示高能点赞,主要是中文内容,国外内容很少</li> <li>Pocket Casts:自用,外国播客app,英文界面,国外内容较多,中文内容较少</li> </ul> <h3>播客推荐</h3> <ul> <li><a>知乎-有哪些值得关注的播客节目</a></li> <li><a>豆瓣-一些播客推荐</a></li> <li><a>不丧</a>-已更新137期,夫妻档,很真实</li> </ul> </content:encoded>
<category>信息源</category>
<comments>https://www.scarsu.com/podcast_intro/#post-comment/</comments>
</item>
<item>
<title>关于我 | 简短的年中总结</title>
<link>https://www.scarsu.com/2021_mid/</link>
<guid isPermaLink="true">https://www.scarsu.com/2021_mid/</guid>
<description>6月底了,复盘了一下上半年做的事情,对下半年的计划略作调整</description>
<pubDate>Fri, 25 Jun 2021 00:00:00 GMT</pubDate>
<content:encoded><h3>上半年看了3本书</h3> <p>看《忍不住的新努力》,跟胡适学习了如何做一个温和、沉稳、务实,而又乐观、积极的人。</p> <p>看《麦肯锡教我的写作武器》,让我更高效、更合理、更有逻辑的写出你此刻所见到的文章。</p> <p>看《亲密关系》,让我更了解自己的情绪,更懂得维护和伴侣、家人的关系。</p> <h3>开了月刊,更新了4期,会持续更新。</h3> <p>顺便想在此聊一聊为什么开月刊,我写博客、更新公众号,是想做一个能分享一些有价值内容的输出者。</p> <p>但是作为一个25岁没有足够人生阅历、视野认知有局限、没有硕博学历、事业技术水平都没达到行业金字塔顶部的平凡程序员,</p> <p>可能只处于互联网内容产出者金字塔的底部。</p> <p>之前看happy xiao的文章,说互联网内容大多是由B级玩家产出的,内容消费者是C级玩家,真正的A级玩家,是顶部的行业大亨、专家、学者、作家,他们是很少产出互联网内容的。</p> <p>在如今的互联网中,内容产出几乎没有门槛,谁都可以发文章、发视频、开直播,因此B级玩家是一个庞大的群体。</p> <p>每个B级玩家,都有他自己的一套信息渠道,去定期获取新信息,结合自己的思考,才能输出见解。</p> <p>这些信息渠道、信息源不是固定不变的,每个信息源都有其上级信息源,直至追溯到源头的A级玩家。</p> <p>我做月刊的目的,就是把自己不断更新的那些信息渠道、信息源分享出来,让我的博客不仅仅有自己的见解,也有日益更新的信息来源。</p> <p>假如我分享了自己的见解A,分享了这个见解的信息源头B,C,D,那么我传递给你的信息就从A扩展到了B,C,D,</p> <p>你还可以自己从每个B,C,D中继续向上溯源,找到更多有价值的信息,这样就间接实现了这个博客的价值~</p> <p>另一个方面的原因,其实是我忍不住。</p> <p>我觉得好的信息值得分享,不分享出来很可惜,我相信每一次分享,都是对 我想看到的优质互联网内容的一次投票~</p> <h3>优化了我的时间管理方案 GTD</h3> <p>TODO List + Inbox 收集箱 + 知识体系,感兴趣的博友可以看<a>这篇文章</a></p> <p><img src="/images/picgo/picgo20210127180326.png" alt="GTD时间管理" /></p> <h3>优化了我的日记/记账体系</h3> <p>目前稳定实践了三个月,等使用达到半年后,如果觉得省心+高效+有意义,就会分享出来</p> <p><img src="/images/picgo/picgo20210625175717.png" alt="日记" /></p> <p><img src="/images/picgo/picgo20210625175758.png" alt="月结年结" /></p> <h3>上半年<a>NotionX</a>更新了2版本</h3> <p>Google商店中目前的用户量是2160,算是我的开源启蒙项目,希望以后做出更好的技术工具</p> <p><img src="/images/picgo/picgo20210626105832.png" alt="NotionX" /></p> <h3>年初参与了StateOfJS 2020的<a>翻译</a></h3> <p>希望国内外技术社区的隔阂和差异能越来越小</p> <p><img src="/images/picgo/picgo20210626110002.png" alt="StateOfJS 2020" /></p> <h3>上半年只整理了一篇技术文章</h3> <p>上半年在技术学习提升这一方面,主要的时间在看新出的红宝书第四版,学一个算法课程,坚持刷leetcode,处于输入和自我消化的阶段,因此技术输出暂时停滞。</p> <p><img src="/images/picgo/picgo20210626110441.png" alt="红宝书进度" /></p> <p><img src="/images/picgo/picgo20210626110106.png" alt="leetcode热力图" /></p> <p>计划中第四季度会发不少技术文章。</p> <h3>下半年规划</h3> <p>第三季度有两个月要用来考证,还有一个月读两本上半年想看没来得及看的书《卡耐基魅力口才与演讲艺术》和《心流》</p> <p>第四季度集中在技术上,复习一下去年的全栈课、完成红宝书第四版阅读、理清自己的前端知识体系,查漏补缺</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/2021_mid/#post-comment/</comments>
</item>
<item>
<title>亲密关系:好的亲密关系是独立+合作</title>
<link>https://www.scarsu.com/relationship/</link>
<guid isPermaLink="true">https://www.scarsu.com/relationship/</guid>
<description>我们都是完整而独立的个体、而爱情就是拥有一个合作伙伴一起经营人生</description>
<pubDate>Sat, 05 Jun 2021 00:00:00 GMT</pubDate>
<content:encoded><h2>引言</h2> <p>阿德勒曾说过:“一切烦恼都来自于人际关系”</p> <blockquote> <p>因为我们每个人都是社会中的一份子,无法脱离人群和社会独自生存</p> </blockquote> <p>而亲密关系,更是占据了我们人生的大部分篇章</p> <p>子女、父母、爱人、朋友,都是我们人生中不可或缺的角色</p> <p>处理得好,亲密关系能给我们带来极大的快乐</p> <p>处理得不好,则会造成重大创伤和无与伦比的痛苦</p> <h2>恋爱的本质是满足需求</h2> <blockquote> <p>情感是来自人类“爱与被爱”的基本需求</p> </blockquote> <p>开始和维持一段亲密关系背后的真正动机,其实在于需求。</p> <p>在日常生活中,我们的所作所为,绝大部分都是为了让某些需求得到满足。我们追求或吸引别人来做我们的伴侣,是因为我们需要人陪伴、照顾、了解、支持、接受、赞赏、抚摸和相拥而眠……</p> <p><strong>这是人类的本性,并没有什么不对</strong>,但是如果我们认为,我们所需要的快乐、安全感、自尊或其他的许多事物,都要<strong>依赖别人来实现</strong>的话,这就成为一个大问题了。</p> <h2>爱不是依赖、不是占有</h2> <p>每个人的童年时代,没有任何生活能力,所以需要依赖父母来达成的内心的需求、满足归属感、感受自己的重要性。</p> <p>但是当我们长大之后,我们应该培养自己独立生活的能力、自爱的能力,而不是找到一个人,来满足自己的这些感受,弥补这些缺失,从别人身上索取爱。</p> <p>因为如果你依赖别人,当发现对方不满足需求和期望时,就想改造对方,各种“手段”因此而生:</p> <ul> <li>暗示、明示、甚至PUA,以“改造”对方,“如果你真的爱我,你就应该xxx”。</li> <li>吵架,用愤怒当作自我防御、自我欺骗的机制,用愤怒保护自己脆弱的内心。</li> <li>扮演受害者,把自己的伤痛归咎在对方身上。</li> </ul> <p><img src="/images/picgo/picgo20210413155630.png" alt="" /></p> <p>这不是爱,这是把对方当作满足自己内心的需求的工具人。</p> <h2>好的亲密关系是:独立+合作</h2> <blockquote> <p>我们每个人都是完整的个体,不是离开谁活不下去</p> </blockquote> <p>害怕受伤、痛苦、恐惧,渴望永恒真挚、开心、快乐,都是我们生而拥有的情绪,</p> <p>要学会独立消化、处理自己的情绪</p> <p>要学会接受、面对自己,面对自己最好的、最糟的状态</p> <blockquote> <p>每个成年人的行为、决策,都是他生而为人的自由</p> </blockquote> <p>你可以建议、沟通,但是不能干涉、强迫;</p> <p>与自由相应的,每个人都有独立承担其行为后果的责任</p> <p>不要扮演受害者,你的需求未满,不是别人的责任</p> <blockquote> <p>亲密关系,不是我们人生的最终目的</p> </blockquote> <p>亲密关系是丰富我们漫漫人生之旅的风景、增强人生体验的精神补剂</p> <p>要勇于接受未来,舍得放下过去</p> <blockquote> <p>不能把自己的需求和期望,强加在伴侣、亲人、朋友身上</p> </blockquote> <p>要学会自爱,让自己内心变得完整、安全、有爱</p> <p>建立独立完整的自尊体系,心智成熟</p> <p>你跟我在一起,我拥有了<strong>合作</strong>走完人生的伙伴,我可以开心幸福</p> <p>你不跟我在一起,我也能独自看完这世上的风景,我也不会崩溃度日</p> <h2>愉悦与不快都很重要</h2> <p>亲密关系是一种完美设计</p> <p>在亲密关系中,所有的一切都是重要的部分,即使是令人不悦的冲突与不适的情境。</p> <p>当你继续在感情中成长时,你也开始<strong>懂得欣赏你跟伴侣之间所发生的任何事情</strong>。</p> <p>你的伴侣不是你的爱与幸福的来源,满足你的期待与使你开心不是他们的职责。</p> <p>你的伴侣在你的生活中扮演了三个重要的角色:</p> <ul> <li>一面镜子,让你看见引发你关注的不舒服感;</li> <li>一名老师,在你探寻真实自我的时候,激励与启发你;</li> <li>一名“玩伴”,开启并陪伴你一段生命的旅程。</li> </ul> <h2>不要过度追求浪漫主义的恋爱</h2> <p>一见钟情的颜值、小鹿乱撞的心动、一束花、</p> <p>一次表白、几句甜言蜜语、嘘寒问暖、</p> <p>肾上腺素飙升的亲密接触、轰轰烈烈的你追我逐、</p> <p>都是爱情的修饰,而不是爱情本质,</p> <p>不要再通过 小说/影视剧/磕cp去 学习爱情,</p> <p>坚持读书、勇于识人,可以补充我们缺少的“爱情教育”</p> <p>积累知识和人生经验,去成就洒脱、成熟的亲密关系</p> <h2>总结</h2> <p>慕名而读,结果读错了,不是这本,是另一本罗兰·米勒的《亲密关系》。但是看完了这本书,还是有一定收获的。</p> <p>这本书从心理学和人性的角度,直戳亲密关系中的问题,以及问题出现的原因。</p> <p>边看书边审视自己的上一段恋爱,从而发现导致分手的原因双方都有责任,过去对他的埋怨和不满也放下了,把这本书推荐给他看之后,我们复合了。从高中到工作第三年,我们从懵懂无知地向往爱情,到热恋期的亲密无间 ,到归于平淡,再到吵吵闹闹,互相埋怨,分道扬镳......</p> <p>一切都是因为我们不懂爱情,我们在年少无知的时候选择了彼此,把彼此当作依赖,当作生活、工作、压力的唯一寄托和宣泄口,把彼此当作那个 理所当然、应该无条件支持、纵容自己的人。</p> <p>现在我们才懂,我们都是完整而独立的个体、而爱情就是拥有一个合作伙伴一起经营人生</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/relationship/#post-comment/</comments>
</item>
<item>
<title>月刊#4 | 2021.05-06</title>
<link>https://www.scarsu.com/monthly_4_2021_05-06/</link>
<guid isPermaLink="true">https://www.scarsu.com/monthly_4_2021_05-06/</guid>
<description>指路人系列、开发资源、有意思的资源、纪录片推荐</description>
<pubDate>Tue, 01 Jun 2021 00:00:00 GMT</pubDate>
<content:encoded><h2>【Grow Up With You】指路人系列</h2> <ul> <li><a>霍孙杨 hcy</a>: Vue核心团队成员,Vue设计分析文章《Vue Design》作者</li> </ul> <h2>开发资源</h2> <ul> <li><a>MDH • 前端情报日刊</a>:社群活跃,每日更新</li> <li>最新的<a>前端框架性能对比结果</a>、<a>分析文章</a>、<a>了解测试的基准</a></li> <li><a>You-Dont-Need-JavaScript</a>: 用原生CSS实现UI逻辑</li> <li><a>免费公开API搜集仓库</a></li> <li><a>动画算法仓库</a></li> <li>手写<a>easy webpack</a> ,熟悉AST</li> </ul> <h2>纪录片推荐</h2> <ul> <li><a>海豚湾 2009</a></li> </ul> <h2>有意思的资源</h2> <ul> <li><a>FUNN.FUN</a>: 奇趣网站收藏家</li> <li><a>世界电台</a>:从世界地图上探索全世界电台</li> <li><a>Deep Nostalgia</a>:将人脸照片转换成表情视频</li> <li><a>NandGame</a>:从逻辑电路开始一步一步制造电脑的游戏</li> </ul> <p><img src="/images/picgo/picgo20210604101214.png" alt="NandGame" /></p> </content:encoded>
<category>信息源</category>
<comments>https://www.scarsu.com/monthly_4_2021_05-06/#post-comment/</comments>
</item>
<item>
<title>月刊#3 | 2021.04</title>
<link>https://www.scarsu.com/monthly_3_2021_04/</link>
<guid isPermaLink="true">https://www.scarsu.com/monthly_3_2021_04/</guid>
<description>舒适生活指南、职业发展、投资、话题、文章推荐</description>
<pubDate>Thu, 01 Apr 2021 00:00:00 GMT</pubDate>
<content:encoded><h2>舒适生活</h2> <ul> <li>成年人<a>如何科学地应对压力?</a></li> <li><a>每天晚上睡觉之前写下当天发生的3件好事</a>:低成本持续幸福</li> <li><a>写日记的意义</a>:和自己对话</li> <li><a>闲鱼攻略</a></li> </ul> <h2>职业发展</h2> <ul> <li>Solo Developer:<a>两位独立开发者</a></li> <li>若川:<a>公众号运营策略</a></li> <li>Happy Xiao博客推荐:<a>你在展示你是谁,你如何思考,而不是你在想什么</a></li> </ul> <h2>投资</h2> <ul> <li>【<a>2020胡润财富报告</a>】目前中国拥有600万人民币资产、千万人民币资产、亿元人民币资产和3000万美金资产的家庭数量和地域分布情况,包括中国内地和香港、澳门、台湾</li> <li>【业界事件】<a>一表看完散户大战华尔街全过程(持续更新)</a></li> <li>【投资思维】<a>复利的谎言</a> 随机性、不连续性、不均匀性、非对称性、思考&gt;勤奋</li> <li>【投资分析】<a>中国居民会增加股票配置吗?</a></li> </ul> <h2>话题推荐</h2> <ul> <li>【自律=压抑欲望?】 所谓自律,就是主动要求自己以积极的态度承受痛苦。——<a>《少有人走的路》</a></li> <li>【感情是信念的基础】“爸爸说我很冷静,他并没有真正理解我,我认为,有时候,感情是信念的基础,这里有我汗水浸过的土地,这里有我患难与共的亲友,这里有我相濡以沫的妻子,这里有我生命的根。”——电影<a>《牧马人》</a></li> <li>【投射】我们所看到的每件事其实都是我们内心的投射。我们怎么评论别人,就是我们怎么看待自己。如果我觉得别人太爱批评而讨厌他,就代表我讨厌自己爱批评的习性。——<a>《亲密关系》</a></li> </ul> <h2>文章推荐</h2> <ul> <li>教育内卷现状:<a>为了鸡娃,上海的家长到底有多拼</a></li> <li><a>「翻墙违法是无可争议的事实」</a></li> </ul> </content:encoded>
<category>信息源</category>
<comments>https://www.scarsu.com/monthly_3_2021_04/#post-comment/</comments>
</item>
<item>
<title>麦肯锡教我的写作武器:如何无痛写文章</title>
<link>https://www.scarsu.com/writing_tech/</link>
<guid isPermaLink="true">https://www.scarsu.com/writing_tech/</guid>
<description>写作能力是这个时代许多行业的基本功</description>
<pubDate>Sun, 28 Mar 2021 00:00:00 GMT</pubDate>
<content:encoded><h2>引言 - 写文章为什么令我痛苦</h2> <p>作为一个理科生,要问我学生生涯最讨厌的是什么,我无疑会回答<strong>写作文</strong>。</p> <p>无论是小学的流水账日记,</p> <p>还是高考的800字作文,</p> <p>甚至是现在工作上的文档/报告,</p> <p>都曾为我的脱发症增添几分贡献🤧。</p> <p>自从维护博客/写公众号以来,我常常反思,<strong>写文章为什么令我痛苦</strong></p> <p>我写文章,一是为了将我自己对某些事物的思考/总结记录下来,供自己回顾;二是为了分享给你,听听你不同的见解。</p> <p>总归是有一些东西在脑子里,想表达出来,却缺乏章法🤯。</p> <p>因此在朋友给我推荐这本书的时候,就没有犹豫加入书单了✅。</p> <h2>《麦肯锡教我的写作武器》是怎样的书</h2> <p>这本书可以说是一本<strong>商务文案写作指南</strong></p> <p>虽说是商务文案,但是也同样适合日常写作和技术文章。</p> <p>因为这本书<strong>从信息筛选、遣词造句,到整体结构的设计</strong>这些方面,介绍了写文章的通用技巧和思维。</p> <p>下面的正文,会从上述的三个方面,总结书中的内容。</p> <h2>信息筛选</h2> <h3>信息是组成文章的“零件”</h3> <p>写作本质上就是信息的整合。</p> <p>能明确表现主语与谓语的关系的句子,都是信息。</p> <p>“这瓶农夫山泉的容量是500ml”可以作为一条信息;</p> <p>“农夫山泉”、“500ml”这种单独的对象,都不是信息;</p> <h3>信息分三类</h3> <ul> <li><strong>记述信息</strong>:描述事物的情况和现象本身,常常包含现象、数据、经验、实例(平铺直叙)</li> </ul> <p>例子🌰:本篇文章总结了《麦肯锡教我的写作武器》这本书的主要内容。</p> <ul> <li><strong>评价信息</strong>:表达某一情况或现象的好坏(有形容词)</li> </ul> <p>例子🌰:《麦肯锡教我的写作武器》这本书很值得读。</p> <ul> <li><strong>规范信息</strong>:要求事物应有的状态以及人该采取的行动(有动词)</li> </ul> <p>例子🌰:你应该读一读《麦肯锡教我的写作武器》。</p> <p><strong>区分清楚信息类型非常重要</strong>,以书中的一处对话为例🌰:</p> <blockquote> <p>主管:山田,X公司最近的业绩如何?</p> <p>山田:是……X公司最近一季的销售额为220亿日元,营业利益为5亿日元。自由现金流量(Free Cash Flow)为87亿日元。昨天股票的收盘价为每股358日元。</p> <p>主管:喔,所以呢……</p> <p>山田:啊!是……好像还有特别损失的部分,再扣除税之后,利益为2亿日元。利息支出大概是1千万日元左右。</p> <p>主管:所以呢?</p> <p>山田:啊!还有……该公司利息收入为200万日元。销售成本是……</p> <p>主管:我是问你“他们的业绩怎么样?好还是不好?”</p> <p>山田:喔!是……似乎回升了不少。</p> <p>主管:好啦,有上升就是了,我知道了……</p> </blockquote> <p>从上面的对话可以看出来,主管想要了解的是<strong>评价信息</strong>,并进行了四次提问才得到想要的回答,而山田小呆呆前三次都回答的是<strong>记述信息</strong>。</p> <p>所以为了避免像他一样给上司留下“鸡同鸭讲、对牛弹琴”的不良印象❌,</p> <p>同样为了避免给文章读者造成混淆❌</p> <p>在传达信息前,我们应该明确,究竟要传达哪一类信息。</p> <h3>活用三种类型的信息</h3> <p>记述信息 + 评价标准:有“评价信息”的效果,却比直接评价更委婉。🌰例如小明的妈妈说:你这次考了40分,60分是及格分。</p> <p>评价某种行为的信息:有“规范信息”的效果,却比规范信息更委婉。🌰例如小明的妈妈接着说:下次再考40分就过分了。</p> <p>如果你表达了某一类信息,例如记述信息,别人仍然说“听不懂”时,可以接着说出评价信息、规范信息。🌰例如小明对妈妈说:这台电脑RAM有32G。+运行内存很大,电脑运行十分流畅。+妈妈你应该买给我学习。</p> <h3>文章的主题不是信息</h3> <p>一般来说,文章的主题不应该是一条信息,🌰例如“我分享了一篇关于《麦肯锡教我的写作武器》的文章”不适合作为文章的主题。</p> <p>文章的主题应该告诉别人你文章内<strong>信息的范围</strong>,🌰例如“《麦肯锡教我的写作武器》读后感觉”可以作为文章主题。</p> <p>此外,用“时间”替主题定调,可以增加吸引力,🌰例如"三分钟了解《麦肯锡教我的写作武器》"。</p> <h2>遣词造句</h2> <p>信息的筛选很重要,如何将信息合适的表达出来也很重要,</p> <p>想让信息提升说服力,可以从遣词造句下手。</p> <h3>1. 善用主语</h3> <p>明确表达一条信息,核心在于,高度明确的<strong>主语与谓语的关系</strong>。</p> <p>在日常生活口语中,我们常常习惯于省略主语,但是这个习惯带入到文章中,容易造成误解、加重阅读负担。</p> <p>此外,也可以通过主语影响别人思考,🌰例如:“门要关了”,“列车员要关门了”这两句话,后一句的主语时活生生的人,会引发听者更多思考。</p> <h3>2. 明确逻辑,善用连接词</h3> <p>文字的逻辑性是否强,思维是否流畅,很大程度上取决于<strong>连接词</strong>。</p> <p>连接词用好,可以降低阅读负担,让文章一气呵成。</p> <p>🌰举个例子,如果删去下面这段话中加粗的连接词,会给人一种“这段话每个句子我都认识,但就是不知道想表达什么”的感觉:</p> <blockquote> <p>美国总统明年一月开始进入第二任的任期,<strong>关于执政</strong>(解说),国民年金以及税制的根本改革是优先课题。<strong>首先</strong>(分点1),国民年金将导入确定提拔型的“个人结算”,<strong>以</strong>(目的)防止高龄化带来的年金财政的缺口。<strong>其次</strong>(分点2),简化繁杂的所得税制,<strong>同时</strong>(追加)继续保持减税路线,<strong>为的是</strong>(目的)长期的经济成长。<strong>当然</strong>(让步),要努力减少过去最严重的“双重赤字”,也就是财政赤字和贸易赤字。<strong>不过</strong>(转折),在通往实现的道路上,困难重重。</p> </blockquote> <p>常见的逻辑连接词及分类可以参考下图:</p> <p><img src="/images/picgo/picgo20210324101814.png" alt="高杉逻辑连接词表" /></p> <h3>3. 用词“具体”</h3> <p>滥用抽象的表达,是不负责任的表现。</p> <p>“……的活性化”、“……的多样化”、“重新评估”、“推动”、“调整”这类词汇仅仅可以用于表达一个方向性,如果用多了,会显得文章空泛、圆滑闪躲。</p> <h3>4. 合理分段</h3> <p>一个分段最好传达单一的信息。</p> <p>分段的数量也有小tips,最少3个,5、7这样的质数也比较合适,因为3是稳定结构的最小数量,7是科学证明人类一次能记住的最大数量,而质数更容易被记忆。</p> <h2>文章结构</h2> <p>前两段,分别讲了如何筛选合适的信息、如何遣词造句以更好的传达信息,</p> <p>除了表达独立的信息,整体文章的设计也很重要。</p> <h3>金字塔结构</h3> <p>金字塔结构是写大多数文章的常用结构,分为多个层级</p> <ol> <li>主要信息</li> <li>关键信息</li> <li>次要信息</li> </ol> <p><img src="/images/picgo/picgo20210324122454.png" alt="金字塔结构" /></p> <p>和思维导图一样,金字塔结构可以一路扩展下去,这样的结构,逻辑性强,条理清晰。</p> <h3>由上而下⬇️设计结构(分解</h3> <p>当你拥有一个写作目标时,例如高考的命题作文,就可以由上而下设计文章结构。</p> <p>先选定一个主要信息,然后再分解成个别的关键信息。</p> <p>分解的方法有理由法和详述法,考虑“为了让上层信息更有说服力,要用哪些下层信息比较能够支持论点”,来设计信息。</p> <h3>由下而上⬆️设计结构(抽象、摘要</h3> <p>当你拥有一些零散信息和思维时,可以由下而上设计文章结构。</p> <p>由下而上法就是要将位于下层的信息群往上精炼,成为上层的信息。</p> <p>具体来说,需要先将零散信息分组,再通过结论法和摘要法,得到上层信息。</p> <p>通常我写读书笔记就是采用这种方法:看书时,标记出有收获的字句、段落,输出笔记时,聚合所有的标记、分类、向上提炼,三步套路之后,写读书笔记就能得心应手。</p> <p><img src="/images/picgo/picgo20210324123212.png" alt="由下而上" /></p> <h3>MECE:不重复不遗漏</h3> <p>除了主题的数量、金字塔结构,还有一个在构成关键主题时很重要的概念,那就是主题之间是否为MECE。</p> <p>MECE的全称是“Mutually Exclusive Collectively Exhaustive”,直译之意为“相互排他性、集合网罗性”,也有人翻译成“不重复、不遗漏”。</p> <p>将关键主题设定在三、五、七个,目的在于分类能够清楚,<strong>没有重复冗余</strong>,同时又能<strong>足够完整</strong>地网罗重要条目,没有遗漏。</p> <h2>结语</h2> <p>掌握了信息筛选、遣词造句、结构设计,足够写出一篇逻辑清晰的文章,</p> <ul> <li>如何将脑子里的种种思维,以更有逻辑的形式,形成文章</li> <li>如何提高文章说服力</li> <li>如何流畅写作,提高写作效率</li> </ul> <p>这些写作最核心的问题,也能找到答案。</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/writing_tech/#post-comment/</comments>
</item>
<item>
<title>月刊#2 | 2021.03</title>
<link>https://www.scarsu.com/monthly_2_2021_02/</link>
<guid isPermaLink="true">https://www.scarsu.com/monthly_2_2021_02/</guid>
<description>2020年总结收集、学习资源、Notion相关资源、工作、书单、话题</description>
<pubDate>Mon, 01 Mar 2021 00:00:00 GMT</pubDate>
<content:encoded><h2>2020年总结收集</h2> <ul> <li><a>若川的2020年度总结,水波不兴</a> (川佬的第七个年总结</li> <li><a>前端劝退师:晃荡一年,我那错乱无力的2020 | 年度总结</a> (晃荡又不失风骚的职业旅程</li> <li><a>惊天码盗:2020年度总结(增长的朋友)</a> (偏重于学习/工作/职业成长</li> <li><a>一位阿里前端er的年总结</a> (生活、工作、兴趣、理财,主题丰满</li> </ul> <h2>学习资源</h2> <ul> <li>英文演讲/影子跟读【Never Give Up】尼克·胡哲 <a>音频</a> <a>中英文稿</a></li> <li><a>神经网络入门教程 - freecodecamp</a></li> <li><a>docker教程 - freecodecamp</a></li> <li><a>如何快速进入学习状态 - bilibili</a></li> </ul> <h2>Notion相关资源</h2> <ul> <li>Notion 自动化:Notion API key + <a>Automate.io</a></li> <li>Mac <a>alfred Notion搜索快捷操作</a></li> <li><a>Notion子弹笔记</a></li> </ul> <h2>工作</h2> <ul> <li><a>工作中提高效率的方法</a></li> <li><a>前端软技能,反制职场PUA</a></li> <li>敏捷项目管理:<a>notion 看板</a>,<a>飞书多维表格</a></li> </ul> <h2>书单</h2> <ul> <li><a>女权书单</a></li> <li><a>30+大男孩的世界好奇书单</a></li> <li><a>学科入门书单/短板补充书单</a></li> </ul> <h2>话题</h2> <ul> <li>【自律=压抑欲望?】 所谓自律,就是主动要求自己以积极的态度承受痛苦——<a>《少有人走的路》</a></li> <li>【“人设”的作用】是快速让对方知道能从你身上获得哪一类内容。</li> <li>【投资】<a>一表看完散户大战华尔街全过程(持续更新)</a></li> <li>【职业故事】<a>两位独立开发者</a></li> </ul> </content:encoded>
<category>信息源</category>
<comments>https://www.scarsu.com/monthly_2_2021_02/#post-comment/</comments>
</item>
<item>
<title>前端图标的那些事</title>
<link>https://www.scarsu.com/iconfont/</link>
<guid isPermaLink="true">https://www.scarsu.com/iconfont/</guid>
<description>更新svg-symbol</description>
<pubDate>Sat, 13 Feb 2021 00:00:00 GMT</pubDate>
<content:encoded><ul> <li>初次发布于2020-02-19</li> <li>第二次编辑于2021-03-13,更新svg-symbol</li> </ul> <hr /> <h2>前言</h2> <p>用了矢量图标,</p> <p>UI再也不吐槽你页面的图标放大后有点糊了...</p> <p>PM再也不会嫌弃你画的页面图片太大,太占load time了...</p> <p>你也不用因为一个hover状态,就写一段换图片src的逻辑了...</p> <h2>矢量图标</h2> <ul> <li>不会因为放大/缩小而导致图标变模糊,即可以任意定义尺寸的icon。</li> <li>在现代前端项目中,除了任意定义尺寸,对图标的要求还有定义颜色等等。</li> </ul> <h2>字体图标</h2> <ul> <li>以字体的形式定义的图标,可以像字体一样定义尺寸,颜色。</li> <li>优点:体积小(用到的图标越多性价比越高);样式便于控制,与字体一样可以调节font-size,color,阴影,旋转,透明度,且兼容低版本浏览器。</li> <li>方法与原理:UI提供svg矢量图 -&gt; 用工具将svg转换成字体文件 -&gt; 前端在css中自定义font-face,通过unicode的方式使用图标。</li> <li>可以使用主流的字体图标库:fontAwesome,阿里的iconfont。</li> <li>也可以使用自动化工具,例如<a>@ztwx/webfont</a>:可以自动化上述过程,运行工具打开网页后,上传svg文件,自动更新代码中的字体文件和css文件。</li> <li>缺点:需要UI合作;每次图标变更都需要重新生成字体文件,更改css中定义的font-face和class。</li> <li>前端引用iconfont主流方式:</li> </ul> <ol> <li> <p>直接使用Unicode字符</p> <ul> <li>兼容性最好,支持 IE6+,及所有现代浏览器。</li> <li>支持按字体的方式去动态调整图标大小,颜色等等。</li> <li>但是因为是字体,所以不支持多色。</li> </ul> <pre><code>/*第一步:自定义@font-face,引用字体文件*/ @font-face { font-family: 'iconfont'; src: url('iconfont.eot'); src: url('iconfont.eot?#iefix') format('embedded-opentype'), url('iconfont.woff2') format('woff2'), url('iconfont.woff') format('woff'), url('iconfont.ttf') format('truetype'), url('iconfont.svg#iconfont') format('svg'); } /*第二步:定义使用 iconfont 的样式*/ .iconfont { font-family: "iconfont" !important; font-size: 16px; font-style: normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } /*第三步:挑选相应图标并获取unicode编码,应用于页面*/ &lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt; </code></pre> </li> <li> <p>font-class(使用最多)</p> <ul> <li>unicode变体,解决了unicode编码语义不明确的问题,书写更直观。可以很容易分辨这个 icon 是什么,著名的<strong>FontAwesome</strong>即使用该方式</li> <li>兼容性良好,支持 IE8+,及所有现代浏览器。</li> <li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li> <li>本质上还是字体,所以多色图标还是不支持的。</li> </ul> <pre><code>/*第一步:自定义@font-face,引用字体文件*/ @font-face { font-family: "iconfont"; src: url("iconfont.eot"); src: url("iconfont.eot?#iefix") format("embedded-opentype"), url("iconfont.woff2") format("woff2"), url("iconfont.woff") format("woff"), url("iconfont.ttf") format("truetype"), url("iconfont.svg#iconfont") format("svg"); } /*第二步:定义iconfont样式*/ .iconfont { font-family: "iconfont" !important; font-size: 16px; font-style: normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } /*第三步:定义每个icon unicode 样式类*/ .icon-gouwuche:before { content: "\e669"; } </code></pre> <pre><code>&lt;!-- 第四步:引入1,2步的css --&gt; &lt;link rel="stylesheet" href="./iconfont.css" /&gt; &lt;!-- 第五步:挑选相应图标并使用定义的类名,应用于页面: --&gt; &lt;span class="iconfont icon-xxx"&gt;&lt;/span&gt; </code></pre> </li> <li> <p>Symbol</p> <ul> <li>本质是svg,支持多色。</li> <li>较新的使用方式,兼容性较差,支持 IE9+,及现代浏览器。</li> <li>通过一些技巧,支持像字体那样,通过 font-size, color 来调整样式。</li> <li>浏览器渲染 SVG 的性能一般,还不如 png。</li> </ul> <pre><code>&lt;!-- 第一步:引入js代码 --&gt; &lt;script src="./iconfont.js"&gt;&lt;/script&gt; </code></pre> <pre><code>/* 第二步:加入通用css样式(引入一次即可) */ .icon { width: 1em; height: 1em; vertical-align: -0.15em; fill: currentColor; overflow: hidden; } </code></pre> <pre><code>&lt;!-- 第三步:挑选相应图标并获取类名,应用于页面: --&gt; &lt;svg class="icon" aria-hidden="true"&gt; &lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt; &lt;/svg&gt; </code></pre> </li> </ol> <h2>icon最佳实践:svg图标</h2> <ul> <li>除了字体图标,现代前端项目中使用更多的是Svg图标</li> <li><code>&lt;svg&gt;</code>及其一系列元素,用于矢量图像的结构、绘制与布局</li> <li><code>&lt;symbol&gt;元素</code>,是可复用的svg图像,用来定义一个图形模板对象,它可以用一个<code>&lt;use&gt;</code>元素实例化。</li> </ul> <pre><code>&lt;svg&gt; &lt;!-- symbol定义模板(symbol本身不会显示图像 --&gt; &lt;symbol id="sym01" viewBox="0 0 150 110"&gt; &lt;circle cx="50" cy="50" r="40" stroke-width="8" stroke="red" fill="red"/&gt; &lt;circle cx="90" cy="60" r="40" stroke-width="8" stroke="green" fill="white"/&gt; &lt;/symbol&gt; &lt;!-- 使用use元素才能实例化 --&gt; &lt;use xlink:href="#sym01" x="0" y="0" width="100" height="50"/&gt; &lt;use xlink:href="#sym01" x="0" y="50" width="75" height="38"/&gt; &lt;use xlink:href="#sym01" x="0" y="100" width="50" height="25"/&gt; &lt;/svg&gt; </code></pre> <ul> <li><code>symbolId</code>:在<code>&lt;use&gt;</code>元素的<code>xlink:href</code>属性需要指向symbol元素的id</li> <li>优点: <ol> <li>svg图标拥有字体图标的各种优点此外</li> <li>svg不需要UI转成字体、定义font-face,只需要原始的svg代码,即可使用。</li> <li>通过现代前端工具整合,svg图标变更时,只需要变更单个svg文件,耦合度低</li> </ol> </li> </ul> <h2>svg symbol应用于现代前端框架</h2> <ul> <li>创建svg目录,存放一个svg文件,例如<code>@/assets/svg/test.svg</code></li> <li>在webpack中配置<code>svg-sprite-loader</code>,匹配上述的svg文件,并将其symbolId配置为svg文件名,详情参考<a><code>svg-sprite-loader</code>文档</a></li> </ul> <pre><code>// 以下为vue cli4的配置 module.exports = { chainWebpack(config){ // 1. 将./src/assets/svg排除在vue的默认webpack配置的svg规则之外 config.module.rule('svg') .exclude.add(resolve('./src/assets/svg')) // 2. 添加一条icons规则 config.module.rule('icons') .test(/\.svg$/) // 匹配svg后缀的文件 .include.add(resolve('./src/assets/svg')).end() // 添加规则生效的路径 .use('svg-sprite-loader') // 使用svg-sprite-loader插件 .loader('svg-sprite-loader') // 加载svg-sprite-loader插件 .options({symbolId: 'icon-[name]'}) // name:文件名,此处的symbolId即svg的xlink:href属性,xlink:href="#icon-文件名" } ... } </code></pre> <ul> <li>在vue模板中即可直接使用</li> </ul> <pre><code>// text.vue &lt;template&gt; ... &lt;svg :class="svgClass" v-on="$listeners"&gt; &lt;use xlink:href="#icon-test"&gt;&lt;/use&gt; &lt;/svg&gt; ... &lt;/template&gt; import '@/assets/svg/test.svg'; ... </code></pre> <ul> <li>更进一步的封装:不需要每个icon都import;<code>&lt;svg-icon&gt;</code>组件;</li> </ul> <ol> <li>通过webpack上下文,将svg文件作为固定上下文,即可避免手动import,用到了webpack中的<a>require.context api</a></li> </ol> <pre><code>// @/assets/svg/index.js // 使用 webpack提供的require.context()指定svg为固定上下文 function importAll(r) { r.keys().forEach(r); } importAll(require.context("@/assets/svg", false, /\.svg$/)); </code></pre> <ol> <li>在main.js中引入上述js文件</li> </ol> <pre><code>import "@/assets/svg/index.js"; // svg上下文 </code></pre> <ol> <li>封装icon组件</li> </ol> <pre><code>&lt;template&gt; &lt;svg :class="svgClass" v-on="$listeners"&gt; &lt;use :xlink:href="iconName" /&gt; &lt;/svg&gt; &lt;/template&gt; &lt;script&gt; export default { name: "SvgIcon", props: { // iconClass要和svg的文件名一致 iconClass: { type: String, required: true, }, // className可以用来定制样式 className: { type: String, default: "", }, }, computed: { iconName() { return `#icon-${this.iconClass}`; }, svgClass() { if (this.className) { return "svg-icon " + this.className; } else { return "svg-icon"; } }, }, }; &lt;/script&gt; &lt;style scoped&gt; .svg-icon { width: 1em; height: 1em; vertical-align: -0.15em; fill: currentColor; overflow: hidden; } &lt;/style&gt; </code></pre> <ol> <li>在main.js中注册全局组件</li> </ol> <pre><code>import SvgIcon from '@/components/common/SvgIcon.vue' Vue.component('SvgIcon', SvgIcon) </code></pre> <ol> <li>使用</li> </ol> <pre><code>&lt;svg-icon iconClass="test"&gt;&lt;/svg-icon&gt; </code></pre> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/iconfont/#post-comment/</comments>
</item>
<item>
<title>月刊#1 | 2021.02</title>
<link>https://www.scarsu.com/monthly_1_2021_01/</link>
<guid isPermaLink="true">https://www.scarsu.com/monthly_1_2021_01/</guid>
<description>推荐文章、优质信息源、学习资源、流量积累、看看机会</description>
<pubDate>Mon, 01 Feb 2021 00:00:00 GMT</pubDate>
<content:encoded><h2>我的本月文章</h2> <ul> <li><a>2021年,给自己来点鸡血</a></li> <li><a>《当我谈跑步时我谈些什么》:痛苦难以避免,而磨难可以选择</a></li> <li><a>【GTD时间管理】高效低耗的应对信息洪流</a></li> <li><a>我做了一年公众号有多少收入?</a></li> </ul> <hr /> <h2>推荐文章</h2> <ul> <li><a>构建个人知识体系</a></li> </ul> <blockquote> <p>知识习得的闭环:信息 → 学习内化 → 输出 → 应用 → 信息</p> </blockquote> <ul> <li><a>早起和赚钱,这2件事的逻辑其实一样</a></li> </ul> <blockquote> <p>用培养技能的逻辑,做到早起</p> </blockquote> <hr /> <h2>优质信息源</h2> <ul> <li><a>构建我的被动收入</a> - 马大伟</li> </ul> <blockquote> <p>终身学习(认知杠杆) → 全栈技术(时间杠) → 投资理财(财务杠杆) → 被动收入(人生杠杆)</p> </blockquote> <ul> <li><a>美团技术博客</a></li> </ul> <blockquote> <p>更新稳定,积累多,技术领域宽泛</p> </blockquote> <hr /> <h2>学习资源</h2> <ul> <li> <p><a>美团技术沙龙——85个演讲,70+小时视频</a></p> </li> <li> <p><a>技术人必读书单-美团</a></p> </li> <li> <p><a>技术团队书单-美团</a></p> <ul> <li> <p><strong>通用能力类:6本</strong></p> <p><a>原则</a> 8.3</p> <p><a>系统之美</a> 8.2</p> <p><a>潜力量</a> 8.7</p> <p><a>乔布斯的魔力演讲</a> 7.8</p> <p><a>远见 : 如何规划职业生涯3大阶段</a> 7.7</p> <p><a>事实 : 用数据思考,避免情绪化决策</a> 8.0</p> </li> <li> <p><strong>经济管理类:6本</strong></p> <p><a>孙子兵法</a> 9.4</p> <p><a>格鲁夫给经理人的第一课</a> 9.1</p> <p><a>刷新</a> 7.5</p> <p><a>关键时刻MOT</a> 8.2</p> <p><a>领导梯队</a> 8.1</p> <p><a>经济学通识课</a> 8.3</p> </li> <li> <p><strong>哲学历史类:8本</strong></p> <p><a>光荣与梦想</a> 8.7</p> <p><a>民国大人物</a> 6.5</p> <p><a>极简欧洲史</a> 8.2</p> <p><a>世界观</a> 8.9</p> <p><a>当下的力量</a> 8.0</p> <p><a>枪炮、病菌与钢铁:人类社会的命运</a> 8.8</p> <p><a>传习录</a> 9.3</p> <p><a>西方心理学史</a> 6.7</p> </li> <li> <p><strong>人物传记类:3本</strong></p> <p><a>邓小平时代</a> 9.2</p> <p><a>我的世界观</a> 8.9</p> <p><a>曾国藩传</a> 6.8</p> </li> </ul> </li> </ul> <hr /> <h2>流量积累</h2> <ul> <li> <p><a>独立博客 流量可视化案例</a></p> </li> <li> <p><a>零成本搭建现代博客之订阅推送篇</a></p> </li> </ul> <p>独立博客流量的即时性</p> <hr /> <h2>看看机会</h2> <ul> <li> <p>【JD】莉莉丝(年终抽奖真香</p> <ul> <li>莉莉丝游戏 - 平台组</li> </ul> <pre><code>公司名:莉莉丝游戏 部门名称:平台组 工作城市:上海 经验要求:2年以上 招聘岗位:前端工程师(P6、P6+) 职位描述: 1、负责公司官网,社区,平台开发和维护; 2、负责游戏管理系统的开发; 3、参与平台产品的架构优化,性能优化。 职位要求: 1、精通html5、css3、javascript、ajax等web开发技术,掌握至少一种前端框架,如react,angular,vue。熟悉ECMAscript6/7语法; 2、熟悉不同版本浏览器的兼容性、能够对不同尺寸设备进行适配; 3、至少一门后端开发语言,如nodejs,php,java等。掌握数据库和缓存系统,如mysql,memcached,redis等 ; 4、有一定的架构设计理念,熟悉常用设计模式; 5、有良好的ui交互实现能力、能熟练使用photoshop进行切图; 6、计算机或相关专业本科及以上学历; 内推联系人(微信):Jaked_M 内推联系人(邮箱):liuchao@lilith.com </code></pre> <ul> <li>莉莉丝游戏 - Avatar项目组</li> </ul> <pre><code>公司名:莉莉丝游戏 部门名称:Avatar项目组 工作城市:上海 经验要求:3年以上 招聘岗位:RN工程师(P6 ~ P7) 职位描述 1、负责社区核心产品的设计、开发、维护工作 2、负责App基础组件和架构设计,编写高质量代码 3、和产品经理配合,深度参与产品需求讨论,功能定义,优化产品体验 4、研究移动平台新技术,持续优化App性能,对齐业内一流产品水平 任职要求 1、大学本科或以上学历,3年以上工作经验 2、iOS/Android端开发经验(高级android开发优先),具备一定双端开发能力者优先 3、深入理解Android端界面绘制原理/iOS端内存管理机制 4、熟悉网络通信机制和常用协议,有网络连接优化经验者优先 5、熟悉移动端性能调优方法 6、熟悉设计模式的相关知识 7、有即时通信产品开发经验者优先 8、熟悉React Native框架/JS语言者优先 9、了解swift/kotlin语言者优先 内推联系人(微信):Jaked_M 内推联系人(邮箱):liuchao@lilith.com </code></pre> <ul> <li>莉莉丝游戏 - 测试开发部</li> </ul> <pre><code>公司名:莉莉丝游戏 部门名称:测试开发部 工作城市:上海 经验要求:3年以上 招聘岗位:前端开发工程师 职位描述 1、参与莉莉丝游戏内部测试平台的研发并独立负责前端开发工作 2、与设计师同事合作,对UI图进行高度还原和页面交互的实现 任职要求 1、大学本科或以上学历,3年以上工作经验 2、熟练运用JavaScript语言与HTML5、CSS3等技术 3、熟悉模块化,熟练运用主流的Web端JS库和开发框架,例如:Vue、Webpack、React等 4、有node开发经验优先 内推联系人(微信):Jaked_M 内推联系人(邮箱):liuchao@lilith.com </code></pre> <ul> <li>莉莉丝游戏 - 产品发行中心</li> </ul> <pre><code>公司名:莉莉丝游戏 部门名称:产品发行中心 工作城市:上海 经验要求:2年以上 招聘岗位:前端开发工程师 (P5+) 职位描述 1、负责游戏官网、H5活动页、小程序等相关网站的前端开发与维护工作; 2、与设计师、后端同学紧密合作,负责产出高质量的产品前端层; 3、协助中台系统开发。 任职要求 1、大学本科或以上学历,2年以上工作经验 2、精通HTML5、CSS3、JavaScript等Web开发技术,具备扎实的前端基础; 3、对页面的架构和布局、多端的适配兼容、网站性能的优化、模块/组件等有深入的理解; 4、至少熟悉并上线使用过一种主流的前端开发框架,比如:vue、react; 5、热爱前端、较强的责任感、良好的团队协作能力。 内推联系人(微信):Jaked_M </code></pre> </li> </ul> </content:encoded>
<category>信息源</category>
<comments>https://www.scarsu.com/monthly_1_2021_01/#post-comment/</comments>
</item>
<item>
<title>忍不住的新努力:胡适的人生哲学</title>
<link>https://www.scarsu.com/shizhi/</link>
<guid isPermaLink="true">https://www.scarsu.com/shizhi/</guid>
<description>保持质疑,保持兴趣,保持对“努力”的自信</description>
<pubDate>Sun, 31 Jan 2021 00:00:00 GMT</pubDate>
<content:encoded><h2>引言</h2> <p>《忍不住的新努力》是文化大师<strong>胡适</strong>的随笔集,收集了他34篇经典文章。</p> <p>以前对胡适的了解,仅限于历史书中“新文化运动的倡导者”这样一个标签。</p> <p>读完这本书,才感受到一个更有温度的胡适:</p> <p>他的文字透露着他温和、乐观、自由、沉稳的性情和态度,他留学美国师从哲学家,做过北大的教授,参与或创办过《新青年》等等刊物,获得过诺贝尔文学奖提名。</p> <p>但他的建树不仅限于文学:</p> <p>他宣扬个性解放、思想自由、向当时代的学生科普宇宙观、时间观,他追求科学、实践和真理。</p> <p>在我们这一代人中,<strong>鲁迅</strong>先生很受欢迎,他比胡适大10岁,也算是同时代的人,他的文字犀利激烈、令人振聋发聩。</p> <p>但是读完这本书后,我发现自己更喜欢胡适,温和沉稳但坚定、有态度、务实。</p> <p>因为是随笔集,所以内容很宽泛,读完之后,我总结了其中几个令我有收获的主题:</p> <ul> <li>生活的意义</li> <li>读书/问学的方法</li> </ul> <h2>生活的意义</h2> <p>生活的意义、人生的意义,是一个很广很抽象的哲学话题,不同的人有不同的理解。</p> <p>这本书中的有几点能反映作者的人生哲学:</p> <h3>有意思的生活</h3> <p>如何过有意思的生活:一个人做的事应该件件事回的出一个“为什么”,说得出为什么,就是有意思的生活</p> <h3>迷茫?青年困惑?不满社会?</h3> <p>不满于社会,又无能为力,无所作为,怎么办?这是很多青年人的困惑。</p> <p>作者的答案,就是“独善其身”,先努力学习充实自己,然后能兼善天下。</p> <p>大多数的失望,皆起于<strong>奢望&gt;能力</strong>。</p> <p>因此,无论是内因还是外因导致的苦闷,都要先从自己做起。</p> <h3>人生的意义到底是什么?</h3> <p>人生的意义是各人自己造出来的</p> <p>人生的意义在于自己对待人生的态度</p> <p>人生的意义在于自己赋予其的意义</p> <p>“高尚、清贵、污浊、有用、无用”......都在于你自己的追求</p> <h2>对学习的理解</h2> <h3>学习驱动力</h3> <p>我之前专门写过一篇学习方法,但是没讨论过为什么要学习。</p> <p>活学活用,学习的意义在于知道自己“为什么”学习,也就是找到最原始的学习驱动力:</p> <ol> <li>保持<strong>质疑</strong>的态度。问题是一切知识的来源。</li> <li>保持<strong>兴趣</strong>。找到令自己感兴趣的事物,兴趣是驱动力。</li> <li>保持对<strong>努力</strong>的信心。功不唐捐,努力就一定不会后悔。</li> </ol> <h3>求知的原则</h3> <ol> <li>怀疑。始终保持怀疑的态度去看待他人、自己的认知,不盲从,构建自己的知识体系。</li> <li>务实。切实的做,而不是一味的打口号,立flag。</li> <li>讲证据。依靠证据去质疑别人、质疑自己现有的认知,依靠证据支撑自己的认知。</li> <li>追求真理。宇宙无穷,真理无穷。以追求真理为求学态度,以追求真理为乐趣所在。</li> </ol> <h3>学习的目标</h3> <p>学习的目标可以分为两点,就是提升<strong>智、识</strong>:</p> <ul> <li>识:拥有知识</li> <li>智:拥有运用、发挥知识的能力</li> </ul> <h3>学习的方法</h3> <ul> <li>精</li> </ul> <ol> <li> <p>眼到,要理解字面意思</p> </li> <li> <p>口到,熟读</p> </li> <li> <p>心到,思考,横向比较思考,纵向追根究底,不断质疑“为什么”,和已有知识建立连接,融入自己的知识体系</p> </li> <li> <p>手到,抄录、提炼、总结心得,知识只有在经过自己的思考提炼,形成自己的“输出”后,才真正成为自己的知识</p> </li> </ol> <ul> <li>博</li> </ul> <p>构建金字塔型的知识体系,能广大、有专精</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/shizhi/#post-comment/</comments>
</item>
<item>
<title>GTD时间管理</title>
<link>https://www.scarsu.com/gtd/</link>
<guid isPermaLink="true">https://www.scarsu.com/gtd/</guid>
<description>Get Things Done,简单高效的应对信息洪流</description>
<pubDate>Wed, 27 Jan 2021 00:00:00 GMT</pubDate>
<content:encoded><h2>优点</h2> <ul> <li>更好的应对<strong>信息洪流</strong>,不被其打乱<strong>节奏</strong>,减少信息焦虑,减压</li> </ul> <p>遇见一个信息就处理一个,很容易打乱节奏,先收集再定期处理,类似计算机进程调度</p> <ul> <li>和任务管理协同执行,定期处理信息、更新任务,可以使任务更灵活稳定,成长<strong>效率</strong>更高</li> </ul> <p>例如每周7天,前6天专心执行当下的任务,不理会新的信息,只需要将其丢入inbox;</p> <p>第7天专心整理inbox,对任务做相应的调节(毕竟大脑是个单线程机器</p> <ul> <li>利于对信息抽丝剥茧,更高效的将<strong>信息</strong>筛选转化为自己的<strong>认知</strong></li> </ul> <p>举个例子🌰,你养了一个鱼塘,每天都去钓鱼,无论肥瘦只要上钩你都照单全收,最后鱼篓不一定挺得住不说,鱼的质量也不高; 但是你养上一周一个月,再去挑大鱼,又省力,质量又高 😉</p> <h2>简化的GTD流程</h2> <p><img src="/images/picgo/picgo20210127180326.png" alt="GTD流程图" /></p> <h3>1 执行 <strong>&amp; 收集期</strong></h3> <ul> <li>在各种设备、将各种来源的新信息,统一收集到inbox收集箱</li> <li>专心的执行当下的任务,不受信息困扰</li> </ul> <p>inbox的形式千千万,用的开心就好</p> <p>可以使用专业的app,例如:OmniFocus、Doit IM</p> <p>也可以使用更易得的工具,例如:只有自己的微信QQ群、邮箱</p> <p>我个人比较偏向QQ群,1是手机电脑qq常在线,2是比微信方便同步,3支持文字 图片 链接 文件,覆盖大部分场景</p> <h3>2 <strong>处理期</strong></h3> <ul> <li>定期整理:规定定期的时间,例如每周末/每月底,处理inbox</li> <li>理解转化:筛选有价值的信息,理解并记忆,输出自己的东西,归纳融合到自己的知识体系中</li> <li>计划:根据信息的更新,确定/调整下一周期的待办事项</li> </ul> <h2>更多资源</h2> <ul> <li><a>一年多的GTD和自我管理之路文章</a></li> </ul> <hr /> <p>顺嘴提一下,本篇文章也是作者通过GTD方法得来的:听微信群友提到GTD,就把关键词转到了inbox,月末的时候整理inbox,检索GTD信息,有了自己的理解,输出成了本篇文章。</p> <p>希望对你有帮助,成长愉快:)</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/gtd/#post-comment/</comments>
</item>
<item>
<title>关于我 | 2021年,给自己来点鸡血</title>
<link>https://www.scarsu.com/2021_hello/</link>
<guid isPermaLink="true">https://www.scarsu.com/2021_hello/</guid>
<description>及时止废</description>
<pubDate>Fri, 01 Jan 2021 00:00:00 GMT</pubDate>
<content:encoded><h2>为什么要趁年轻多学习&lt;a rel="nofollow" href="https://www.zhihu.com/question/354919014/answer/906152325"&gt;&lt;i class="fa fa-link"&gt;&lt;/i&gt;原文&lt;/a&gt;</h2> <blockquote> <p><strong>爆炸性压力才能带来爆炸性进步</strong></p> <p>每次我状态低迷的时候,我都会看看这个视频,视频18分钟,如果你懒得看,我简述一下:</p> <p>演讲者是许峰源先生,他出身一个非常贫穷的家庭,整个家庭,靠的是父亲踩着三轮车出去卖豆腐微薄的收入支撑着。</p> <p>这不是一个烂仔逆袭的故事,因为从小看到了生活艰苦的一面,许峰源一直很努力想考上台大法律系,因为成为律师才有高收入,才能改变家庭的现状。</p> <p>不幸的是,在他上大学的时候,父亲却查出了舌癌晚期,只剩一年左右的时间,为了让父亲在临终前看到自己的孩子成才,许峰源用了极短的时间通过了司法考试,成为了一名律师,让父亲看到了自己的律师证,才安然去世。</p> <p>祸不单行,很快许峰源的母亲也查出了患有肺腺癌,一种扩散很迅猛的癌症,为了让母亲有一个安享晚年的环境,许峰源在23岁的时候,毅然辞职创业,白天在律师事务所打拼,晚上做培训,最终让母亲住上了好房子,接受更好的治疗,然后平静地送走了母亲。</p> <p>前半生,许峰源先生为之奋斗的两个对象都走了,迷茫了一阵子之后,他依然没有放弃努力,而是选择了实现自我,成为了一名作家。</p> <p>再烂的牌也得打下去,这就是人生</p> </blockquote> <h2>成熟的一些标志</h2> <blockquote> <p>能克制欲望,不追求即时反馈,延迟享受。</p> <p>保持一致性,无论在人群中还是独处时,知行合一,不卑不亢,不矫揉造作,不哗众取宠。心中始终有底线、有原则、有追求。时刻反省自己:what在做什么、why为什么这样做、how如何做的更好</p> </blockquote> <p>—— 尼古拉斯·鱼</p> <h2>别让任何人打乱你的人生节奏</h2> <blockquote> <p>每个人的人生都不同</p> <p>"Not everything that counts can be counted,and not everything that's counted truly counts"</p> <p>"并不是每件算出来的事,都有意义;也不是每件有意义的事,都能被算出来" ——爱因斯坦</p> </blockquote> <p><a>@https://www.bilibili.com/video/BV1WW411F7Hx</a></p> <h2>如何追求快乐</h2> <blockquote> <p>有很多快乐是放纵的快乐,是降低了人性尊严的快乐,而越能体现人性尊严的快乐,越是一种高级的快乐。</p> <p>追求高级的快乐并不意味着放弃低级的快乐,但是如果你的眼目永远只关注地下,你永远不知道向上看有多么的快乐。</p> </blockquote> <p>——罗翔</p> <p><a>@https://www.bilibili.com/video/BV1AE411T7p7</a></p> <blockquote> <p>I don't need dollar bills to have fun</p> </blockquote> <p>——【Cheap Thrills】 Sia</p> <h2>关于坚持</h2> <blockquote> <p>坚持这两个字,远比你想象中的要难的多,但也比你想象中的有效的多。</p> <p>'You do make a difference!'</p> </blockquote> <p><a>@https://www.bilibili.com/video/BV1XJ411d7Xx</a></p> <blockquote> <p>两年,是很容易虚度过去的时长,也是足够改变自己的时长。</p> </blockquote> <p><a>@https://www.bilibili.com/video/BV1NE41197sr</a></p> <h2>就是不想努力怎么办</h2> <blockquote> <p>我就想做一个安于现状的人</p> <p>就想利用上班赚钱过好自己的小日子</p> <p>就想平凡的过完一生</p> <p>我就是不想拼命奋斗,拼命努力,拼命内卷</p> <p>不可以吗?</p> </blockquote> <p>当然可以,每个人的追求不同,淡泊名利,平静一生,真正能做到的话,是一种很高的人生境界。</p> <p>但是你做出这种决定,就要考虑其带来的结果</p> <blockquote> <p>你能做到真正的“淡泊名利”吗?</p> <p>当别人用光鲜亮丽的服装、车子、房子包装和提升自己的生活品质时,你能做到不羡慕吗</p> <p>当别人在马尔代夫浮潜、在阿尔卑斯滑雪、在土耳其滑翔、在富士山脚泡温泉喝清酒,你能做到不羡慕吗</p> <p>你身边的人生活品质都比你高得时候,你会不会后悔</p> <p>你的普通收入扣除房子首付、房贷、车子、奶粉钱之后你还足够安稳吗</p> <p>如果不买房,你可以做到一生租房,并容忍一生到老不断的搬家吗</p> <p>你的普通收入能让你匹配上你心仪的另一半吗</p> <p>你的现状能维持你一生的稳定平凡吗?你能对抗人生所有的风险吗</p> <p>你可以为自己的一生、父母后半生、孩子前半生的大大小小的健康问题买单吗</p> <p>如果你有了孩子,你作为爸爸/妈妈,能给孩子最好的教育吗</p> </blockquote> <p>如果你深刻的考虑了这些问题,得到的答案都是肯定的,那么安于现状,不拼命努力,也没什么不好</p> <p>每个人的人生都不同,人生的路也没有对错之分,只是路上的酸甜苦辣,你需要独自承担</p> <h2>比本文更硬核的鸡血</h2> <p><a>为什么要趁年轻多学习 - 知乎</a> <a>乔布斯 斯坦福大学演讲 - bilibili</a> <a>前端er要向qian看 - BOSS直聘</a> <a>别让任何人打乱你的人生节奏 - bilibili</a> <a>如何对抗平庸的生活 - 罗翔</a> <a>做人一定要坚持 - bilibili</a> <a>改变自己,只需要两年时间 - TED</a> <a>真正的自律 - Will Smith</a> <a>自信心不足? - bilibili</a></p> <hr /> <p>2021,自律 + 坚持,一路向前</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/2021_hello/#post-comment/</comments>
</item>
<item>
<title>动画demo解释 防抖、节流、rAF(CSS Tricks译文)</title>
<link>https://www.scarsu.com/debounce_raf/</link>
<guid isPermaLink="true">https://www.scarsu.com/debounce_raf/</guid>
<description>这三种技术用于优化事件处理函数,都很有用,且各有区别,互相补充。</description>
<pubDate>Wed, 30 Dec 2020 00:00:00 GMT</pubDate>
<content:encoded><p>原文链接:<a>防抖与节流的区别</a></p> <p>译者注:为了文章更易理解,对原文略有改动</p> <hr /> <p><strong>防抖</strong>与<strong>节流</strong>是两种相似(但不同)的技术,用于控制一定时间内函数的执行次数。</p> <p>当我们为<code>DOM</code>事件添加事件处理函数时,防抖或节流函数十分有用。为什么呢?因为我们并不能控制<code>DOM</code>事件被触发的频率,而防抖和节流在事件和事件处理函数之间,为我们添加了一个控制层。</p> <p>例如<code>scroll</code>事件,看这个demo:</p> <p>&lt;iframe height="265" style="width: 100%;" scrolling="no" title="Scroll events counter" src="https://codepen.io/dcorb/embed/PZOZgB?height=265&amp;theme-id=dark&amp;default-tab=css,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"&gt; See the Pen &lt;a href='https://codepen.io/dcorb/pen/PZOZgB'&gt;Scroll events counter&lt;/a&gt; by Corbacho (&lt;a href='https://codepen.io/dcorb'&gt;@dcorb&lt;/a&gt;) on &lt;a href='https://codepen.io'&gt;CodePen&lt;/a&gt;. &lt;/iframe&gt;</p> <p>当使用触控板,滚轮,或者滚动条滚动时,每秒钟可以轻易地触发30个事件。但是在我的测试中,在手机中缓慢滑动屏幕,每秒可以触发多达100个事件。你能确保你的事件处理函数在这种执行频率下正常工作吗?</p> <p>2011年,Twitter网站上出现了一个问题:当你在向下滚动Twitter feed时,网页变得缓慢且无响应。John Resig发表了<a>一篇关于这个问题的博客</a>,文章中解释了将消耗昂贵的函数直接附加到<code>scroll</code>事件上是多么的糟糕。</p> <p>John建议的解决方案(当时是五年前)是在<code>onScroll</code>事件之外,每隔250ms运行一个循环。这样处理程序就不会与事件耦合。通过这个简单的技术,我们可以避免破坏用户体验。</p> <p>现如今,有一些更复杂一些的处理事件的方法。让我给大家介绍一下<code>Debounce</code>、<code>Throttle</code>和<code>requestAnimationFrame</code>,以及相应的demo。</p> <h2><strong>Debounce 防抖</strong></h2> <p><code>Debounce</code> 防抖技术允许我们将多次连续的执行"分组"到一次单一的执行中。</p> <p><img src="https://i0.wp.com/css-tricks.com/wp-content/uploads/2016/04/debounce.png" alt="https://i0.wp.com/css-tricks.com/wp-content/uploads/2016/04/debounce.png" /></p> <p>想象一下这样的场景,你在电梯里,电梯门开始关闭,突然有另一个人想上电梯,电梯则不会运行,门会再次打开。然后又有一个人要上电梯,电梯再次延迟了它的运行(移动楼层),但优化了它的资源。</p> <p>可以在下面的示例中,尝试在顶部的“Trigger area”中点击或移动:</p> <p>&lt;iframe height="265" style="width: 100%;" scrolling="no" title="Debounce. Trailing" src="https://codepen.io/dcorb/embed/KVxGqN?height=265&amp;theme-id=dark&amp;default-tab=css,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"&gt; See the Pen &lt;a href='https://codepen.io/dcorb/pen/KVxGqN'&gt;Debounce. Trailing&lt;/a&gt; by Corbacho (&lt;a href='https://codepen.io/dcorb'&gt;@dcorb&lt;/a&gt;) on &lt;a href='https://codepen.io'&gt;CodePen&lt;/a&gt;. &lt;/iframe&gt;</p> <p>在上面的示例中可以看到,<code>debounced</code>事件是如何代替一组连续快速触发事件的。但如果事件的触发有很大的时间间隔,则不会发生<code>debouncing</code>。(可以这样理解,如果一直有人要上电梯,电梯就不会运行,直到等待一定时间内无人上电梯,电梯就会开始运行,在上述的示例中,这个<em>等待时间</em>被设定为四个刻度,也就是400ms)</p> <h2>l<strong>eading / immediate 参数</strong></h2> <p>在上述的示例中,<code>debouncing</code>事件需要<em>等待</em>,直到事件在一定时间内停止触发,才会执行函数。这种场景与等电梯的场景吻合。</p> <p>如果有另一种场景,需要在事件触发时,就立即执行函数,在快速连续触发的过程中,直到有一个暂停(满足<em>等待时间</em>),才会再次执行函数。</p> <p>这种需求,可以通过<code>leading</code>参数来实现:(在underscore.js中,这个参数的名称叫 <code>immediate</code> )</p> <p><img src="https://i2.wp.com/css-tricks.com/wp-content/uploads/2016/04/debounce-leading.png" alt="https://i2.wp.com/css-tricks.com/wp-content/uploads/2016/04/debounce-leading.png" /></p> <p>“<code>leading</code>”防抖的demo:</p> <p>&lt;iframe height="265" style="width: 100%;" scrolling="no" title="Debounce. Leading" src="https://codepen.io/dcorb/embed/GZWqNV?height=265&amp;theme-id=dark&amp;default-tab=css,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"&gt; See the Pen &lt;a href='https://codepen.io/dcorb/pen/GZWqNV'&gt;Debounce. Leading&lt;/a&gt; by Corbacho (&lt;a href='https://codepen.io/dcorb'&gt;@dcorb&lt;/a&gt;) on &lt;a href='https://codepen.io'&gt;CodePen&lt;/a&gt;. &lt;/iframe&gt;</p> <h2><strong>Debounce 实现</strong></h2> <p>我第一次看到debounce的Javascript实现是2009年,在<a>John Hann的这篇文章</a>中(他也是这个词的发明者)。</p> <p>不久之后,Ben Alman创建了<a>一个jQuery插件</a>(不再维护),一年之后,Jeremy Ashkenas将其<a>添加到了underscore.js</a>中。后来,它又被添加到Lodash中,成为undererscore的替代方案。</p> <p>这3种实现内部有些不同,但它们的接口都差不多。</p> <p>曾经有一段时间,在我于2013年发现<code>_.debounce</code>函数中的<a>一个bug</a>之后,underscore采用了Lodash的<code>debounce</code> / <code>throttle</code>实现。从那时起,两种实现都有了长足的发展。</p> <p>Lodash在其<code>_.debounce</code>和<code>_.throttle</code>函数中 <a>增加了</a> 更多的功能。原来的<code>immediate</code> 标志被替换为<code>leading</code> 和<code>trailing</code> 选项。你可以选择启用一个,或者两个。默认情况下,只有<code>trailing</code> 被启用。(leading可以理解为,在一组连续触发事件的起始,就调用函数;而trailing,则是在一组连续触发事件的末尾,经过<em>等待时间</em>后,执行函数)</p> <p>还有一个新的<code>maxWait</code>选项(目前只在Lodash中使用)在本文中没有涉及,但它可能非常有用。</p> <p>实际上,在Lodash的源码种,<code>throttle</code>节流函数是用通过<code>_.debounce</code>和<code>maxWait</code>选项来定义的。</p> <h2><strong>Debounce 实例</strong></h2> <h3><strong>Resize 实例</strong></h3> <p>当调整(桌面端)浏览器窗口的大小时,可能会触发许多的<code>resize</code>事件。</p> <p>可以在下面的demo中看到:</p> <p>&lt;iframe height="265" style="width: 100%;" scrolling="no" title="Debounce Resize Event Example" src="https://codepen.io/dcorb/embed/XXPjpd?height=265&amp;theme-id=dark&amp;default-tab=js,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"&gt; See the Pen &lt;a href='https://codepen.io/dcorb/pen/XXPjpd'&gt;Debounce Resize Event Example&lt;/a&gt; by Corbacho (&lt;a href='https://codepen.io/dcorb'&gt;@dcorb&lt;/a&gt;) on &lt;a href='https://codepen.io'&gt;CodePen&lt;/a&gt;. &lt;/iframe&gt;</p> <p>如你所见,上面的例子中,启用了默认的<code>trailing</code>选项,因为我们只关心用户停止resize后的最终值。</p> <h3>带有AJAX请求的自动填充输入框的输入事件</h3> <p>有一些场景例如等待用户停止输入后再验证其输入,反馈验证信息。这种场景下 <code>_.debounce</code>可以实现:只有当用户停止输入时才发送请求。</p> <p>此时,<code>leading</code> 标志没有意义,因为我们需要等待至最后的输入。</p> <p>&lt;iframe height="265" style="width: 100%;" scrolling="no" title="Debouncing keystrokes Example" src="https://codepen.io/dcorb/embed/mVGVOL?height=265&amp;theme-id=dark&amp;default-tab=js,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"&gt; See the Pen &lt;a href='https://codepen.io/dcorb/pen/mVGVOL'&gt;Debouncing keystrokes Example&lt;/a&gt; by Corbacho (&lt;a href='https://codepen.io/dcorb'&gt;@dcorb&lt;/a&gt;) on &lt;a href='https://codepen.io'&gt;CodePen&lt;/a&gt;. &lt;/iframe&gt;</p> <h2>如何使用<strong>debounce 和 throttle 以及 常见陷阱</strong></h2> <p>你可以自己写<code>debounce</code>/<code>throttle</code>函数,或者从一些随机的博客文章中复制它,但我的建议是直接使用 <code>underscore</code> 或 <code>Lodash</code>库。</p> <p>如果你只需要<code>_.debounce</code>和<code>_.throttle</code>函数,你可以使用Lodash自定义构建器来输出一个自定义的2KB minified库。下面时构建命令:</p> <pre><code>npm i -g lodash-cli lodash include = debounce, throttle </code></pre> <p>也就是说,大多数人都是通过webpack/browserify/rollup工具,使用模块化形式的<code>lodash/throttle</code>和<code>lodash/debounce</code>或<code>lodash.throttle</code>和<code>lodash.debounce</code>包。</p> <p>一个常见的陷阱是,多次调用<code>_.debounce</code> 函数:</p> <pre><code>// WRONG $(window).on('scroll', function() { _.debounce(doSomething, 300); }); // RIGHT $(window).on('scroll', _.debounce(doSomething, 200)); </code></pre> <p>在lodash 和 underscore.js中,为debounced饭都处理过的函数创建一个变量,可以调用私有方法 <code>debounced_version.cancel()</code></p> <pre><code>var debounced_version = _.debounce(doSomething, 200); $(window).on('scroll', debounced_version); // If you need it debounced_version.cancel(); </code></pre> <h2><strong>Throttle 节流</strong></h2> <p>通过使用 <code>_.throttle</code>, 可以限制函数在 X 毫秒内,最多只能执行一次。</p> <p>与<code>debouncing</code>的主要区别在于,节流保证了函数的定期执行,至少每X毫秒一次。</p> <h2><strong>Throttling 实例</strong></h2> <h3><strong>无限滚动</strong></h3> <p>举一个很常见的例子,用户正在向下滚动你的无限滚动页面。你需要检查用户离底部有多远。如果用户在底部附近,我们应该通过Ajax请求更多的内容,并将其添加到页面中。</p> <p>在这种场景下,<code>_.debounce</code>就不适用了,它只有在用户停止滚动时才会触发......而我们需要在用户到达底部之前开始获取内容。而<code>_.throttle</code>可以保证我们不断地检查用户离底部有多远。</p> <p>&lt;iframe height="265" style="width: 100%;" scrolling="no" title="Infinite scrolling throttled" src="https://codepen.io/dcorb/embed/eJLMxa?height=265&amp;theme-id=dark&amp;default-tab=js,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"&gt; See the Pen &lt;a href='https://codepen.io/dcorb/pen/eJLMxa'&gt;Infinite scrolling throttled&lt;/a&gt; by Corbacho (&lt;a href='https://codepen.io/dcorb'&gt;@dcorb&lt;/a&gt;) on &lt;a href='https://codepen.io'&gt;CodePen&lt;/a&gt;. &lt;/iframe&gt;</p> <h2><strong>requestAnimationFrame (rAF)</strong></h2> <p><code>requestAnimationFrame</code> 是限制函数执行速度的另一种方式。</p> <p>它相当于<code>_.throttle(dosomething, 16)</code>,但保真度要高很多,因为它是浏览器原生的API,拥有更好的准确性。</p> <p>可以考虑使用<code>rAF</code> API,作为节流函数的替代品,以下是它的优缺点:</p> <h3>优点:</h3> <ul> <li>目标为60fps(即每秒60帧),但是由浏览器内部机制决定如何安排渲染的最佳时间。</li> <li>更简单和更标准的API,未来不会改变,更好维护。</li> </ul> <h3>缺点:</h3> <ul> <li>rAFs的启用/取消是我们的责任,不像<code>debounce</code>或<code>throttle</code>,是内部管理的。</li> <li>如果浏览器标签页未激活,它就不会被执行。(对于滚动、鼠标或键盘事件来说,这并不重要)。</li> <li>虽然所有的现代浏览器都提供了RAF,但在IE9、Opera Mini和旧的Android中仍然不支持。仍然需要<a>polyfill</a> 。</li> </ul> <p>根据经验来讲,如果我的JavaScript函数是 "绘画 ",或者会直接变更动画相关属性,我会使用<code>requestAnimationFrame</code>,以及在一切涉及重新计算元素位置的地方使用它。</p> <p>如果要进行Ajax请求,或者决定是否添加/删除一个class(可能会触发CSS动画),我会考虑<code>_.debounce</code>或<code>_.throttle</code>,因为可以设置更低的执行速率(例如200ms,而不是16ms)。</p> <h3><strong>rAF 实例</strong></h3> <p>这个demo灵感来自于 <a>Paul Lewis的文章</a>, 文章做他详细解释了demo中的原理和逻辑。</p> <p>我把<code>rAF</code>和  <code>16ms 的_.throttle</code> 放在一起进行了比较,结果是它们的性能相似。但是在更复杂的情况下,rAF可能性能会更高。</p> <p>&lt;iframe height="265" style="width: 100%;" scrolling="no" title="Scroll comparison requestAnimationFrame vs throttle" src="https://codepen.io/dcorb/embed/pgOKKw?height=265&amp;theme-id=dark&amp;default-tab=js,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"&gt; See the Pen &lt;a href='https://codepen.io/dcorb/pen/pgOKKw'&gt;Scroll comparison requestAnimationFrame vs throttle&lt;/a&gt; by Corbacho (&lt;a href='https://codepen.io/dcorb'&gt;@dcorb&lt;/a&gt;) on &lt;a href='https://codepen.io'&gt;CodePen&lt;/a&gt;. &lt;/iframe&gt;</p> <p>我在headroom.js库里见到过<code>rAF</code>技术更高级的实例,其中的 <a>逻辑被解耦</a> 并且被包装在了对象中。</p> <h2>总结</h2> <p><code>debounce</code>防抖, <code>throttle</code> 节流和 <code>requestAnimationFrame</code> 可以用来优化事件处理函数,三种技术都很有用,且各有区别,互相补充:</p> <ul> <li><strong>debounce防抖:</strong> 将快速连续的多次事件触发分组,归为一次执行。</li> <li><strong>throttle节流:</strong> 确保每隔X 毫秒就有一次稳定的执行,例如每200ms检查一次用户滚动位置以触发一个CSS动画。</li> <li><strong>requestAnimationFrame:</strong> 节流函数的16ms替代选择。更适用于在页面上重新计算/渲染元素的函数,能得到更平滑的动画。但是注意: IE9 不支持。</li> </ul> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/debounce_raf/#post-comment/</comments>
</item>
<item>
<title>当我谈跑步时我谈些什么:痛苦难以避免,而磨难可以选择</title>
<link>https://www.scarsu.com/running_life/</link>
<guid isPermaLink="true">https://www.scarsu.com/running_life/</guid>
<description>村上春树的跑步与人生哲理</description>
<pubDate>Mon, 30 Nov 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>引言</h2> <p>即使我是一个不怎么爱看文艺类书籍的理工科出身程序猿,也听过<strong>村上春树</strong>的大名。</p> <p>他是日本著名的作家、小说家,代表作有《挪威的森林》、《1Q84》。</p> <p>我的书单上从没有出现过<strong>村上春树</strong>的书,直到有一天逛书店,看到了这本《当我谈跑步时我谈些什么》。</p> <p>那段时间刚好开始晨跑,每天早上起床5公里,大约坚持了一个多月,十分倦怠,所以希望看看这本书,<strong>为意志力充充电</strong>。</p> <h2>作者的跑步人生</h2> <p>作者年近30时,才转行做一名职业作家。</p> <p>开始专职于写作之后,他发现自己每天需要高强度的脑力工作,一坐就是一整天,一天下来要吸掉60多支烟。</p> <p>要维持体力,又要将体重保持得“恰到好处”,村上春树选择跑步,作为解决健康问题的方法,并发展成了终生爱好。</p> <p>每天一小时的长跑,几乎每年都参加一场马拉松,即使没拿到过名次和奖励,但依然跑了30年。</p> <blockquote> <p>跑步时,人最残酷的对手是自己,其他选手都不是真正的敌人;</p> <p>真正的敌人就是你自己,就是你用智慧和勇气掌控自己情绪的能力。</p> </blockquote> <blockquote> <p>戴好流线型头盔,架上体育专用太阳眼镜</p> <p>水壶里灌满了水,设定好计时器</p> <p>一意猛骑</p> </blockquote> <p><img src="/images/picgo/picgo20210125155333.png" alt="" /></p> <p>书中作者对跑步、以及参加铁人三项的细微感触、日日坚持跑步的所见所闻、所惑所思,十分打动人心。</p> <p>很遗憾的是这本书还没看完的时候,我由于膝盖疼痛没能继续坚持晨跑。</p> <p>但是我依然看完了这本书,因为这本书不仅仅讲了作者的跑步历程和意义。</p> <p>令我收获良多的,还有贯穿全书的<strong>人生哲学</strong>。</p> <h2>坚持与磨砺</h2> <p><img src="/images/picgo/picgo20210201093452.png" alt="目下3米,便是我当下的世界" /></p> <blockquote> <p>无论奔跑速度降了多少,我都不走,这是原则,违背了自己顶下的原则,哪怕只有一次,以后就将违背更多原则</p> </blockquote> <p><img src="/images/picgo/picgo20210125114249.png" alt="" /></p> <p>这是<strong>村上春树</strong>诠释的马拉松精神,更是一种对待人生的态度。</p> <p>无论多么微小的举动,长久坚持,就一定会有其影响力。</p> <blockquote> <p>痛苦难以避免,而磨难可以选择</p> <p>Pain is inevitable, Suffering is optional</p> </blockquote> <p>坚持跑步的理由不过一丝半点,中断跑步的理由却足够装满一辆大型载重卡车。我们只能将那“一丝半点的理由”一个个慎之又慎地不断打磨。见缝插针,得空儿就孜孜不倦地打磨它们。</p> <blockquote> <p>刻意经历这痛苦</p> <p>起码曾经努力的事实会留存下来</p> <p>即使这是虚妄的没结果的行为,也不是愚蠢的行为</p> </blockquote> <p><strong>曾经努力</strong>就不会给日后的自己,留下后悔的机会。</p> <h2>输赢与自卑</h2> <blockquote> <p>在长跑中,如果说有什么必须战胜的对手,那就是过去的自己</p> </blockquote> <blockquote> <p>欧内斯特•海明威好像也说过类似的话:持之以恒,不乱节奏,对于长期作业实在至为重要。</p> <p>一旦节奏得以设定,其余的问题便可以迎刃而解。</p> <p>诚然,我并非毫无争强好胜之心。不过不知何故,跟别人一决雌雄,我自小就不甚在乎胜负成败。这一性格在长大成人后也大致未变。</p> <p>无论何事,赢了别人也罢输给别人也罢,都不太计较,倒是更为关心能否达到为自己设定的标准。</p> </blockquote> <p><strong>村上春树</strong>参加多次马拉松也未获得过名次或奖励,诺奖也陪跑多年,但是不曾气馁,仍然全意追求自己想要的人生,掌握并坚持自己的节奏。</p> <blockquote> <p>世人皆有其唯一性,必定与他人相异,不必与人比较</p> <p>年少时,无力客观的把握自己的定位</p> <p>极易因微不足道的事而沾沾自喜</p> <p>也极易产生自卑感。</p> <p>随着年龄的增长,经历了形形色色的失误</p> <p>该拾起来的拾起来,该抛弃的抛弃掉</p> <p>然后才能形成这样的认知:</p> <p>缺点如果以一去数,必将没完没了</p> <p>可是优点肯定也有</p> <p>我们只能凭借手头现有的东西去面对世界</p> </blockquote> <p>这是他对<strong>自卑</strong>的态度,语言真切,结论也很直观:</p> <p><strong>自卑、与他人比较是虚妄的,只需要利用好现有的条件,做最好的自己。</strong></p> <h2>保持自己的节奏</h2> <blockquote> <p>我是那种喜欢独处的人。更确切地说,我是那种不觉得孤独是痛苦的人。我发现每天花一两个小时独自跑步,不跟任何人说话,还有四五个小时独自坐在办公桌前,既不困难,也不无聊。我从小就有这种倾向,当时如果有选择的话,我更喜欢自己看书或专心听音乐,而不是和别人在一起。我总是能想出自己要做的事情。</p> </blockquote> <blockquote> <p>希望一人独处的念头,始终不变地存于心中。</p> <p>所以一天跑一小时,来确保只属于自己的沉默的时间,</p> <p>对我的精神健康来说,成了具有重要意义的功课。</p> <p>至少在跑步时不需要和任何人交流,不必听任何人说话,只需眺望周围的风光,凝视自己即可。</p> <p>这是任何东西都无法替代的宝贵时刻。</p> </blockquote> <p>从小我的性格,就十分依赖别人,和朋友玩就久久不想分开,不喜欢一个人睡觉,没有人陪伴就会觉得孤独。</p> <p>这种抵触一个人独处的情绪,直到成年才慢慢消除。</p> <p>因为越长大,才越能体味到作者对“独处”的感触。</p> <ul> <li>长大了才知道,人生的路,出生到死亡,没有人能真正陪伴你全程</li> <li>长大了才知道,热闹的人群给你带来的也许是温暖,但不是成长</li> <li>长大了才知道,孤独其实并不是坏事</li> <li>长大了才知道,这世界上没有任何人能真正的与你<strong>感同身受</strong></li> <li>长大了才知道,你所有的行为都要自己承担后果,你要为自己兜底</li> </ul> <p>而当我学会独处,并开始享受独处,我才意识到自己真正的成熟了。</p> <blockquote> <p>不管全世界所有人怎么说,我都认为自己的感受才是正确的。</p> <p>无论别人怎么看,我绝不打乱自己的节奏。</p> <p>喜欢的事自然可以坚持,不喜欢怎么也长久不了。</p> </blockquote> <p>人在失去自我方面浪费的时间越多,形成自己的特点的机会越少,大多数人最后都活成了麻雀群里的一个点。</p> <p>学会独处,更多的发现和探索自己,才能找到真正喜欢的事情,才能独一无二的特别的你。</p> <h2>结语</h2> <p>无论少年还是暮年,</p> <p>希望你心中始终有一面鲜明的旗帜,指示着你自己的坚持;</p> <p>希望你心中始终有一扇嘀嗒的时钟,稳定着你自己的节奏。</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/running_life/#post-comment/</comments>
</item>
<item>
<title>自卑与超越:一本对自我的答疑书</title>
<link>https://www.scarsu.com/meaning_of_life/</link>
<guid isPermaLink="true">https://www.scarsu.com/meaning_of_life/</guid>
<description>我为什么是我</description>
<pubDate>Fri, 30 Oct 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>书与作者简介</h2> <ul> <li>作者:[奥地利]阿尔弗雷德·阿德勒 <ul> <li>医学博士</li> <li>从医:眼科、全科、精神科</li> <li>探索人格、心理与身体,得到了当时心理学大师弗洛伊德的赏识,加入了弗的心理分析学会</li> <li>与弗在产生分歧,退出了弗的心理分析学会,转而自立门派,研究“个体心理学”</li> <li>因“个体心理学”研究、一系列著作出版,而声名远播</li> </ul> </li> <li>书:心理学必读经典书籍《What Life Should Mean To You》 <ul> <li>从个体心理学的观点出发,阐明人生道路和人生意义</li> <li>是一本通俗性读物,但包含着极深的哲理,和丰富的学术创见</li> <li>全书涉及了人生的方方面面:人活着的意义、心灵&amp;肉体关系、自卑感&amp;优越感、早起记忆和梦的意义、原生家庭和学校对人的影响、青春期、犯罪、职业、人&amp;同伴&amp;社交、爱情&amp;婚姻......</li> <li>中文书名的由来:这本书着重讲了自卑感的形成,自卑感对人的影响,如何超越自卑感,如何将自卑感转为对优越地位的追求以取得成就</li> </ul> </li> </ul> <h2>带着问题看文章</h2> <p>很对人从孩童时期、到青春期、到中年,都在不断地苦苦思索人生的意义。</p> <p>很对人活一世,即使到临死前,也没能够了解自我。</p> <p>不知道这一生在追寻什么,最终得到了什么。</p> <p>因此,可以把这本书当作一本对自我的答疑书来看。</p> <p>当对人生的方方面面产生困惑时,可以翻阅本书,跟着阿德勒的个体心理学,探寻自己内心的最深处,摸索答案。</p> <hr /> <h2>生活的意义到底是什么</h2> <p>职业、交际和两性</p> <blockquote> <p>1、我与地球:我们生活在地球上,依靠地球所提供的资源生存,除此之外别无选择。</p> </blockquote> <p>2、我与他人/种族:任何人都是人类族系的一员,每个人必然要与他人发生关系。</p> <p>3、我和她:这一问题涉及爱情和婚姻。人类有两种性别,男和女。任何人的一生都无法避开爱情和婚姻这一问题。</p> <blockquote> <p>1、在地球的有限资源限制下,为了永存,我们应该如何工作?</p> </blockquote> <p>2、为了与人合作,共同发展,我们应该获得怎样的定位和身份?</p> <p>3、面对“人有男女”和“人类延续依赖于爱与婚姻”这一事实,我们应该如何调整自我?</p> <p>所以,个体心理学认为人类的所有问题都可以归于职业、交际和两性这三个问题。</p> <p>比如,一个人完全没有爱情,生活遭遇挫折,在工作上也表现得平平庸庸,并且不善交际,朋友很少,他觉得与同伴交往是非常痛苦的事情。那么生活对于他来说就是痛苦而危险的事。</p> <p>而如果一个人交友广泛,人脉很广,事业有成,拥有甜蜜的爱情和幸福的生活。那么我们可以断定,他的生活是丰富的,是充满创造性的。</p> <p>所以,作者认为,生命的意义在于乐于关注他人,渴望成为社会大家庭一员,梦想着为人类和社会贡献自己的力量。</p> <p>著名国学大师季羡林在望九之年写过一篇文章,叫《人生的意义与价值》,在文章的最后,他是这么说的:</p> <p>如果人生真有意义与价值的话,其意义与价值就在于对人类发展的承上启下,承前启后的责任感。 古往今来,但凡人们认为具有“生命意义”的人或事,都离不开对他人和社会的贡献。那些赋予人生以个人意义的人,他们的人生就此走过,没有留下一丝痕迹。</p> <p>因此作者说:</p> <p>个人意义没有任何价值,真正的生命意义存在于个体与他人的交互作用中。每个人都希望自己变得重要、有价值,但如若不能搞懂个人的成就建立在对他人做出贡献的基础之上,那就太容易走上歧途。 至此我们就能理解前面的话了,在努力追求优越感的过程中,只有那些为了他人的利益而前进的人和为了社会的发展而奋斗的人,才是能够超越生活,从而顺利获得优越感的人。</p> <p>以他人利益为重,那我们自己的利益怎么办?要回答这个问题,我们需要理解个体与社会的关系。</p> <h2>早期记忆/童年 对一个人的影响有多大</h2> <blockquote> <p>一个人的价值观,世界观都和经历有关,所有的经历造就了现在的你,你的所有需求,你的所有期望,都是曾经你经历的没有得到,所以你现在渴望得到。 没有了解一个人的童年,是不会了解他的现在的。</p> </blockquote> <h2>自卑感&amp;优越感</h2> <blockquote> <p>我们每个人都有不同程度的自卑感,因为我们都想让自己更优秀,让自己过更好的生活。自卑感的存在并不是一件坏事,因为它激励了人不断追求卓越,克服自身的障碍,在有限的生命空间内发挥出最大的价值。</p> </blockquote> <h2>家庭</h2> <blockquote> <p>婚姻是一种合作关系,所以两个人都不应该试图驾驭对方。</p> </blockquote> <p>自卑情结</p> <h2>反思</h2> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/meaning_of_life/#post-comment/</comments>
</item>
<item>
<title>CSS变量</title>
<link>https://www.scarsu.com/css_variable/</link>
<guid isPermaLink="true">https://www.scarsu.com/css_variable/</guid>
<description>原生js控制css变量、Vue3响应式css变量</description>
<pubDate>Fri, 25 Sep 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>资源</h2> <ul> <li><a>文档</a></li> <li><a>在线demo</a></li> <li><a>vue3 css变量文档</a></li> </ul> <h3>是什么</h3> <p>CSS自定义属性、CSS变量、级联变量,可以文档中重复使用的样式变量</p> <h2>声明</h2> <ul> <li> <p>声明一个自定义属性,属性名需要以两个减号(--)开始</p> </li> <li> <p>大小写敏感</p> </li> <li> <p>属性值则可以是任何有效的CSS值。</p> </li> <li> <p>和其他属性一样,自定义属性也是写在<strong>规则集</strong>之内的</p> </li> <li> <p>例子🌰:</p> <pre><code>element { --main-bg-color: brown; } </code></pre> </li> <li> <p><strong>规则集</strong>所指定的选择器 定义了自定义属性的可见<strong>作用域</strong></p> </li> <li> <p>自定义属性具有<strong>继承性</strong>,受级联的约束,从其父级继承其值。</p> </li> <li> <p><strong>最佳实践</strong>💁‍♀️:根伪类<code>:root</code>,相当于全局变量</p> <pre><code>:root { --main-bg-color: brown; } </code></pre> </li> </ul> <h2>使用变量</h2> <p><code>color: var(--main-color);</code></p> <h2>备用值 / 默认值</h2> <pre><code>// 正确做法 var(--my-var, red) var(--my-var, var(--my-background, pink)) // 错误做法 var(--my-var, --my-background, pink) </code></pre> <h2>js更新变量</h2> <pre><code>// 获取一个 Dom 节点上的 CSS 变量 element.style.getPropertyValue("--my-var"); // 获取任意 Dom 节点上的 CSS 变量 getComputedStyle(element).getPropertyValue("--my-var"); // 修改一个 Dom 节点上的 CSS 变量 element.style.setProperty("--my-var", newValue); </code></pre> <h2>Vue3 响应式css变量</h2> <pre><code>&lt;template&gt; &lt;div class="text"&gt;hello&lt;/div&gt; &lt;/template&gt; &lt;script&gt; export default { data() { return { color: 'red' } } } &lt;/script&gt; &lt;style vars="{ color }"&gt; .text { color: var(--color); } &lt;/style&gt; </code></pre> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/css_variable/#post-comment/</comments>
</item>
<item>
<title>【学会如何学习】成为更好的终身学习者</title>
<link>https://www.scarsu.com/learning_how_to_learn/</link>
<guid isPermaLink="true">https://www.scarsu.com/learning_how_to_learn/</guid>
<description>通过精神学、心理学原理,探寻学习的本质,提高学习效率,降低学习挫败感,成为更好的终身学习者</description>
<pubDate>Tue, 15 Sep 2020 00:00:00 GMT</pubDate>
<content:encoded><ul> <li>6000字长文预警,建议拉到底部,先看总结❤</li> <li>原创不易,欢迎<strong>点赞,在看,转发</strong>支持</li> </ul> <p><img src="/images/picgo/picgo20200921190445.png" alt="文章大纲" /></p> <hr /> <p>酥鱼我从小学到大学毕业,当了十六年的学生,工作又选择了程序员这个发展日新月异、需要持续学习的行业。</p> <p>如何提升学习效率,减少学习带来的挫折感和痛苦,一直是我所苦苦追寻而不得的。</p> <p>每每看到别人能用更短的时间,学到更多、更深刻、更系统的知识,我都留下了羡慕的泪水。</p> <p>因此我也曾向很多学霸、前辈们请教学习的法门,多多少少能有些学习方法上的收获,但这些方法都因人而异,起不到决定性的作用,始终觉得自己对于<strong>如何学习</strong>这个问题,理不出一个最完美的、有逻辑性的答案。</p> <p>直到我接触到了Coursera上的一门免费课程<a>Learning how to Learn</a>,这门课从神经学、生物学的角度,揭示了大脑认知的底层原理,和学习的本质,从而提供了一系列提升学习效率、减轻学习痛苦与挫败感的技巧。</p> <p>这门课视频内容大概10小时,值得花时间去上,但是如果你想节省时间,可以直接看看本文。</p> <p>如果你刚好学过这门课,可以跟着本文一起<strong>复盘</strong>一遍(学过的你一定知道复盘的重要性。</p> <p>另外有一本书<a>《学习之道》</a>,是这门课的书面材料,书的作者也是课程主讲老师,内容和视频是相对应的,因此也可以直接啃书。</p> <p>废话讲了一堆,下面跟着我一起开始正文吧~</p> <p><img src="/images/picgo/picgo20200915181959.gif" alt="" /></p> <hr /> <h2>人脑的两种思维模式</h2> <p>提到学习,离不开大脑的思维,有了思维才能去理解、才能拥有记忆。</p> <p>人的大脑一共有两种思维模式:</p> <table> <thead> <tr> <th>Focused Mode &lt;br /&gt;专注模式</th> <th>Diffuse Mode&lt;br /&gt; 发散模式</th> </tr> </thead> <tbody> <tr> <td>集中精力解决单一问题</td> <td>放松的思考模式</td> </tr> <tr> <td>熟练掌握的内容</td> <td>新事物学习,获取灵感</td> </tr> <tr> <td>顺序思考</td> <td>整体思考</td> </tr> <tr> <td>熟练掌握的内容</td> <td>新事物学习,获取灵感</td> </tr> </tbody> </table> <p>以弹珠游戏类比大脑的思维:</p> <ul> <li><strong>专注模式</strong>下,大脑遇到已知问题,能快速定位到已掌握的知识,利用训练好的知识回路,专一且迅速的解决问题(弹珠定向发射),此时思维的粒度很细(弹珠盘上的桩很密集),当遇到新问题时,由于过于关注细节,大脑无法进行更广的思维跳跃,无法将更多的知识回路连接(由于桩很密集,弹珠弹射区域很小)。</li> </ul> <p><img src="/images/picgo/picgo20200915094332.png" alt="专注模式" /></p> <ul> <li><strong>发散模式</strong>下,大脑处于放松状态,不考虑细节(弹珠盘上的桩很少),思维灵活跳跃,能从整体层面解决问题,更有助于发挥创造力(弹珠随意发射,在较大的区域弹射)。</li> </ul> <p><img src="/images/picgo/picgo20200915094340.png" alt="发散模式" /></p> <p>这两种思维区别很大,而且不能同时应用,所以我们需要将两种思维模式<code>结合使用,灵活转换</code>。</p> <p>举个例子🌰:</p> <p>Salvador Dali,20世纪著名超现实主义画家。他有一个有趣的方法,来帮他创造富有创造性的作品:<em>坐在椅子上,放松大脑,模糊的思考着之前专注的事情,手上拿着一串钥匙晃悠,当他睡着时,钥匙会掉落在地上,把他吵醒,这样他就能把脑子里刚刚<strong>发散模式</strong>下的联想和点子集中起来,带着它们回到<strong>专注模式</strong>去记录灵感并进行创作。</em></p> <p><strong>专注模式更适合解决细节问题,发散模式更适合寻找灵感和整体解决方案</strong>。</p> <h2>如何拥有更牢固的记忆</h2> <p>学习,其实就是掌握知识的过程,这个过程主要就是两步,<strong>理解 + 记忆</strong>。</p> <p>理解,可以通过很多方式,比如听老师讲课,看书,看视频,看资料,请教前辈等等,方式很多,这一步一般不需要很多时间。</p> <p>先来谈谈记忆,这门课把人类记忆划分为两种:</p> <table> <thead> <tr> <th>Working Memory&lt;br /&gt; 工作记忆</th> <th>Long-term Memory &lt;br /&gt;长期记忆</th> </tr> </thead> <tbody> <tr> <td>短期记忆</td> <td>长期记忆</td> </tr> <tr> <td>负责处理即时的有意识的想法&lt;br /&gt;例如专注学习新知识时&lt;br /&gt;如果不加以复习和记忆,会被其他信息挤掉</td> <td>负责存储已掌握的知识&lt;br /&gt;需要时常复习,才能提升未来能记忆到的几率</td> </tr> <tr> <td>类似于计算机内存,或者一块小黑板</td> <td>类似于硬盘,或者一个存储仓库</td> </tr> <tr> <td>例如你尝试在脑海中用多个概念串联起来,&lt;br /&gt;去解决一个当下遇到的问题</td> <td>例如你回忆99乘法表去计算9×9的结果</td> </tr> <tr> <td>存储于大脑的前额皮质,与大脑的其他部位可以联系</td> <td>占据大脑大片区域</td> </tr> <tr> <td>容量较小,因人而异,大约可以存储四个组块的信息</td> <td>容量巨大</td> </tr> <tr> <td>处于大脑的前额叶皮质区域,与大脑的其他区域可以连接</td> <td>不同类别的长期记忆,处于大脑的不同位置</td> </tr> <tr> <td><img src="/images/picgo/picgo20200915190943.png" alt="image-20200915190943225" /></td> <td><img src="/images/picgo/picgo20200915191016.png" alt="image-20200915191016075" /></td> </tr> </tbody> </table> <p><strong>学习的最终目标,就是将已经理解的知识从工作记忆,转化到长期记忆</strong>。而这个过程,需要的是<strong>练习</strong>。</p> <p>那么怎样<code>在相同练习次数下,获取更牢固的记忆</code>呢?</p> <ul> <li><strong>间隔重复</strong>:刻意的进行反复练习,每次练习中间要有间隔,不断增大两次练习之间的时间间隔。(同样次数的练习,分散在几天中做的效果 比集中在一个晚上做更好)</li> <li>利用比喻、类比、想象,将知识 和 人类<strong>感官联系</strong>,如视觉、听觉、触觉、情感,更有利于记忆。例如:把想要记住的东西,转换成一些难忘的画面、大声朗读单词文章等等</li> <li><strong>充足睡眠+睡前复盘</strong>:睡眠对于学习至关重要,入睡时脑细胞会缩小 使得专注学习时产生的代谢毒物可以被清除,且大脑会在睡眠期间自动清理不重要的记忆,并在潜意识中排演睡前学习的内容。因此睡前花几分钟回顾学习内容,有助于记忆。</li> <li><strong>冷静</strong>。在你感到紧张/生气/害怕时,这些情绪会占用你的工作记忆。因此开始专注前,要排除各种情绪的干扰。</li> </ul> <h2>学习的本质:Chunk 组块</h2> <p><strong>Chunk 组块</strong>:是指大脑可以轻松使用的小而紧凑的<strong>信息碎片</strong>(可以理解成多个神经元组成的回路或思维回路</p> <p><strong>Chunking 组块化</strong>:根据意义和逻辑将信息碎片拼接起来,得到Chunk的思维过程</p> <p>概念有点抽象,举一个<code>拼图</code>的例子🌰:</p> <p>一堆拼图碎片是凌乱无意义的,每块拼图碎片的棱角和图像就是它和其他碎片相互连接的信息和逻辑,理清了所有碎片的逻辑关联,拼成整体后,才能得到一个具有清晰逻辑的整体图片</p> <p><img src="/images/picgo/picgo20200916130211.png" alt="image-20200916130210985" /></p> <p>再以小星星⭐举例:</p> <p>S,T,A,R四个字母单独看,都是单纯的无意义字母,组合成<code>Star</code>后,就是一个有意义的词,你就能联想到五角星的图片形象,也能联想到星空,这就是一个<strong>chunk</strong>的例子,这个<strong>chunk</strong>虽然是一个抽象的概念,但是在你的大脑中,真实存在着相互连接的神经元,其中包含了对四个字母、五角星和星空形象的记忆。</p> <p>最后一个栗子🌰:</p> <p>我们人类出生后最初的学习,就是认识妈妈,一个母亲不断的在孩子面前说“妈妈”这个词,孩子就能学会叫妈妈,并且能把“妈妈”这个词的发音,和母亲的笑容、母亲的形象联系起来,从而不会把别人错认成妈妈。这个学习过程会形成下图👇这样的神经回路,也就是<strong>Chunk</strong>。</p> <p><img src="/images/picgo/picgo20200916131723.png" alt="" /></p> <p>为什么要用这么多内容介绍<strong>Chunk</strong>呢?</p> <p>因为,<strong>专注学习、重复训练的过程,就是建立chunk的过程</strong>,当chunk建立后,神经回路里的任何一点,都能引导你串联整个记忆回路。</p> <p>人类复杂的神经活动、记忆的存储、牛顿从“苹果落地”到“万有引力”,都建立了并依赖于大脑中众多的<strong>Chunks</strong>。</p> <p><strong>Chunk</strong>就像是人脑中<strong>最小可利用的思维回路</strong>,解决复杂问题、掌握复杂知识时,需要利用到众多的相互关联的Chunk,最终形成了你整个大脑的思维网络。</p> <p><img src="/images/picgo/picgo20200918164835.png" alt="" /></p> <p>再回到之前讲的学习的本质,就是<strong>理解+记忆</strong>,记忆这一步的技巧前面已经讲了,理解这一步要做的,就是把现有的外界的知识,转化成自己的知识,在大脑中形成Chunk,为你所用。</p> <p>那么<code>怎样建立牢固可靠的Chunk</code>呢?</p> <p><strong>1. 开启专注模式</strong></p> <p>集中注意力,切断一切外界干扰,不能让有限的工作记忆被其他事情占用。</p> <p>例如呆在一个安静的环境,打开手机电脑的勿扰模式,将手边无关的东西都拿开,打开番茄钟计时,然后开始专注。</p> <p><strong>2. 自下而上学习 - chunking</strong></p> <p>先从<strong>基本概念</strong>开始理解,在理解的前提下,将新知识与已掌握的知识相关联,建立chunk。</p> <p>理解后不断的用<strong>自测</strong>的方式,检验chunk是否真正形成。自测的形式很多,可以合上书回忆所有内容,也可以practice(实践),脱离书本,自己利用Chunk去实际独立操作、独立解决问题,通过这个过程知道<strong>怎么使用chunk</strong></p> <p><img src="/images/picgo/picgo20200916162710.png" alt="image-20200916162217085" /></p> <p><strong>3. 自上而下学习 - context</strong></p> <p>gaining context,获取背景知识,从更广的更高的角度去理解chunk如何融入整体的知识架构,通过这一点去了解<strong>何时何处使用chunk</strong>,掌握了how to之后,思考why to ,when to,从而在遇到问题的各种场景中信手拈来。</p> <p>例如🌰看一本书之前,先看看图片、章节大纲,看完一本书后,画流程图、思维导图,就能更清楚整体的结构,有利于chunk的建立和巩固。</p> <p><img src="/images/picgo/picgo20200916162704.png" alt="" /></p> <h2>最高效的学习方法:间隔重复</h2> <p>Science杂志曾发布一篇论文,让一群学生,使用不同的方法,在相同时间内,学习一篇科技文本,最终的结论是这样的:相较于 重复阅读、边学边画思维导图等方式,通过<strong>recall</strong>方式学习的学生,学的最多、也最牢固。</p> <p>这里的<strong>recall</strong>,我把它总结成<code>间隔重复练习法</code>,也就是不断重复下面的3个步骤:</p> <ul> <li>学习</li> <li>脱离书本回忆(<strong>自测</strong>)</li> <li>留出时间间隔(随着练习的次数增多,逐渐增大时间间隔)</li> </ul> <p>看完这篇文章,你可以忘记所有内容,但是一定要记得这个 <em>经过实验验证有效的</em> 学习方法。</p> <h2>一些学习的误区</h2> <ul> <li> <p><code>看书喜欢画线、画高光</code>:很容易给自己造成”画了就是会了“的错觉,不是不可以画重点,但是记得要通过<strong>自测</strong>的方式检验一下自己是否真的掌握。</p> </li> <li> <p><code>能看懂,就是会了</code>:能看得懂不代表能独立解决,不要觉得你理解的知识,就是你的知识。一定要自己亲自<strong>去实践,去自测</strong>。要建立自己的思维模式,而不是被动的接受知识。</p> </li> <li> <p><code>过度学习</code>:在掌握一个知识后继续反复学习和训练的行为,在需要练出肌肉记忆、自动反应的情况下是必要的(比如体育竞技、演讲),在其他状况下,过度学习是<strong>对时间和精力的浪费</strong></p> </li> <li> <p><code>思维定势</code>:固定的思维形式、牢固的记忆和chunk可能会阻碍你发现更好的灵感,因此在学习新事物时,要<strong>把过去的思维模式先放下</strong>。(有几个关于死亡的句子对这个观点具有启发性:1. There's the old saying that science progresses one funeral at a time,国外有句老话说,科学会随着每个葬礼的进行而进步; 2.乔布斯在斯坦福大学的演讲中曾说,死亡是我们生命中最酷的发明,死亡是生命轮换的代理人,它淘汰旧的以给新生事物发展空间。 3. 死亡意味着根深蒂固的旧思想的流逝)</p> </li> </ul> <h2>一些学习的技巧</h2> <ul> <li><code>记笔记</code>:看书时,减少划线和画高光以避免错觉,可以在知识点旁边写下你<strong>自己的理解</strong>,这样更利于加深印象,巩固记忆(酥鱼我仍然记得,我高中的时候做练习册,都喜欢把练习册写的黑压压的,即使是我掌握了的知识,也会在旁边写上清晰的解题思路。这种习惯一直延续到现在,我看过的书随便翻一翻就能看到笔记。我相信比起看完了还是一片雪白的书,这种方式更容易加深记忆</li> <li><code>换个环境</code>:间隔重复练习的时候,<strong>切换不同的环境</strong>,可以帮助我们脱离记忆对固定场景的依赖,避免单环境下的知识误区,更全面的理解所学知识的各个方面</li> <li><code>transfer知识迁移</code>:联系<strong>不同领域</strong>的相似chunk,也有助于加深记忆</li> <li><code>interleaving交替学习</code>:在已经掌握了基础知识后,可以<strong>交叉</strong>着不同类别的问题、方法、知识一起学习,有利于让大脑更具有灵活性和创造性,也更利于记忆。(用过百词斩的应该知道,他们的逻辑就是背一轮单词,再来一轮,不同的单词交替着出现,比一个单词一直背的效果好很多)另外可以了解一下<strong>Anki软件</strong>,利用交替学习等原理实现了帮助记忆的算法,形式类似于百词斩,只是把单词换成了你想记忆的知识点。</li> <li><code>奖励性学习</code>:在学习或者完成适量的目标后<strong>激励自己</strong>,可以让负责人体动力的多巴胺发挥生理作用</li> <li><code>刻意训练</code>:<strong>专注于学习困难的部分</strong>,是容易和别人拉开差距、超越平均水平的好方法</li> <li><code>关注过程,而不是结果</code>:对于一些困难的任务,需要很多时间和付出才能得到结果,如果只关注结果,会让人产生痛苦,导致拖延。只关注过程恰恰其实是大脑最喜欢的,在deadline之前的时间内,平静地尽最大的努力,关注每个番茄钟的30分钟周期,是否专注成功。</li> <li><code>在睡前坚持写周计划和日计划</code>:研究显示入睡时潜意识会进入类似于 Diffuse Mode 的状态来“消化”和“排练”要完成的项目,从而使你在白天能更好地去完成他们。写计划的另一个好处在于,如果你不这么做,这些待办事项就会停留在你的 Working Memory 中,占据宝贵的精神空间。通过将它们转移到纸上,你能够更好地专注于做事情本身。</li> <li><code>确定好停止学习的时间</code>:计划并严格遵守于 停止学习、专注、工作的时间是很重要的。这么做有助于形成日程规律,形成惯性,还给你更多时间去休息、发展身心健康</li> <li><code>把最困难最厌恶的事情放在早上第一件事做</code></li> <li><code>运动</code>有助于神经元的活跃,有助于学习和记忆</li> <li><code>创建生动的视觉比喻和类推</code>,将知识形象化,能够帮助你更好地理解内容本身,将新事物与旧的神经回路联系了起来,使得大脑能思考得更快、更发散,也能帮助你突破定势 比如 18 世纪的化学家开始想象和可视化分子级别的运动时,他们取得了巨大的突破。</li> <li><code>与其他人一起合作</code>,在专注模式下,大脑倾向于坚持已经建立的推理步骤。与其他人一起合作可以填补你思维上的空缺,建立起更强的自我纠正能力。从这个意义上讲,与你一同合作的人们就好像是对你而言的外部发散思维。对身边的人解释所学的内容也有助于自身的学习。</li> <li><code>考试策略</code>:前文中多次提到<strong>自测</strong>,测试本身是一种非常有用的学习体验,</li> </ul> <h2>如何准备一场考试</h2> <p>这里介绍 Richard Felder 博士 提出的<strong>备考清单</strong>。</p> <ul> <li>是否认真地理解了内容?</li> <li>是否与同学讨论过课后问题?</li> <li>是否尝试列出课后问题的解题大纲?</li> <li>是否积极参加小组讨论?</li> <li>咨询过老师吗?</li> <li>是否弄清楚了所有课后问题的答案?</li> <li>对于不清楚的问题,是否在课堂上提出疑问?</li> <li>是否尝试快速列出一些问题的解题大纲?</li> <li>是否认真通读了辅导书</li> <li>是否参与考前复习?</li> <li>测试前有一个合理的睡眠时间吗?</li> </ul> <p>对于上述问题,在理想的备考状态下,肯定的回答越多越好。</p> <p><code>一些考试时的策略</code>:</p> <ul> <li> <p><strong>先难后易</strong>:如果我们先大概看一眼题目,从困难的问题出发,将它们“加载”到大脑中,然后跳回去做简单的问题,从而使大脑进入 Diffuse Mode 发散模式,这样就很有可能在较短的时间内找到难题的思路(当然,应该控制在你能力范围内,如果短时间内找不到思路,应该直接跳过)</p> </li> <li> <p><strong>保持兴奋</strong>:当你处于紧张状态时,大脑会分泌化学物质引发一系列生理反应。但你可以用不同的方式来解读这些反应。恐惧和兴奋其实是两种很相似的反应。当你坐在考场里,心跳加速,满头是汗,如果你<strong>不去想“这场考试让我恐惧”而是“这场考试让我兴奋”</strong>,这会对你的考试非常有 帮助。</p> </li> <li> <p><strong>深呼吸</strong>:考试时感到心慌是自然反应。你可以通过深呼吸来部分或者全部抵消这一反应。当然,不要等到考试的时候才去做。考前两周、考试开始前的最后时间里做深呼吸,有助于平复心情。</p> </li> <li> <p><strong>不要被大脑欺骗</strong>:我们的大脑经常会欺骗自己,是自己认为自己的解答是正确的。在考试过程中要时刻小心,可以多眨眨眼或是晃晃头,用这种方式来提醒自己稍微往 Diffuse Mode 发散模式 倾斜一点看看有没有出错,然后再用 Focused Mode 专注模式 进行确认。</p> </li> </ul> <h2>拖延症 &amp; 习惯</h2> <p><strong>拖延症的原理</strong>:</p> <p>拖延症是个普遍的现象,在所有人身上多多少少都有体现,这是因为,<strong>拖延是大脑做出的自然反应</strong>。</p> <p>当你遇到不想做的事情时,会感受到不快,这种刺激(Cue)激活了大脑中与疼痛相关的区域,大脑就会迅速作出反应去寻找停止这种负面刺激的方式,即转移注意力到另一件令你愉快的事情上,从而让你在短期内感到舒服一些。</p> <p><strong>拖延症的影响:</strong></p> <p>拖延的负面影响不限于当前被拖延的事情。例如你觉得某一门课或者某一类知识很难,拖延症使你不断地拖迟学习它,当这种拖延行为成为习惯后,即使是想到学习这件事,都会令你痛苦。</p> <p>因此拖延的负面影响是有累积效应的,越拖延,不适的感觉越强。</p> <p><code>对抗拖延症的几个技巧</code>:</p> <ul> <li>有研究人员发现,当人们真正去做不喜欢的事情后,这种精神上的抵触和不适很快就会消失。了解这个原理,在遇到不想做的事情时,暗示自己<strong>先开头去做,很快就能克服</strong>,就可以减轻负面刺激带来的不快感</li> <li><strong>番茄工作法</strong>:利用计时器或者番茄钟,<strong>计时25分钟</strong>,这25分钟内排除一切干扰集中精力专注,专注结束后,<strong>计时5分钟</strong>,给自己一些奖励:放松一下/起来溜达一圈/上网冲冲浪/吃点零食/聊会天。30分钟一次循环,这样的时间效率会相当高,计时器的作用,就是Cue,提醒你切换专注模式和发散模式。(25分钟的专注,对于大多数人来说应该不难。但是如果你发现自己很难持续专注25分钟,那可以循序渐进,先从10分钟开始训练自己的专注耐力)</li> <li>利用<code>习惯</code></li> </ul> <p>对抗拖延症,是对抗身体的本能,需要消耗精力和意志力,而<strong>习惯就是我们的节能机制</strong>。</p> <p>一旦形成习惯,只需要一点点的Cue(信号),后面的行为就会<strong>像呼吸一样自然</strong>,消耗很少的精力和毅力</p> <p>就像你刚开始学车,倒车入库会让你手足无措、手心流汗、提心吊胆,但是当你成为了老司机,看后视镜、转动方向盘就会一气呵成,流畅自然。</p> <p>那么<code>如何养成好习惯</code>呢:</p> <ol> <li>Cue信号:触发惯性行为的外界刺激。比如待办清单上的第一项,办公桌前的便利贴。Cue 大致可以分为四类:时间、地点、感受、反应,从这四个方面,<strong>为自己的好习惯,找一个显眼的信号</strong>。</li> <li>Routine惯性行为:大脑受到信号刺激后,习惯性做出的反应。<strong>反复多次的练习</strong>,就可以养成。</li> <li>Reward奖励:任何习惯得以延续,都是因为它可以回报我们,它会立即给我们带来愉悦感。拖延极易养成习惯,就是因为拖延能带给我们迅速即时的愉悦感。因此为了克服拖延症,<strong>奖励好习惯</strong>很重要。</li> <li>Belief信念:习惯的力量之所以强大,是因为你在内心深处往往认为它们是无法被改变的。</li> </ol> <h2>总结</h2> <ul> <li>灵活运用<code>两种思维模式</code>:专注模式更适合解决细节问题,发散模式更适合寻找灵感和整体解决方案</li> <li><code>牢固记忆</code>的4个技巧:间隔重复、感官联系、充足睡眠+睡前复盘、保持冷静</li> <li>学习的本质是<code>建立组块</code>Chunks,建立过程有三个步骤:开启专注模式、自下而上学习、自上而下学习</li> <li>最高效的学习方法:<code>间隔重复</code>练习法(可以用Anki应用辅助)</li> <li><code>拖延症</code>没那么可怕,只要开始入手做,痛苦就会减轻;可以利用<code>番茄钟</code>、良好的<code>习惯</code>,来帮助你减轻拖延症提高效率</li> <li>4个学习误区、14个学习技巧、关于考试的几个技巧也值得掌握~</li> </ul> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/learning_how_to_learn/#post-comment/</comments>
</item>
<item>
<title>Harmony OS | 作为前端技术人,体验刚开源的鸿蒙OS</title>
<link>https://www.scarsu.com/hmos/</link>
<guid isPermaLink="true">https://www.scarsu.com/hmos/</guid>
<description>鸿蒙OS中的轻量级响应式前端框架</description>
<pubDate>Sat, 12 Sep 2020 00:00:00 GMT</pubDate>
<content:encoded><p><img src="/images/hmos/000.png" alt="" /></p> <p>华为2020开发者大会在9月10号如约而至</p> <p>从2019年大会鸿蒙发布后,很多人的目光都聚焦在了鸿蒙OS的开源计划上,“PPT系统”的声音不绝于耳</p> <p>今天发布会之前,吃瓜的我无意间在gitee上看到了这个横幅👇,我知道,终于它来了</p> <p><img src="/images/hmos/001.png" alt="HDC2020" /></p> <p>截至到我发稿前,开源仓库已经有了2k+ star</p> <p><img src="/images/hmos/002.png" alt="鸿蒙OS即将开源" /></p> <p>并且提供了看起来比较完善的中文文档</p> <p><img src="/images/hmos/003.png" alt="鸿蒙OS开源" /></p> <p>同时发布了一款配套的IDE <strong>「DevEco Studio」</strong>,注册开发者即可下载</p> <p><img src="/images/hmos/004.png" alt="鸿蒙OS - DevEco Studio" /></p> <h2>前端er上手体验</h2> <p>作为一个前端技术人,比较令我兴奋的是,鸿蒙OS有一套基于<strong>前端技术栈</strong>的UI开发框架</p> <p><img src="/images/hmos/005.png" alt="鸿蒙OS - JS框架" /></p> <p>于是我上手体验了一下,下面简单介绍一下步骤。</p> <p>安装IDE之后,创建项目,这里我选择了一个TV设备的项目模板</p> <p><img src="/images/hmos/006.png" alt="鸿蒙OS" /></p> <p>做一些简单的配置</p> <p><img src="/images/hmos/007.png" alt="鸿蒙OS" /></p> <p>然后会自动打包构建出一个demo项目,并且在IDE内提供了远程模拟设备</p> <p><img src="/images/hmos/008.png" alt="鸿蒙OS" /></p> <p>选取合适的模拟设备后,就可以运行项目了,得到的效果是这样的</p> <p><img src="/images/hmos/009.png" alt="鸿蒙OS" /></p> <h2>代码</h2> <p>效果图这样的一个电视页面,用到了 <strong>hml+css+js</strong> 三部分代码</p> <p>hml:</p> <pre><code>&lt;div class="container"&gt; &lt;div class="tv_box"&gt; &lt;div class="title_box"&gt; &lt;text class="title"&gt;{{title}}&lt;/text&gt; &lt;text class="title"&gt;酥鱼TVtest&lt;/text&gt; &lt;button type="circle" icon="{{icon_src}}" class="setting_box" onfocus="iconFocusFunc" onblur="iconBlurFunc" &gt;&lt;/button&gt; &lt;/div&gt; &lt;tabs class="tab_box"&gt; &lt;tab-bar mode="scrollable" class="bar_box"&gt; &lt;block for="[1,2,3,4,5,6,7,8,9]"&gt; &lt;text class="tab_text"&gt;{{$t('strings.tab')}} &lt;/text&gt; &lt;/block&gt; &lt;/tab-bar&gt; &lt;tab-content&gt; &lt;block for="[1,2,3,4,5,6,7,8,9]"&gt; &lt;div class="content_box"&gt; &lt;list class="content_img"&gt; &lt;block for="[1,2,3,4]"&gt; &lt;list-item type="listItem" class="list_img"&gt; &lt;image focusable="true" class="tab_img" src="/common/img-large.png" &gt;&lt;/image&gt; &lt;/list-item&gt; &lt;/block&gt; &lt;/list&gt; ... &lt;/div&gt; &lt;/block&gt; &lt;/tab-content&gt; &lt;/tabs&gt; &lt;/div&gt; &lt;/div&gt; </code></pre> <p>js:</p> <pre><code>import app from "@system.app"; export default { data: { title: "", subtitle: "", icon_src: "/common/plus.png", appName: app.getInfo().appName, }, onInit() { this.title = this.appName; this.subtitle = this.$t("strings.subtitle"); }, iconFocusFunc: function () { this.icon_src = "/common/plus-black.png"; }, iconBlurFunc: function () { this.icon_src = "/common/plus-white.png"; }, }; </code></pre> <p>css:</p> <pre><code>.container { flex-direction: column; justify-content: center; align-items: center; background-color: #000000; } .title_box { flex-direction: row; justify-content: space-between; align-items: center; height: 60px; } .title { font-size: 36px; color: rgba(255, 255, 255, 0.9); margin-left: 48px; } ... </code></pre> <h2>JS架构和源码</h2> <p>鸿蒙的 JS 框架 <strong>ace_lite_jsfwk</strong>,官方介绍是“轻量级 JS 核心开发框架”</p> <p>&lt;!-- <img src="https://gitee.com/openharmony/docs/raw/master/readme/figures/js-framework.png" alt="架构图" /> --&gt;</p> <p><img src="/images/hmos/012.png" alt="鸿蒙OS 前端框架 架构图" /></p> <blockquote> <p>提供了一套跨平台的类web应用开发框架,通过Toolkit将开发者编写的<strong>HML、CSS和JS</strong> 文件编译打包成<strong>JS Bundle</strong>,然后再将JS Bundle<strong>解析运行成C++ native UI的View 组件</strong>进行渲染。通过支持三方开发者使用声明式的API进行应用开发,以数据驱动视图变化,避免了大量的视图操作,大大降低了应用开发难度,提升开发者开发体验。</p> </blockquote> <p>源码的地址在:<a>https://openharmony.gitee.com/openharmony/ace_lite_jsfwk</a></p> <p>其中JS的核心代码,主要在以下几个文件</p> <pre><code>runtime-core\src\core\index.js runtime-core\src\observer\ |----observer.js |----subject.js |----utils.js runtime-core\src\profiler\index.js </code></pre> <p>也提供了一些测试用例:</p> <p><img src="/images/hmos/010.png" alt="鸿蒙OS" /></p> <p>从源码看,实现了一个轻量的响应式MVVM系统,使用了 vue2 同样的属性劫持技术,即 <code>Object.defineProperty</code> API。</p> <h2>总结</h2> <p>整体体验下来,感觉开发过程还是很丝滑的,api和开发模式很有vue的味道,应该存在借鉴。对于vue技术栈的前端er来说应该很好上手</p> <p><img src="/images/hmos/011.png" alt="鸿蒙OS" /></p> <p>自从去年的贸易战到后来的疫情,国际局势日趋复杂,鸿蒙OS的开源,对于国家和国内技术行业都有非凡的意义</p> <p>单从前端行业的角度来看,鸿蒙OS的发布,给前端技术人提供了web之外,扩展向物联网行业的,更广的发挥空间和更多的应用场景</p> <p>值得前端技术人向国内鸿蒙开源社区,提供更多的关注,注入更多的技术力量</p> <h2>资源</h2> <ul> <li><a>鸿蒙OS开源地址</a></li> <li><a>鸿蒙OS IDE下载</a></li> <li><a>鸿蒙OS开发者文档</a></li> <li><a>鸿蒙OS前端js框架文档</a></li> <li><a>鸿蒙OS前端js框架源码</a></li> </ul> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/hmos/#post-comment/</comments>
</item>
<item>
<title>Vu3响应式原理</title>
<link>https://www.scarsu.com/vue3_reactive/</link>
<guid isPermaLink="true">https://www.scarsu.com/vue3_reactive/</guid>
<description>vue2 & vue3 响应式原理对比,手写mini版vue3响应式代码</description>
<pubDate>Fri, 24 Jul 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>关于Vue3</h2> <p>话说,Vue3已经进行到rc4版本了,4月份beta发布的时候前端圈红红火火,不知道大家开始学了没</p> <p>整理了一些资源,现在开始学习应该还不算晚[狗头]</p> <ul> <li><a>vue-next仓库</a></li> <li><a>20200723 Vue3 官方发布的beta文档</a></li> <li><a>Vue3 Roadmap &amp; FAQ</a></li> <li><a>Vue3仓库已经合并的780多个PR</a></li> <li><a>尤大在Vue Mastery的Vue3课:Vue 3 Deep Dive with Evan You</a></li> <li><a>202007 尤大在前端会客厅节目关于Vue3的访谈</a></li> <li><a>202005 The process: Making Vue 3</a></li> <li><a>202004 尤大 - 聊聊 Vue.js 3.0 Beta 官方直播</a></li> <li><a>2018 VueConf 杭州 尤大关于Vue3的演讲视频</a></li> </ul> <h2>vue2 响应式原理回顾</h2> <ul> <li>对象响应化:遍历每个key,通过 <code>Object.defineProperty</code> API定义getter,setter</li> </ul> <pre><code>// 伪代码 function observe() { if (typeof obj != "object" || obj == null) { return; } if (Array.isArray(obj)) { Object.setPrototypeOf(obj, arrayProto); } else { const keys = Object.keys(); for (let i = 0; i &lt; keys.length; i++) { const key = keys[i]; defineReactive(obj, key, obj[key]); } } } function defineReactive(target, key, val) { observe(val); Object.defineProperty(obj, key, { get() { // 依赖收集 dep.depend(); return val; }, set(newVal) { if (newVal !== val) { observe(newVal); val = newVal; // 通知更新 dep.notify(); } }, }); } </code></pre> <ul> <li>数组响应化:覆盖数组的原型方法,增加通知变更的逻辑</li> </ul> <pre><code>// 伪代码 const originalProto = Array.prototype; const arrayProto = Object.create(originalProto)[ ("push", "pop", "shift", "unshift", "splice", "reverse", "sort") ].forEach((key) =&gt; { arrayProto[key] = function () { originalProto[key].apply(this.arguments); notifyUpdate(); }; }); </code></pre> <h2>vue2响应式痛点</h2> <ul> <li>递归,消耗大</li> <li>新增/删除属性,需要额外实现单独的API</li> <li>数组,需要额外实现</li> <li>Map Set Class等数据类型,无法响应式</li> <li>修改语法有限制</li> </ul> <h2>vue3响应式方案</h2> <p>使用ES6的 <strong><a><code>Proxy</code></a></strong> 进行数据响应化,解决上述Vue2所有痛点</p> <p>Proxy可以在目标对象上加一层拦截/代理,外界对目标对象的操作,都会经过这层拦截</p> <p>相比 <code>Object.defineProperty</code> ,Proxy支持的对象操作十分全面:get、set、has、deleteProperty、ownKeys、defineProperty......等等</p> <pre><code>// reactive 伪代码 function reactice(obj) { return new Proxy(obj, { get(target, key, receiver) { const ret = Reflect.get(target, key, receiver); return isObject(ret) ? reactice(ret) : ret; }, set(target, key, val, receiver) { const ret = Reflect.set(target, key, val, receiver); return ret; }, deleteProperty(target, key) { const ret = Reflect.deleteProperty(target, key); return ret; }, }); } </code></pre> <h2>响应式原理</h2> <p><img src="/images/vue3/reactive.png" alt="vue3响应式原理图" /></p> <ul> <li>通过 <strong><code>effect</code></strong> 声明依赖响应式数据的函数cb ( 例如视图渲染函数render函数),并执行cb函数,执行过程中,会触发响应式数据 <code>getter</code></li> <li>在响应式数据 <code>getter</code>中进行 <code>track</code>依赖收集:建立 <strong>数据&amp;cb</strong> 的映射关系存储于 <code>targetMap</code></li> <li>当变更响应式数据时,触发 <code>trigger</code> **,**根据 <code>targetMap</code> 找到关联的cb执行</li> <li>映射关系 <code>targetMap</code> 结构:</li> </ul> <pre><code>targetMap: WeakMap{ target:Map{ key: Set[cb1,cb2...] } } </code></pre> <h2>手写vue3响应式</h2> <p>大致结构</p> <pre><code>// mini-vue3.js /* 建立响应式数据 */ function reactice(obj) {} /* 声明响应函数cb(依赖响应式数据) */ function effect(cb) {} /* 依赖收集:建立 数据&amp;cb 映射关系 */ function track(target, key) {} /* 触发更新:根据映射关系,执行cb */ function trigger(target, key) {} </code></pre> <h3>reactive</h3> <pre><code>/* 建立响应式数据 */ function reactive(obj) { // Proxy:http://es6.ruanyifeng.com/#docs/proxy // Proxy相当于在对象外层加拦截 // Proxy递归是惰性的,需要添加递归的逻辑 // Reflect:http://es6.ruanyifeng.com/#docs/reflect // Reflect:用于执行对象默认操作,更规范、更友好,可以理解成操作对象的合集 // Proxy和Object的方法Reflect都有对应 if (!isObject(obj)) return obj; const observed = new Proxy(obj, { get(target, key, receiver) { const ret = Reflect.get(target, key, receiver); console.log("getter " + ret); // 跟踪 收集依赖 track(target, key); return reactive(ret); }, set(target, key, val, receiver) { const ret = Reflect.set(target, key, val, receiver); console.log("setter " + key + ":" + val + "=&gt;" + ret); // 触发更新 trigger(target, key); return ret; }, deleteProperty(target, key) { const ret = Reflect.deleteProperty(target, key); console.log("delete " + key + ":" + ret); // 触发更新 trigger(target, key); return ret; }, }); return observed; } </code></pre> <h3>effect</h3> <pre><code>/* 声明响应函数cb */ const effectStack = []; function effect(cb) { // 对函数进行高阶封装 const rxEffect = function () { // 1.捕获异常 // 2.fn出栈入栈 // 3.执行fn try { effectStack.push(rxEffect); return cb(); } finally { effectStack.pop(); } }; // 最初要执行一次,进行最初的依赖收集 rxEffect(); return rxEffect; } </code></pre> <h3>track</h3> <pre><code>/* 依赖收集:建立 数据&amp;cb 映射关系 */ const targetMap = new WeakMap(); function track(target, key) { // 存入映射关系 const effectFn = effectStack[effectStack.length - 1]; // 拿出栈顶函数 if (effectFn) { let depsMap = targetMap.get(target); if (!depsMap) { depsMap = new Map(); targetMap.set(target, depsMap); } let deps = depsMap.get(key); if (!deps) { deps = new Set(); depsMap.set(key, deps); } deps.add(effectFn); } } </code></pre> <h3>trigger</h3> <pre><code>/* 触发更新:根据映射关系,执行cb */ function trigger(target, key) { const depsMap = targetMap.get(target); if (depsMap) { const deps = depsMap.get(key); if (deps) { deps.forEach((effect) =&gt; effect()); } } } </code></pre> <h3>测试demo</h3> <pre><code>&lt;!-- test.html --&gt; &lt;div id="app"&gt; {{msg}} &lt;/div&gt; &lt;script src="./mini-vue3.js"&gt;&lt;/script&gt; &lt;script&gt; // 定义一个响应式数据 const state = reactive({ msg:'message' }) // 定义一个使用到响应式数据的 dom更新函数 function updateDom(){ document.getElementById('app').innerText = state.msg } // 用effect声明更新函数 effect(updateDom) // 定时变更响应式数据 setInterval(()=&gt;{ state.msg = 'message' + Math.random() },1000) &lt;/script&gt; </code></pre> <p>效果:</p> <p><img src="/images/vue3/demo.png" alt="" /></p> <p>如果想获取上述代码,放在了这个<a>仓库:mini-vue3-reactive</a></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/vue3_reactive/#post-comment/</comments>
</item>
<item>
<title>非暴力沟通:有些话真的可以好好说</title>
<link>https://www.scarsu.com/nonviolent_communication/</link>
<guid isPermaLink="true">https://www.scarsu.com/nonviolent_communication/</guid>
<description>当我们褪去隐蔽的精神暴力,爱将自然流露。</description>
<pubDate>Sun, 14 Jun 2020 00:00:00 GMT</pubDate>
<content:encoded><p><img src="/images/nvc/nvc-map.png" alt="思维导图" /></p> <h2>前言</h2> <p>当有人批评指责你的时候,你的愤怒和失望会让你作出什么反应?</p> <p>你是否会以同样的方法去报复?</p> <p>还是干脆置之不理,实施冷暴力?</p> <p>有时候,你是否很想与家人、朋友、爱人进行友爱的沟通,和同事进行高效的沟通,却以矛盾、吵架和不愉快收场?</p> <p>当你看见别人的恶行、听见别人的恶语、在网络上遇到扛精喷子的时候,</p> <p>你是不是很想重拳出击,指责、批评、贬低、嘲讽、惩罚他?</p> <p>上面列举的这些沟通问题都可以归类到 <strong>暴力沟通</strong> 的范畴。</p> <p><strong>暴力沟通</strong> 困扰着我们生活的方方面面,对我们造成精神伤害,蒙蔽了我们的爱和情感。</p> <p>如果你也被类似的沟通问题所困扰,那么《非暴力沟通》这本书能启发你,如何通过 <strong>好好说话</strong>,来解决这些问题~</p> <h2>简介</h2> <p>今天分享的《非暴力沟通》这本书,于2018年,由华夏出版社出版,作者是美国的 马歇尔·卢森堡 博士,豆瓣评分: 8.8。</p> <h3>非暴力的表达+聆听</h3> <p>这本书指导我们转变谈话和聆听的方式。</p> <p>让我们不再条件反射式的反应,而是去了解自己的观察、感受和需求,有意识地使用语言。</p> <p>使我们既诚实清晰地表达自己,又尊重与倾听他人。</p> <h3>非暴力沟通的4要素</h3> <p>非暴力沟通模式下,我们需要关注4个要素:观察、感受、需求、请求。</p> <ul> <li>第1是表达我们此刻观察到什么,说出人们所做的事情,清楚表达观察的客观结果,而不是去主观判断或者评价。</li> <li>第2是了解和体会感受,比如受伤害怕喜悦开心气愤等等</li> <li>第3,我们需要去弄清楚,是哪些需求导致了我们这样的感受。</li> </ul> <p>举一个常见的例子来说:一位母亲可能对他处于青春期的儿子说</p> <blockquote> <p>我看到桌子下面有两只脏袜子, 我不太高兴, 因为我比较看重整洁</p> </blockquote> <ul> <li>接着她可以立即提出非暴力沟通的第4个要素,也就是具体的请求。</li> </ul> <p>她会说</p> <blockquote> <p>你是否愿意将袜子拿到房间或者放进洗衣机</p> </blockquote> <p>这一要素,要明确的告知他人,我们期待他采取哪种行动来满足我们的需求。</p> <p>这样这位母亲就清楚的说出了非暴力沟通的4个要素,借助这4个要素,诚实高效地表达了自己。</p> <p>下面我们将这4个要素拆分开来看,逐一分析,如何将这4个要素做好。</p> <h2>01 观察和评论</h2> <p>非暴力沟通的第1个要素是 <strong>描述观察</strong>。</p> <p>它强调的是我们要如实的表达出观察的客观结果,而不是我们的主观评价。</p> <p>举几个主观评价的例子:</p> <blockquote> <p>哥哥昨天无缘无故的对我发脾气 我男朋友是一个没有主见的人 我女朋友是一个很霸道的人</p> </blockquote> <p>其实以上这三个例子,在我们以往的沟通中十分常见。</p> <p>我们常常通过单一的行为去给一个人贴标签,</p> <p>我们通过静态的语言去定性变化不断的现实。</p> <p>印度哲学家<code>克里希那穆提</code>曾经说:</p> <blockquote> <p>不带评论的观察是人类智力的最高形式</p> </blockquote> <p>对于大多数人来说,观察他人及其行为,而不去评判指责,或以其他方式进行分析,是难以做到的。</p> <p>将客观的观察和主观的评价混淆,往往会在沟通中造成误解,让人产生逆反心理。</p> <p>想要更合理的表达出我们的观察,而不是评论,可以通过以下几点去改善。</p> <ul> <li>我们应该去关注有事实依据的具体行为</li> <li>而不是我们的愿望情感推测</li> <li>不应该把形容词和副词当作观察结果</li> <li>应该更少的使用“总是,从不,每次”这种言过其实的夸张词汇</li> </ul> <p>附上一张书中的对比表格:</p> <p><img src="/images/nvc/nvc2.jpg" alt="观察和评价" /></p> <h2>02 体会和表达感受</h2> <p>非暴力沟通的第2个要素是 <strong>表达感受</strong>。</p> <p>当我们的需求得到满足时,我们的感受可能会有:兴奋,喜悦,甜蜜,开心,振奋等等。</p> <p>当我们的需求没有得到满足的时候,我们的感受可能是:害怕,担心,焦虑,忧虑,着急,绝望,失望,不满,尴尬,遗憾等等。</p> <p>附上一张书中的感受词汇表:</p> <p><img src="/images/nvc/nvc3.jpg" alt="感受词汇表" /></p> <p>在往常的人际交往沟通中,我们往往不愿意表达自己的感受。</p> <p>因为社会文化并不鼓励我们表达个人需求。</p> <p>我们从小到大的教育,使我们习惯于考虑:人们期待我怎么做,而不是倾听自己的内心。</p> <p>但是积极的表达自己的感受,可以使别人更好的了解我们的需求,更容易得到积极的回应。</p> <h2>03 挖掘感受背后的需求</h2> <p>非暴力沟通的第3个要素是 <strong>表达需求</strong>。</p> <p>在分析非暴力沟通第2个要素的时候,我们强调,我们的喜悦或者失望的感受,都来源于 <strong>我们的需求是否得到满足</strong>。</p> <p>这一点其实至关重要,我们通常会错误的认为自己的感受是由他人的行为引起的。</p> <p>举一个简单的例子。</p> <p>我有一个闺蜜冬梅,有一次情人节,她男朋友因为加班没有陪她。</p> <p>如果冬梅跟她男朋友说</p> <blockquote> <p>你昨天没陪我,令我很失望</p> </blockquote> <p>那么她就是认为:<strong>她的感受是由别人的行为引起的</strong>。</p> <p>如果他跟她的男朋友说</p> <blockquote> <p>你昨天没陪我,我很失望,因为我需要你的陪伴</p> </blockquote> <p>那么此时冬梅能够清楚地了解到:<strong>自己感到失望,是因为她的需求没有得到满足</strong>。</p> <p>如果我们认为自己的感受是他人的行为引起的,那么我们更倾向于指责别人</p> <p>我们想利用他人的内疚来达到我们的需求,把自己不愉快的感受归咎于对方。</p> <p>如果我们通过批评来提出主张,人们的反应通常都是反驳和申辩。</p> <p>反之,如果我们直接说出需求,对方就更有可能做出积极的回应。</p> <p>但不幸的是大多数人并不习惯于从需求的角度来考虑问题,在不顺心的时候,我们倾向于考虑别人有什么错。</p> <p>在沟通中,如果双方都习惯于指责对方,这样的沟通往往都不会得到好的结果,伤害彼此的情感。</p> <p>因此从我们的感受,去发掘我们的个人需求,而不是下意识指责他人,是十分重要的。</p> <h2>04 发出请求</h2> <p>在我们清楚地表达观察感受和需求之后,对方往往会做出积极的回应。</p> <p>如果对方没有对我们的需求所处反应,那么我们可以提出请求。</p> <p>这也就是非暴力沟通的第4个要素。</p> <p>在提出请求时,我们应该提出更加具体可行的请求。</p> <p>举一个例子来说</p> <blockquote> <p>我希望你尊重我的个人隐私 我希望你进我房间之前敲门</p> </blockquote> <p>这两种表达,后者是非暴力沟通所倡导的,具体的请求。</p> <p>另外,区分请求和命令也很重要:</p> <p>请求没有得到满足时,如果提出请求的人批评和指责对方,那么这就是命令。他想利用对方的内疚来达到目的。</p> <p>如果别人拒绝了你的需求,那么你也可以通过更深的沟通,去了解别人拒绝你请求的意图,和隐藏在背后的需求。</p> <h2>需求驱动</h2> <p>在有些场景下,书中的固定模式应用起来也许不太合适,</p> <p>但是,只要掌握了非暴力沟通的 <strong>核心思想</strong> ,都能达成非暴力沟通。</p> <p>那就是 <strong>以需求为驱动</strong> 。</p> <p>无论是怎样的沟通场景,</p> <p>无论你是表达的一方,还是聆听的一方,</p> <p>不要急于表达和作出反应,先去 <strong>观察</strong> 和 <strong>感受</strong> ,去发觉彼此的需求,</p> <p>当你透过语言,洞察到了别人的需求,你会用全新的眼光,去看待我们的人际关系,让自己和家人、朋友、同事、爱人,都拥有更好的交际体验。</p> <p>当你透过情绪和感受,洞察到了自己的需求,你能够用更高效更友善的方式,去达到自己的需求,令自己更舒适,令你的生活更有乐趣和爱意。</p> <h2>好好说话的力量</h2> <p>通过这本书,我感受到了好好说话的非凡力量</p> <p>非暴力沟通这种充满善意和爱的沟通方式。</p> <p>能使我们脱离情绪的控制,更好的了解自我,与自我建立和谐的关系。</p> <p>使我们拥有更清晰的沟通思路,更高效的掌握沟通信息,达成沟通目的,</p> <p>同时,还拥有更好的沟通体验。</p> <p>让我们能更加舒适、更加专注的去追求人生的方向。</p> <h2>反思</h2> <p>读完这本书,可以发现,非暴力沟通的实践和应用,不是一朝一夕能达成的。</p> <p>我分享的只言片语,也并不能传达全书的信息。</p> <p>因此这本书,值得你反复阅读、思考,并亲身实践。</p> <p>附上书中的一首诗歌:</p> <p><img src="/images/nvc/nvc.jpg" alt="语言是窗户,否则它们是墙" /></p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/nonviolent_communication/#post-comment/</comments>
</item>
<item>
<title>富爸爸穷爸爸:为什么你很穷</title>
<link>https://www.scarsu.com/rich_dad/</link>
<guid isPermaLink="true">https://www.scarsu.com/rich_dad/</guid>
<description>《富爸爸穷爸爸》被誉为“全球最好的”理财入门书,这本书不会教你如何理财,但是会让你对“金钱”有一个全新的观念和认知。</description>
<pubDate>Sun, 14 Jun 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>简介</h2> <ul> <li>文章标题只是想侧面说明这本书的主要内容,请勿对号入座~</li> <li>我本人是个工作不到两年、背着房贷、没什么存款的理财门外汉,读完这本书,彻底改变了我对“钱”的认知和观念,因此把书中启发到我的地方分享出来,希望对你有些帮助~</li> <li>《富爸爸穷爸爸》从1997年最初版至今已经23年,在全球范围大受欢迎,被誉为“全球最好的理财入门书”,连续六年在纽约时报畅销书榜都榜上有名,目前已翻译超过51国语言。后续又出了一系列以达成财务自由为中心的 <strong>“富爸爸系列”丛书</strong>,。</li> <li>书名中的 <strong>穷爸爸</strong>,指的是作者的亲生父亲,受过良好的教育:从斯坦福大学和芝加哥大学毕业,博士学位,身居夏威夷州教育部门的要职,一生勤奋工作,收入颇丰,是一个看起来十足“成功”的高级知识分子。但是他终其一生都在个人财务问题的泥潭中挣扎,操劳一生离开人世留下了一堆账单。他总是教育作者:要努力学习,取得好成绩,这样才能有好的工作。</li> <li>书名中的 <strong>富爸爸</strong>,指的是作者好友的父亲,初中学历,没有很高的教育水平,但是是一个成功的商人,充分理解金钱的力量,拥有很高的财商,富爸爸是成为了全夏威夷最富有的人之一,他身后留下的是慈善机构、教堂以及巨额的遗产。作者和朋友很小的时候,就开始接受了富爸爸的财商教育。</li> <li>作者:<strong>Robert T. Kiyosaki,Robert ·清崎</strong>,日裔美国人,在1994年47岁的时候,因为遵循了富爸爸教给他的关于金钱和投资的知识,实现了财务自由,创造了“现金流”游戏,财务自由后因出版《富爸爸》系列书而成名,成为金融教育领域的领头人。</li> <li>书中用很多篇幅,对比富爸爸和穷爸爸,指出性格、思想、行为和结果上的差异,从而引出造成贫富差异的原因。</li> </ul> <h2>带着问题看文章</h2> <ul> <li>上班、工作、打工几十年,真的能积累财富吗?</li> <li>退休依靠养老金的模式可靠吗?</li> <li>买房是稳赚不赔的投资吗?</li> <li>普通家境的人用父母前十几年+自己后几十的劳动剩余价值换来的房子值得吗?</li> <li>财商是什么?、财务自由是什么?</li> <li>富人和穷人的差异有哪些?消费观、财商、勇气、自律...</li> </ul> <hr /> <h2>老鼠赛跑的人生</h2> <p>我成长在一个普通家庭,和周围的大多数普通家庭的同学一样,从小到大都接受着来自父母、亲戚、老师的教育:</p> <p>小学中学阶段,他们让我好好学习考一个好大学</p> <p>大学阶段,他们让我好好学习找一个稳定的好工作。</p> <p>工作之后,我拿着在父母眼中还算体面的工资,开始有了消费的自由,买一些自己喜欢的东西。</p> <p>也许不久的将来,我会遇到心爱的人,开始组建新家庭,在我们多年不断努力的工作下,我们的薪水实现了增长,进入 “<strong>中产阶级</strong>” ,但是我们依然需要依靠双方父母的积蓄买房付首付,我们的消费和纳税也水涨船高,我们买车、计划旅行、养孩子......</p> <p>这时候工作就会变成我人生最重要的事情。</p> <p>我需要努力的为老板工作、通过纳税为国家发展做贡献、通过房贷为银行工作。因为工资是我唯一的收入来源,我需要依靠工资来支付生活成本,维持消费,还花呗信用卡,支付房贷月供。</p> <p>于是,我需要不停不休的朝九晚五(甚至996),上班工作,直到退休。</p> <p>我可能还会把同样的教育施加在我的孩子身上,让这样的人生在下一代身上继续循环重复。</p> <p>也许看到文章的朋友中,有创业者,有事业有成的成功人士,有对理财投资颇有心得的朋友。但是当代乃至我们的上一代人,大多数人都有着类似的人生轨迹。</p> <p>这就是《富爸爸》这本书里写的 <strong>“老鼠赛跑”的游戏</strong> :每一代人都不懂理财规划,只会通过拼命工作和加班,用大量的工作时间来换取金钱,再用这些金钱来养育子女赡养父母,而自己的子女也在重复着父母心这一辈的命运。</p> <blockquote> <p>人们的生活总是被恐惧和贪婪控制,太努力工作,而忘记了思考</p> </blockquote> <p>我们因为 <strong>恐惧</strong> 而工作:害怕付不起房贷、养不起老人孩子;</p> <p>我们因为 <strong>贪婪</strong> 而工作:随着工资增加,消费也增加;</p> <blockquote> <p>穷人为钱工作,富人让钱为他工作</p> </blockquote> <p>我们每天都在为了更稳定的生活、更好的生活水平,努力勤恳的上班、挣工资。</p> <p>但是这样的生活方式根本就不是任何一个富人的生活方式。</p> <p>实现了财务自由的富人,不会为了钱而工作,他们用钱创造更多的钱,为自己的消费买单。</p> <h2>区分资产和负债</h2> <p>想要向富人迈进,创造财富,最重要的第一步,就是要分清楚 <strong>资产和负债</strong>:</p> <ul> <li>资产:带来正向“现金流”的个人拥有的东西 =&gt; 能把钱放进你口袋的东西。</li> <li>负债:产生支出的个人拥有的东西 =&gt; 把钱从你口袋拿走的东西。</li> </ul> <h2>关注自己的现金流</h2> <p>资产和负债强调的,就是 <strong>现金流</strong>。</p> <p>现金流更多用于分析企业是否良好经营,但是对于个人来说,<strong>越早关注现金流,有利于越早实现财务自由</strong>。</p> <p>《富爸爸》中用了 <strong>收益表+资产负债表</strong> 分别描述了穷人、中产阶级、富人的现金流:</p> <ul> <li>穷人的现金流</li> </ul> <p><img src="/images/rich/poor_cf.png" alt="穷人的现金流" /></p> <p>对于大多数穷人来说,他们的收入基本全部来源于工资,工资通过日常开支、教育支出等费用消耗掉。他们的资产和负债项是空的。</p> <ul> <li>中产阶级的现金流</li> </ul> <p><img src="/images/rich/middle_cf.png" alt="中产阶级的现金流" /></p> <p>中产阶级的现金流中多了一部分来自于负债的支出。负债项目包括:房贷、车贷、消费分期等。对于大多数买了刚需住房的人来说,房子只能算是他们的“负债”,因为带来不了正向的现金流,如果失业,他们可能会因为这些资产比穷人产生更多的压力,因为他们的开支中除了每月的生活开销,还有他的房贷、车贷。</p> <ul> <li>富人的现金流</li> </ul> <p><img src="/images/rich/rich_cf.png" alt="富人的现金流" /></p> <p>富人和穷人以及中产阶级最大的区别就是:富人的现金流,更多的来自他们的资产项,也就是所谓的“税后收入”,而不是工资。</p> <p>这也与Robert 对 <strong>财富</strong> 的定义相匹配:</p> <blockquote> <p>财富:一个人没有工作后能生活多久的能力</p> </blockquote> <p>对于实现了财务自由的富人来说,这个时间就是无限长,因为他们拥有足够多的资产,为他们创造足够支出的现金流收入,如果收入减去支出还有盈余,他们的资产就会不断增加。</p> <h2>合理的消费观</h2> <p>想要像富人那样更多的积累资产,拥有正向的现金流,培养合理的消费观,最小化支出+负债很重要。</p> <blockquote> <p>富人购买资产,穷人购买负债</p> </blockquote> <blockquote> <p>重要的不是挣了多少,而是能留下多少;</p> </blockquote> <p>身边经常有人在说,越有钱的人越抠门,还有人总抱怨自己的老板,如何俭省成本,苛待员工。</p> <p>其实不是富人抠门,而是富人深知,最小化支出,才能有更多的钱 用于购买资产,产生更多的正向现金流。</p> <blockquote> <p>富人赚的比你多,花的比你少</p> </blockquote> <p>作者Robert 提倡 <strong>享受要与财富匹配</strong> ,先把收入用于买入资产,用资产项的得利买想要的东西。</p> <p>也就是要<strong>自律消费</strong>。</p> <p>因为消费一定属于支出和负债,不要追求与自身资产不匹配的、不必要的虚荣和表层物质,不要被近几年消费升级的宣传所影响,网红带货、短视频即时营销、直播...资本市场越鼓励消费,说明资本市场从消费获利越大。</p> <h2>税收与公司</h2> <p>除了消费,赋税也是每个上班族不可避免的一部分。</p> <blockquote> <p>中产阶级在承担着沉重的税负,尤其是那些受过良好教育、高收入的中产阶级。</p> </blockquote> <p>这个观点似乎与普遍的认知有所出入,普遍的观点都认为富人应该缴纳更多的税让穷人受益,但事实上是这样的吗?</p> <p>这要从税收的历史讲起。</p> <blockquote> <p>英国和美国在早期是不需要纳税的,只有一些因战争而临时收的税,称为“纳捐”。</p> <p>直到1874年,英国规定纳税是国民义务,1913年,美国将征收所得税,纳入宪法。</p> <p>其后虽然有过冲突和争议,但是英国和美国都花了几乎50年来培养公民缴纳所得税的意识。</p> <p>最初只针对富人收税,但是随着国家发展,政府规模扩大,就需要征收更多的税以维持平衡运营。以致中产阶级也要被征税,且税收范围不断向穷人扩展。</p> </blockquote> <p>表面上来看,税收对富人和中产阶级是公平的。但实际上,有关企业的法律知识,给予了富人远超出穷人和中产阶级的优势。</p> <p>原因在书中也有提及:</p> <blockquote> <p>因为政府需要利用法制,刺激企业主和投资者创造更多的工作机会和住房,这些刺激政策降低了富人的赋税。</p> </blockquote> <p>因此,了解更多法律和财务知识的富人,总有办法从赋税中脱身,用Robert 的原话来说,就是:<strong>只要你拥有一种合法资产,我就可以找出以企业的形式提供的好处和保护</strong>,这也就是赋税最终落到中产阶级身上的原因。</p> <p>这种税收状况和解释,在中国也是基本适用的。</p> <p>因此,公司可以帮助富人避税,公司,并不一定是实体意义上的公司,不一定是有公司名称的办公楼、厂房,可以只是一份没有精神和灵魂的法律文件</p> <p>拥有公司的富人:挣钱~支出~缴税</p> <p>为公司工作的人:挣钱~缴税~支出</p> <p>了解更多的财务、法律知识,利用合理的方式避税,也是穷人和富人的区别。</p> <h2>财商</h2> <p>想要积累资产,除了要最小化支出和负债,用合理的方式避税之外,更重要的是,我们要懂得如何让自己的收入,换来更多的资产,Robert 把这种能力称为 <strong>财商</strong>。</p> <p>财商由四个方面构成:</p> <blockquote> <p>1、会计--财务知识,这是非常重要的技能,你管理的钱越多,越需要精确,否则这大厦就会倒下来!财务知识能帮你读懂财务报表,借助这种能力,你还能分辨业务的优势和劣势。</p> <p>2、投资--钱生钱的科学,投资涉及策略和方案,右脑做的事,或者说是创造。</p> <p>3、了解市场--供给与需求的科学,这要求了解受感情驱动的市场的“技术面”,市场的另一个因素是“基本面”,或者说一项投资的经济意义。一项投资究竟有无意义最终取决于当前的市场状况。</p> <p>4、法律--它可以帮助你有效运营一个进入会计、投资和市场领域的企业并实现爆炸性增长,了解税收优惠政策和公司法律的人能比雇员和小业主更快致富,这就像一个人在走,而另一个人却在飞,若从长远看这种差距会更大。</p> </blockquote> <p>踏实的学习上面的四个知识,提升财商,才能积累更多资产,让自己的每一块钱收入都能夜以继日的替自己工作,产生复利。</p> <h2>勇气</h2> <p>除了合理的消费观和财商,勇气也是影响我们致富的一个重要因素。</p> <blockquote> <p>我们一定是不断的摔倒才学会骑自行车的,我从就没见过一球都不失的高尔夫球手,也从来没见过不曾伤心过的恋人,更没见过从来不亏钱的富人,但是我却遇到过很多从来没有在投资活动中亏掉一毛钱的穷人。</p> </blockquote> <p>Robert 认为,我们应该克服对亏钱和失败的恐惧,为了获得更多的选择和机会而勇于冒险。</p> <p>因为惧怕风险和失败而止步不前,待在舒适圈,就一定会失去成功的机会。</p> <p>我们都听过“不要把鸡蛋放在一个篮子里”的经验,但是如果你的鸡蛋本来就很少,还只追求低风险,那只会让你的财富值止步不前,永远实现不了跃迁。</p> <p><strong>储蓄</strong>,是一种很常见的低风险投资,但是 Robert 认为,储蓄不一定是资产,储蓄不但ROI(投资回报率)低,不一定能跑赢通货膨胀,更重要的是,储蓄会使我们失去投资增值的机会。</p> <p><strong>买房</strong>,对于很多普通人来说,也是牵动人生的一大“投资”,依照短期的国情来看,也是一项稳定不会亏损的投资,但是房子一定是资产吗?虽然 Robert 本人的财务自由,有相当一部分是依靠投资,但是他认为,房子不一定是资产。</p> <p>区分房子是资产还是负债,根据前文说的方法其实很简单,如果你买房是刚需住房,那么你的房子无法给你带来正向现金流,反而会消耗你和家人前十几年(全款买房)的积蓄,或者后几十年(贷款买房)的劳动剩余价值,是“从你口袋拿钱出去”的负债。</p> <h2>持续学习是最大的投资</h2> <p>Robert 一生做了无数的投资抉择,有的给他带来了大量的财富和持续的正向现金流,但是他坚定地认为,持续学习才是他收益最高的一项投资。</p> <p>书中有多处描述,都印证了这一观点:</p> <blockquote> <p>人生是一场无知与觉醒的斗争</p> </blockquote> <blockquote> <p>人最大的财富是所受的教育</p> </blockquote> <blockquote> <p>钱不能解决一切问题,只有知识才能解决问题并创造财富</p> </blockquote> <p>Robert 认为,我们不应该单纯为了赚钱和稳定的生活而工作,应该更多的关注事业而不是职业,关注长远的发展而不是眼下的工资。</p> <p>他在实现财务自由之前,没有遵循“穷爸爸”的建议:长期从事在一个稳定的岗位,而是积极的投身于多种跨行业的工作,对于他来说,不同的工作经验,有助于他掌握更多维的知识,这些知识都对他实现财务自由,起到了关键作用。</p> <blockquote> <p>全世界到处都是才华横溢、极具天赋的人,但是只有天赋是不够的</p> </blockquote> <blockquote> <p>越极度专业化的人才,价值范围越有限</p> </blockquote> <p>不光是持续学习,Robert 更加强调的是横向发展。</p> <p>除非你是所在行业金字塔最顶端的人,否则过度局限的认知,会阻碍你的发展,局限你的人生。</p> <p>之前跟朋友聊天,他说过一句话我十分认同,也和作者的观点十分契合:我们无法赚到超出自己认知的钱,我们所赚的每一分钱都是我们对这个世界认知的变现。</p> <p>做一个“T型”人才,斜杠青年,有自己专业的领域,也要有宽阔的认知面,才能离成功更近。</p> <h2>克服本能</h2> <p>无论是 自律消费,还是 持续学习,都需要我们拥有坚定而强大的内心。</p> <p>前几天看新闻看到了博纳影业副总裁跳楼的消息,有一个<a>知乎回答</a>令我印象十分深刻:</p> <blockquote> <p>很多人向上看,只能看到富贵和纸醉金迷。可是真正一步步向上走,才会发现越往上越暗流汹涌。重回平凡的路被堵死,只能咬牙继续向上。在我们用奋斗的勇气和不服输的精神向上爬的过程中,别忘了打磨自己的心,让心变得无坚不摧。</p> </blockquote> <p>一切成功的前提,都需要我们有足够的自控力,让思想控制情感,让思考先于情感反应,要克服对失败的恐惧,克服懒惰,克服自负。</p> <p>打磨好自己的心,才能在上升时顺风而行,在下落时稳住脚步,不落入万丈深渊。</p> <h2>反思</h2> <ul> <li>其实看完这本书会发现,这不是一本急功近利的财富指南,因为我们不可能因为读一本书,就实现财富自由。</li> <li>但是至少我们知道了,在每一份支出之前,应该有更冷静、自律的判断,不被短暂的享受和营销影响,在每一份收入之后,应该更合理的分配投资和支出。</li> <li>读完这本书,也不仅仅给我带来了对“金钱”的改观,除了致富,想要在其他领域做的更好,持续学习、自律、扩展认知,都是必修课。</li> </ul> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/rich_dad/#post-comment/</comments>
</item>
<item>
<title>结合谈谈对Vue中nextTick的理解</title>
<link>https://www.scarsu.com/nexttick/</link>
<guid isPermaLink="true">https://www.scarsu.com/nexttick/</guid>
<description>tick这个词到底时什么意思😯?</description>
<pubDate>Wed, 10 Jun 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>带着问题看这篇文章</h2> <ul> <li>tick这个单词有点抽象,应该怎么理解?</li> <li>通过nextTick包装的回调,到底何时执行?</li> <li>nextTick存在的意义是什么?</li> </ul> <h2>event loop 中任务执行顺序</h2> <ol> <li>同步代码执行,直至调用栈清空</li> <li>microtask:调用栈清空后,优先执行<strong>所有</strong>的microtask,如果有新的microtask,**继续执行新microtask,**直至microtask queue清空(<strong>微任务</strong>)</li> <li>task queue:执行task queue第一个任务,后续的task暂不处理(<strong>宏任务</strong>)</li> <li>每当调用栈清空后,重复2-3步骤</li> </ol> <p>(关于 Event Loop的细节,我写过一篇很详细的总结<a>试图解释清楚Javascript Event Loop</a>。)</p> <h2>微任务与宏任务</h2> <p>根据event loop的执行机制,微任务的调度优先级比宏任务高.</p> <p>微任务异步API:Promise.then,MutationObserver</p> <p>宏任务异步API:setTimeout,MessageChannel,postMessage,setImmediate</p> <h2>Vue中nextTick的实现</h2> <p>vue中的 nextTick 实现在 util 模块的单个文件中,代码总共100多行:</p> <pre><code>// src\core\util\next-tick.js import { noop } from 'shared/util' import { handleError } from './error' import { isIE, isIOS, isNative } from './env' const callbacks = [] let pending = false function flushCallbacks () { pending = false const copies = callbacks.slice(0) callbacks.length = 0 for (let i = 0; i &lt; copies.length; i++) { copies[i]() } } let timerFunc // nextTick行为利用了微任务队列,微任务队列可以通过原生Promise.then或MutationObserver访问到。 // MutationObserver具有更广泛的支持,但是在iOS&gt; = 9.3.3中的UIWebView中,在触摸事件处理程序中触发时会发生错误。触发几次后,它将完全停止工作 // 因此,如果原生Promise可用,优先使用Promise: if (typeof Promise !== 'undefined' &amp;&amp; isNative(Promise)) { const p = Promise.resolve() timerFunc = () =&gt; { p.then(flushCallbacks) // 在有问题的UIWebViews中,会出现奇怪的状态:微任务队列中有回调但是不被清空,直到浏览器有其他任务,例如处理计时器 // 因此此处使用一个空计时器,来强制触发微任务队列执行 if (isIOS) setTimeout(noop) } } else if (!isIE &amp;&amp; typeof MutationObserver !== 'undefined' &amp;&amp; ( isNative(MutationObserver) || // PhantomJS and iOS 7.x MutationObserver.toString() === '[object MutationObserverConstructor]' )) { let counter = 1 const observer = new MutationObserver(flushCallbacks) const textNode = document.createTextNode(String(counter)) observer.observe(textNode, { characterData: true }) timerFunc = () =&gt; { counter = (counter + 1) % 2 textNode.data = String(counter) } } else if (typeof setImmediate !== 'undefined' &amp;&amp; isNative(setImmediate)) { // setImmediate,宏任务,但是相比 setTimeout 是个更好的选择 timerFunc = () =&gt; { setImmediate(flushCallbacks) } } else { // setTimeout 0 宏任务 timerFunc = () =&gt; { setTimeout(flushCallbacks, 0) } } export function nextTick (cb?: Function, ctx?: Object) { let _resolve callbacks.push(() =&gt; { if (cb) { try { cb.call(ctx) } catch (e) { handleError(e, ctx, 'nextTick') } } else if (_resolve) { _resolve(ctx) } }) if (!pending) { pending = true timerFunc() } // $flow-disable-line if (!cb &amp;&amp; typeof Promise !== 'undefined') { return new Promise(resolve =&gt; { _resolve = resolve }) } } </code></pre> <p>源码中, <code>Vue.nextTick/vm.$nextTick</code> 的具体逻辑:</p> <ul> <li>定义一个 <code>callbacks</code> 数组,用于存储 nextTick 接口传来的回调函数们</li> <li>定义一个 <code>flushCallbacks</code> 方法,用于遍历执行 callbacks 数组中的所有回调函数</li> <li>调用 <code>timerFunc</code> 方法,将 flushCallbacks 方法作为回调任务,添加到异步队列</li> <li>timerFunc由环境决定,<strong>微任务</strong>优先,宏任务作为折衷方案, <code>Promise.then &gt; MutationObserver &gt; setImmediate &gt; setTimeout 0</code></li> </ul> <p><strong>一句话总结</strong>:将回调作为异步任务,添加到(微/宏)任务队列,在当前调用栈清空后再执行。</p> <h2>对nextTick这个词的理解</h2> <p>对于<strong>tick</strong>我的理解是:<code>每次从调用栈开始有函数帧,直到调用栈被清空为止的过程</code>,这个过程可能是:</p> <ul> <li>页面初始加载时<strong>同步脚本执行</strong>的过程</li> <li>也可能是任何一个<strong>异步任务回调执行</strong>的过程</li> </ul> <p>对于<strong>nextTick(cb)</strong>:回调函数cb不在当前调用栈执行期间立即执行,而是被立即添加在任务队列中,在当前调用栈清空后执行。</p> <p>使用nextTick的目的:必须等待当前调用栈的后续代码执行完,才能执行回调,例如这种情况:回调函数中,需要依赖上一个调用栈操作后的某些状态。</p> <p><strong>举个例子:</strong></p> <p>画一个 echarts 图表,希望根据数据的长度来动态调整图表的宽度</p> <pre><code>.. &lt;template&gt; &lt;div id="chart" :style='{width:chartWidth,height:"200px"}' &lt;/template&gt; ... this.chartWidth = getWidthByData(data) this.nextTick(()=&gt;{ let chart= echarts.init(document.getElementById('chart')) chart.setOption({...}) //echarts渲染 }) </code></pre> <p>宽度属性chartWidth存在vue data中,由于vue data是<code>响应式</code>的,变更data值后,div#chart的宽度并不是立即变更的,中间存在一系列过程:</p> <ul> <li>chartWidth 属性上的 descriptor <code>setter</code> 向其依赖的(vue组件的<code>renderWatcher</code>)发布更新</li> <li>watcher 的更新也是一个<strong>异步</strong>过程(queueWatcher,通过nextTick来调度)</li> </ul> <p>因此在chartWidth变更后,对应的dom宽度不是立即更新的,此时如果立即执行echarts的渲染工作,会导致echarts不能按照最新宽度来渲染。</p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/nexttick/#post-comment/</comments>
</item>
<item>
<title>Javascript & 异步机制</title>
<link>https://www.scarsu.com/event_loop/</link>
<guid isPermaLink="true">https://www.scarsu.com/event_loop/</guid>
<description>长文 + 动图 + 实例,试图解释清楚:Javascript Event Loop如何调度异步任务</description>
<pubDate>Mon, 08 Jun 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>带着问题看这篇文章</h2> <ul> <li>我们写的各种回调什么时候执行?按照什么顺序执行?</li> <li>setTimeout(cb,0)和Promise.resolve().then(cb)谁的回调先执行?</li> <li>Javascript的单线程是如何实现异步并发的?</li> <li>Event Loop到底是如何调度任务的?</li> <li>如何利用RAF优化性能?</li> <li>下面这段代码输出是什么?回答不对的朋友,看完这篇文章也许你的思路就会清晰~</li> </ul> <pre><code>console.log(1); setTimeout(() =&gt; { console.log(2); Promise.resolve().then(() =&gt; { console.log(3); }); }); new Promise((resolve, reject) =&gt; { console.log(4); resolve(5); }).then((data) =&gt; { console.log(data); }); setTimeout(() =&gt; { console.log(6); }); console.log(7); // 结果:1475236 </code></pre> <h2>JS Runtime 的几个概念</h2> <h3>call stack 调用栈</h3> <ul> <li>定义:调用栈是浏览器的JavaScript解释器追踪<strong>函数执行流</strong>的一种机制,函数调用形成了一个由若干帧组成的栈。(栈的特点是后进先出)</li> <li>作用:通过调用栈,我们能够追踪:哪个函数正执行;执行的函数体中又调用了哪个函数;以及每一帧的上下文+作用域</li> <li>机制: <ul> <li>每调用一个函数,就把该函数添加进调用栈并执行</li> <li>如果正在调用的函数还调用了其他函数,把新函数也添加到调用栈中,立即执行</li> <li>执行完毕后,解释器会将函数清除出栈,继续执行当前执行环境下剩余的代码</li> <li>当分配的调用栈被占满时,会引发“<strong>Stack Overflow堆栈溢出</strong>”错误</li> </ul> </li> </ul> <h3>heap 堆</h3> <p><strong>堆</strong>一大块内存区域(通常是非结构化的),对象被分配在堆中</p> <h3>task queue 消息队列</h3> <p>JS运行时包含了一个<strong>消息队列</strong>,每个消息队列关联着一个用于处理这个消息的回调函数。(队列的特点是先进先出)</p> <ol> <li>当调用栈为空时,event loop会消息队列中的下一个消息</li> <li>被处理的消息被移出队列,</li> <li>消息被作为参数调用与之关联的回调函数</li> <li>同时为该函数调用向调用栈添加一个新的栈帧</li> <li>调用栈再次为空时,event loop会重复1-4步骤</li> </ol> <p>通常,task queue中的任务被称为:<strong>macrotask 宏任务</strong>.</p> <p>以下几种异步API的回调属于<strong>宏任务</strong>:</p> <ul> <li>setTimeout</li> <li>MessageChannel</li> <li>postMessage</li> <li>setImmediate</li> </ul> <h3>Single Thread 单线程</h3> <ul> <li>单线程 = 单调用栈 = one thing at a time,不能并发,一次只能做一件事</li> <li>为什么单线程能实现异步和并发?</li> <li>因为单线程指的是js runtime</li> <li>而浏览器和Node提供了API,使我们可以调用其他线程去做并发的异步任务,例如网络请求、DOM、setTimeout</li> </ul> <h3>Non-blocking 非阻塞</h3> <ul> <li>blocking:阻塞,是指浏览器在等待耗时长的代码(eg.网络请求,I/O)期间,不能处理任何其他事情,包括用户响应。</li> <li>解决阻塞的方法:异步任务</li> <li>异步任务怎么实现的?依赖的就是<strong>异步API</strong>和<strong>event loop事件循环</strong></li> <li>JavaScript的事件循环模型与许多其他语言不同的一个非常有趣的特性是,它<strong>永不阻塞</strong>,所以当一个应用正等待一个异步任务时,它仍然可以处理其它事情,比如用户输入。(由于历史原因有一些<strong>例外</strong>,如 <code>alert</code> 或者<code>同步 XHR</code>,但应该尽量避免使用它们,<a>例外的例外也是存在的</a>(但通常是实现导致的错误而非其它原因)。</li> </ul> <h3><strong>不被抢占</strong></h3> <p>每个消息被完整的执行后,其他消息才会被执行。</p> <p>优点:当一个函数执行时,它不会被抢占,只有在它运行完毕后才会去运行其他代码,才能修改这个函数操作的数据。</p> <p>缺点:当一个消息需要太长时间才能处理完,浏览器就无法处理用户交互,eg.滚动和点击,这也是性能较差的网页“卡顿现象”的原因。</p> <p>因此良好的操作方式是:缩短单个消息处理时间,在可能的情况下尽量将一个消息裁剪成多个消息。以保证浏览器 <code>60 frames per second</code> 的流畅渲染,即每个消息处理时间 &lt; 1000ms/60=16ms,</p> <h2>Event Loop 事件循环</h2> <p><strong>event loop是一个执行模型,在不同的地方有不同的实现。浏览器和NodeJS基于不同的技术实现了各自的Event Loop。</strong></p> <ul> <li>浏览器的Event Loop模型是在<a>html5的规范</a>中明确定义的,具体的实现由浏览器厂商来做。</li> <li>NodeJS的Event Loop是基于libuv实现的。可以参考Node的<a>官方文档</a>以及libuv的<a>官方文档</a>。</li> </ul> <h3><strong>浏览器EventLoop运行机制(不考虑microtask)</strong></h3> <ul> <li>所有同步任务都在<strong>主线程</strong>上执行,形成一个<strong>call stack</strong>调用栈</li> <li>可以通过<strong>浏览器API</strong>调用 运行在其他线程的<strong>异步任务</strong></li> <li>主线程之外,存在一个待处理消息的<strong>消息队列task queue</strong>。每一个消息都关联着一个用以处理这个消息的回调函数。</li> <li>当主线程调用栈中的所有同步任务执行完毕,系统就会读取task queue,取最先进的消息作为参数,将其关联的回调函数放入主线程调用栈中执行</li> </ul> <h3><strong>添加消息</strong></h3> <ul> <li>浏览器中,如果一个事件有事件监听器,事件被触发后,一个消息就会被添加到消息队列中。</li> <li>除了事件,浏览器提供的其他API,例如setTimeout、xhr等异步任务,都会在任务结束后向消息队列添加消息</li> </ul> <h3><strong>setTimeout(fn,n)</strong></h3> <ul> <li><code>setTimeout</code> 中的第二个参数n是指 消息被加入消息队列的最小延迟</li> <li>因此,不是保证回调在n毫秒内必须执行,而是保证回调在n毫秒之后被添加到消息队列,具体什么时候执行,取决于消息队列中待处理的消息 和 调用栈中已有的函数。</li> <li><strong>零延迟</strong>:<code>setTimeout 0</code> 的作用:将回调立即放入消息队列,而不是0s内立即执行</li> </ul> <h3>debug 一个 demo</h3> <pre><code>// demo function bar() { debugger; console.log("bar"); foo(); } function foo() { debugger; console.log("foo"); setTimeout(function () { debugger; console.log("setTimeout"); }, 1000); } (function all() { debugger; console.log("anounymous"); bar(); })(); </code></pre> <p><img src="/images/event-loop/Untitled.png" alt="" /></p> <p><img src="/images/event-loop/Untitled%201.png" alt="" /></p> <p><img src="/images/event-loop/Untitled%202.png" alt="" /></p> <p><img src="/images/event-loop/Untitled%203.png" alt="" /></p> <p><strong>原理图</strong></p> <p><img src="/images/event-loop/Untitled%204.png" alt="" /></p> <h3>知识延伸:webWorker &amp; 跨运行时通信</h3> <ul> <li>每个 <strong>WebWorker</strong> 、跨域的 **iframe 、**浏览器不同窗口都有各自的运行时,即都有各自的 call stack 、heap、queue。</li> <li>不同的运行时,可以通过 <a>postMessage</a> 方法来通信。</li> </ul> <p><strong>postMessage:</strong></p> <pre><code>// eg. 当一个窗口可以获得另一个窗口的引用时,例如targetWindow = window.opener otherWindow.postMessage(message, targetOrigin, [transfer]); </code></pre> <p>otherWindow:其他窗口的引用:</p> <ul> <li>iframe的contentWindow</li> <li>执行window.open返回的窗口对象</li> <li>通过window.frames获取到的子frame窗口对象</li> </ul> <p>message:要发送到其他窗口的数据,会被<a>结构化克隆算法</a>序列化</p> <p>targetOrigin:用来指定哪些窗口能接收到消息事件</p> <p>transfer:一串和message 同时传递的 <a><code>Transferable</code></a> 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。</p> <p><strong>结构化克隆算法:</strong></p> <p>用于克隆复杂对象</p> <p>不能克隆:Error、Symbol、Function对象、DOM节点</p> <p>不能克隆:属性的描述符、RegExp对象的 lastIndex字段、原型链上的属性</p> <p><strong>Transferable对象:</strong></p> <p>一个抽象接口,代表可以在不同可执行上下文中传递的对象。(抽象:没有定义任何属性和方法)</p> <p>不同执行上下文:例如主线程和webworker之间。</p> <p>ArrayBuffer 、MessagePort 和 ImageBitmap 实现于此接口。</p> <p><strong>接收消息:</strong></p> <pre><code>window.addEventListener("message", receiveMessage, false); function receiveMessage(event) { // event.data:传递来的对象 // event.origin:消息发送方窗口的origin // event.source:对消息发送窗口的引用 } </code></pre> <h2>UI Rendering Task &amp; 性能优化</h2> <h3>浏览器渲染 - Rendering Task步骤</h3> <ul> <li>requestAnimationFrame API(在chrome,火狐,符合WEB标准)</li> <li>style calculation 计算样式</li> <li>layout 计算布局</li> <li>paint 实际渲染像素数据</li> <li>requestAnimationFrame API(在edge,safari)</li> </ul> <h3><strong>render blocking 渲染阻塞</strong></h3> <p>具体来讲,如果js runtime 的 call stack 一直不能清空,例如event loop将一个耗时的回调放进了call stack,会导致浏览器主线程被占用,无法执行render相关的工作,用户交互的事件也被添加在消息队列等待调用栈清空得不到执行,因此无法响应用户的操作,造成阻塞渲染的“卡顿”现象。</p> <h3>60FPS</h3> <p>在event loop处理消息队列时,我们提倡要缩短单个消息处理时间,在可能的情况下尽量将一个消息裁剪成多个消息,rendering task 可以在消息之间执行,以保证保证UI Rendering调用的频率能达到 <code>60 frames per second</code> (UI Rendering Task执行次数通常是每秒60次,但在大多数遵循W3C建议的浏览器中,回调函数执行次数通常与浏览器屏幕刷新次数相匹配。),即每次event loop处理消息执行回调所占用的时间 小于 16.67 毫秒。</p> <h3>demo1:</h3> <p>看下面这段代码,先 append 一个元素再设置display=none去隐藏这个元素,<strong>不必担心</strong>这个元素会闪现,因为这两行代码会在某一次event loop中执行,只有这两行代码执行完,并且清空了当前调用栈,才有可能执行下一次UI Render task</p> <pre><code>document.body.appendChild(el); el.style.display = "none"; </code></pre> <h3>demo2:</h3> <p>下面这段代码,重复的显示隐藏一个元素,看起来开销很大,但其实在RenderingTask期间,只会取最终结果来渲染,</p> <pre><code>button.addEventListener ('click,()=&gt;{ box style. display='none'; box style. display ='block'; box style. display ='none'; box style. display ='block'; box style. display='none'; box style. display ='block'; box style. display ='none'; box style. display ='block'; box style. display ='none'; }) </code></pre> <h3>requestAnimationFrame</h3> <ul> <li>简称RAF,是一个web api,要求浏览器在下一次重绘之前调用指定的回调函数,通常用于执行动画</li> <li>通过RAF,使浏览器可以在单次回流和重绘中优化处理并发动画,每次UI刷新之前执行RAF,使动画帧率更高</li> <li>当requestAnimationFrame() 运行在后台标签页或者隐藏的<code>&lt;iframe&gt;</code> 里时,requestAnimationFrame() 会被暂停调用以提升性能和电池寿命</li> </ul> <p>demo1:requestAnimationFrame优化动画的一个例子</p> <pre><code>// 使用RAF function callback() { moveBoxForwardOnePixel(); requestAnimationFrame(callback); } callback(); // 使用setTimeout function callback() { moveBoxForwardOnePixel(); setTimeout(callback, 0); } </code></pre> <p>效果:</p> <p><img src="/images/picgo/preview.gif" alt="" /></p> <p>demo2:用RAF控制动画执行顺序,需求是box元素的水平位置变化:1000→500</p> <pre><code>button addEventListener ('click,()=&gt;{ box.style.transform = 'translateX(1000px)' box.style.transition= 'transform 1s ease-in-out' box.style.transform = 'translateX(500px)' }) //由于上述代码会一起执行, //因此渲染时,1000px会被忽略,浏览器会取500作为最终值,在下一帧渲染, //因此上述代码的效果是:元素位移0-&gt;500 //换一种写法 button addEventListener ('click,()=&gt;{ box.style.transform = 'translateX(1000px)' box.style.transition= 'transform 1s ease-in-out' requestAnimationFrame(()=&gt;{ box.style.transform = 'translateX(500px)' }) }) // 上述代码,1000的初始值是有效的, //但是在下一次的rendering task期间,由于RAF先执行,因此500将1000覆盖 //最终渲染的效果还是元素位移:0-&gt;500 //如何令500在下下一次渲染再生效?嵌套调用RAF button addEventListener ('click,()=&gt;{ box.style.transform = 'translateX(1000px)' requestAnimationFrame(()=&gt;{ requestAnimationFrame(()=&gt;{ box.style.transition= 'transform 1s ease-in-out' box.style.transform = 'translateX(500px)' }) }) }) </code></pre> <h2>可视化:event loop和rendering</h2> <h3>理想的状态</h3> <p><img src="/images/event-loop/Untitled%205.png" alt="" /></p> <h3>setTimeout的浪费</h3> <p>间隔调用setTimeout的效果:导致浪费</p> <p><img src="/images/event-loop/Untitled%206.png" alt="" /></p> <p>以前的动画仓库的处理方式:<code>setTimeout(animFrame, 1000/60)</code></p> <p>但是这种处理方式不稳定,可能会不准确,因为</p> <p><img src="/images/event-loop/Untitled%207.png" alt="" /></p> <p><img src="/images/event-loop/Untitled%208.png" alt="" /></p> <h3>RAF的稳定有序状态</h3> <p><img src="/images/event-loop/Untitled%209.png" alt="" /></p> <h2>MicroTask 微任务</h2> <p><strong>微任务,microtask,也叫jobs。</strong></p> <h3>微任务 异步类型</h3> <p>一些异步任务执行完成后,其<strong>回调</strong>会依次进入microtask queue,等待后续被调用,这些异步任务包括:</p> <ul> <li><strong>Promise.then</strong></li> <li>MutationObserver</li> <li>process.nextTick (Node独有)</li> <li>Object.observe</li> </ul> <h2>⭐event loop运行机制(含microtask)</h2> <p>event loop中任务的执行顺序:</p> <ol> <li>同步代码执行,直至调用栈清空</li> <li>microtask:调用栈清空后,优先执行<strong>所有</strong>的microtask,如果有新的microtask,**继续执行新microtask,**直至microtask queue清空</li> <li>task queue:执行task queue第一个任务,后续的task暂不处理</li> <li>每当调用栈清空后,重复2-3步骤</li> </ol> <p><strong>两个重点:</strong></p> <ul> <li>微任务阻塞浏览器:如果执行微任务期间,不停的有新的微任务,会导致浏览器阻塞</li> <li>微任务的执行会因为JS堆栈的情况有所不同,要根据<strong>调用栈是否清空</strong>去判断微任务是否会执行。</li> </ul> <p>一个直观的例子:</p> <pre><code>Promise.resolve().then(() =&gt; { console.log("microtask 1"); }); Promise.resolve().then(() =&gt; { console.log("microtask 2"); }); console.log("sync code"); setTimeout(() =&gt; { console.log("macro task 1"); Promise.resolve().then(() =&gt; { console.log("microtask 3"); }); }, 0); setTimeout(() =&gt; { console.log("macro task 2"); }, 0); //结果: //sync code 同步代码优先执行 //microtask 1 同步代码执行完后,调用栈清空,优先执行 microtask //microtask 2 同上 //macro task 1 调用栈清空,microtask queue清空,此时可以执行一个位于队首的macro task,执行期间新增一个microtask //microtask 3 调用栈清空后,由于存在microtask,因此优先执行microtask //macro task 2 最后执行macro task,清空task queue </code></pre> <p><strong>流程图</strong> <img src="/images/event-loop/Untitled%2010.png" alt="" /></p> <p><strong>demo1:调用栈未清空,不执行microtask</strong></p> <p>在控制台中执行一段代码,会当做同步代码来处理。listener1执行后,微任务队列+1,但是因为是同步执行的代码,所以会立即执行listener2,微任务队列+1,所以顺序是<code>listener1,listener2,microtask1,microtask2</code></p> <p><img src="/images/event-loop/Untitled%2011.png" alt="" /></p> <p><strong>demo2:调用栈清空后,microtask 优先于 macro task执行</strong></p> <p>同步执行两个setTimeout,会将 listener1和listener2加入到task queue,同步代码执行就结束。先执行listener1,将microtask1加入微任务队列,listener1执行完后,调用栈清空,即使这时候task queue还有listener2,也会先执行所有微任务,将所有微任务清空后,再执行listener2,因此输出顺序是 <code>listener1,microtask1,listener2,microtask2</code></p> <p><img src="/images/event-loop/Untitled%2012.png" alt="" /></p> <p><strong>demo3:同demo2</strong></p> <p>用户点击事件</p> <p>由于点击事件会被添加到task queue,因此,这个 demo3 的结果和 demo2 结果相同</p> <p><img src="/images/event-loop/Untitled%2013.png" alt="" /></p> <p><strong>demo4:同demo1</strong></p> <p>js调用click()事件</p> <p>由于是在代码中手动执行click,所以会同步执行两个listener,因此demo4和demo1结构相同。</p> <p><img src="/images/event-loop/Untitled%2014.png" alt="" /></p> <p><strong>demo5:micro 优先于 macro执行</strong></p> <p><img src="/images/event-loop/Untitled%2015.png" alt="" /></p> <p><strong>demo6:综合实例</strong></p> <pre><code>// 浏览器中执行 console.log(1); setTimeout(() =&gt; { console.log(2);// callback2,setTimeout属于宏任务 Promise.resolve().then(() =&gt; { console.log(3)// callback3,Promise.then属于微任务 }); }); new Promise((resolve, reject) =&gt; { console.log(4)// 这里的代码是同步执行的 resolve(5) }).then((data) =&gt; { console.log(data);// callback5,Promise.then属于微任务 }) setTimeout(() =&gt; { console.log(6);// callback6,setTimeout属于宏任务 }) console.log(7); // 结果:1475236 // 逻辑: 147是同步执行,同步代码执行完后的queue: task queue:callback2,callback6 microtask:callback5 此时调用栈已清空,优先执行微任务callback5,调用栈清空 再执行callback2,调用栈清空 此时的queue: task queue:callback6 microtask:callback3 优先执行微任务callback3,调用栈清空 最后执行callback6 </code></pre> <p><img src="/images/event-loop/Untitled%2016.png" alt="" /></p> <p><strong>demo7:综合实例</strong></p> <pre><code>console.log('main start'); setTimeout(() =&gt; { //cb1 console.log('1'); Promise.resolve().then(() =&gt; { //cb2 console.log('2') }); }, 0); Promise.resolve().then(() =&gt; { //cb3 console.log('3'); Promise.resolve().then(() =&gt; { //cb4 console.log('4') }); }); console.log('main end'); //结果: // main start,main end,3412 main start 和 main end同步执行,同步代码执行完后,调用栈清空,此时的queue: task queue:cb1 microtask queue:cb3 先执行微任务cb3,执行完后,调用栈清空,此时的queue: task queue:cb1 microtask queue:cb4 先执行微任务cb4,执行完后,调用栈清空,此时的queue: task queue:cb1 microtask queue:空 最后执行cb1,然后执行cb2 </code></pre> <p><img src="/images/event-loop/Untitled%2017.png" alt="" /></p> <p><strong>rendering task的执行顺序</strong> 在上面的event loop执行机制中,没有提到rendering task,是因为rendering task是由浏览器自行去决定何时运行的,与当前设备的屏幕刷新率等因素相关,确定的是:</p> <ul> <li>RAF 在 rendering task 初始期间执行</li> <li>如果定义了多个 RAF 回调,会被加入到 <code>Animation queue</code>中,在UI Rendering 期间,会清空 Animation queue,与 microtask 不同的是,如果清空 Animation queue 期间,有新的 animation task 被加入到 queue 中,此次 rendering task 执行期间,不会处理新的 animation task。</li> </ul> <p>macrotask、microtask、animation task的区别,可以看在下面的动图中横向对比:</p> <p><img src="/images/event-loop/raf.png" alt="" /></p> <p><img src="/images/picgo/event_loop.gif" alt="" /></p> <h2>参考资料</h2> <ul> <li><a>HTML规范</a></li> <li><a>NodeJS Event Loop 文档</a></li> <li><a>mdn相关文档</a></li> <li><a>Jake Archibald在JSConf.Asia的演讲视频【In The Loop】,很值得看:</a></li> <li><a>Philip Roberts在JSConf的演讲视频【What the heck is the event loop anyway】,很值得看</a></li> <li><a>Philip Roberts做的Event Loop可视化网站</a></li> <li><a>JS Runtime运行时 - MDN</a></li> </ul> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/event_loop/#post-comment/</comments>
</item>
<item>
<title>4点起床:舒适而高效的作息方式</title>
<link>https://www.scarsu.com/3-8lifestyle/</link>
<guid isPermaLink="true">https://www.scarsu.com/3-8lifestyle/</guid>
<description>这是一本我用两周地铁通勤时间看完的书,虽然这本书没什么系统性,废话也比较多,但是看完这本书,确实对我的生活有所影响,让我养成了早睡早起的习惯,这篇文章总结一下书中的(我认为的)精华。</description>
<pubDate>Thu, 21 May 2020 00:00:00 GMT</pubDate>
<content:encoded><p><img src="/images/read/3-8lifestyle.jpg" alt="" /></p> <h2><code>REM</code> 睡眠</h2> <p><a><strong>REM : rapid eye movement</strong></a>,快速眼动睡眠,是人睡眠周期的一个阶段。</p> <p><code>REM</code>即<code>快速眼动睡眠</code>睡眠阶段中,身体肌肉放松,单紧闭的眼皮下眼球在来回运动,这个阶段是联系'清醒状态'和'意识体温低下的睡眠状态'的桥梁,为人们“睡醒”做了准备。</p> <p><code>Non-REM</code>、<code>NREM</code>是<code>非快速眼动睡眠</code>,这个阶段是大脑休息的时间,也就是深度睡眠阶段,这个阶段是睡眠中最重要的阶段,也是睡眠效率最高的阶段。</p> <h2>睡眠周期</h2> <p>通常一个成年人的睡眠是这样的:</p> <ul> <li><code>NREM</code>与<code>REM</code>交替出现,交替一次称为一个<code>睡眠周期</code></li> <li>两种循环往复,每夜通常有 <code>4~5个睡眠周期</code>,每个周期90~110分钟。</li> </ul> <p>国际睡眠医学将<code>一个睡眠周期</code>分为五个阶段:</p> <ul> <li>入睡期</li> <li>浅睡期</li> <li>熟睡期</li> <li>深睡期</li> <li>快速眼动期:</li> </ul> <p><img src="/images/read/rem.png" alt="Sleep Cycle" /></p> <p>上图是对一个睡眠周期的近似描述,<code>W</code>是Wake清醒状态,<code>R</code>是<code>REM</code>,<code>N</code>代表<code>NREM</code>非快速眼动睡眠,<code>N3</code>代表最深度的睡眠。</p> <p>由图中可以看出,一个90分钟的睡眠周期中,<code>深度睡眠</code>大约占到了整个睡眠周期的一半以上。</p> <h2>依照睡眠周期来休息</h2> <p>我们在深睡阶段是轻易叫不醒的,如果在深睡阶段被吵醒,身体和大脑从深度睡眠中被突然拉出,通常会使身体和大脑<strong>产生不适</strong>,即使睡眠时间总和很长,也会有没睡好的感觉。</p> <p>相反,如果在浅睡眠阶段,清晨的阳光照射、晨起的鸟叫都能轻易的把我们从快速眼动期唤醒,由于大脑已经经历过处在睡眠周期中间的深度睡眠,得到了休息,这个时候的清醒,身体和大脑都会<strong>感到舒适</strong>。</p> <p>因此,按照睡眠周期的模式来休息至关重要。</p> <p>当然,每个人的睡眠周期不可能都是严格的90分钟,因此也要掌握好自己的身体规律。</p> <p>比如你入睡后一段时候,<strong>开始翻身</strong>或者<strong>容易被吵醒</strong>,这个时候很大概率就是你处在<strong>睡眠周期末尾</strong>的<code>快速眼动阶段</code>。</p> <p>掌握自己身体的睡眠周期,同时让自己处于可以自然醒的环境,例如靠近窗边睡眠,让大自然的声音光线带着身体自然醒,就可以得到最<strong>舒适高效</strong>的睡眠。</p> <p>高效的睡眠也就意味着可以在拥有舒适睡眠的同时,缩短睡眠时间,<strong>可利用的时间</strong>也就增多了,这就是书中作者所提倡的观点。</p> <h2><code>3-8作息</code></h2> <p>前面睡眠周期介绍了如何利用缩短睡眠时间,来提升可利用时间,而<code>3-8作息法</code>要介绍的,是在相同睡眠时间的情况下,如何<strong>提升可利用时间的效率</strong>。</p> <p>答案就是<strong>早起</strong>。</p> <p><code>3-8作息法</code>是指:将一天时间分为3块,上午8小时,下午8小时,晚上8小时。也就是4点起床,下午8点休息。</p> <h2>为什么要早起</h2> <p>其实<code>3-8</code>模式,强调的起早,是让晚上的时间去置换早上的时间。</p> <p>那么为什么要早起呢,书中用大量的篇幅介绍了早起的好处。</p> <p>例如,从生理学的角度来说,人的身体会分泌两种令人“精力充沛”的荷尔蒙,<strong>肾上腺素、肾上腺皮质类脂醇</strong>,这两种荷尔蒙在早上分泌的量比晚上分泌的多,大概是3倍左右,因此早上大脑的<strong>效率</strong>比晚上的高,早上的大脑更加清醒,精力更加旺盛。</p> <p>另一方面,<strong>日出而作,日落而息</strong>是人类进化几千年形成的习惯,只是到了现代,人们在夜里可以做的事情越来越多,加班的情况也越来越多,很多人的睡眠时间越来越晚,甚至有些自由工作制的公司里,很多人都是<code>11-12</code>的作息方式,在正午起床,在月影朦胧时才睡去,这是违背大自然和人体规律的。</p> <p>当你利用睡眠周期规律,养成早睡早起的习惯后,会发现一些<strong>美妙</strong>的事情,比深夜的手机、视频、夜宵、电脑、小说更加精彩,比如:</p> <ul> <li>光线、鸟叫带来的自然醒的舒适</li> <li>清晨你所在城市的样貌,和形形色色早起的人</li> <li>适宜的晨间光照,和空气中适宜的湿度</li> <li>在空空荡荡的地铁上安然看书的舒适</li> <li>...</li> </ul> <h2>早起能做什么</h2> <p>之前发朋友圈晒了一张等首发地铁的图片,有朋友问,“起那么早干什么?”</p> <p><img src="/images/picgo/morning.png" alt="起那么早干什么?" /></p> <p>其实,一切你想做的事情,都可以放在早上完成(除了看星星看月亮这种)。</p> <p>书中举了很多例子,比如</p> <ul> <li>悠闲的享受早餐</li> <li>散步、运动(运动有助于缓解压力)</li> <li>冲热水澡</li> <li>晨间社交</li> <li>看书学习</li> <li>发展副业</li> <li>发展兴趣爱好,做内因驱动的事情</li> <li>...</li> </ul> <h2>找不到自己早起想做的事?</h2> <p>书中还有一个观点令我印象深刻,如果你找不到自己想做的事情呢?</p> <p>就不需要早起,或者陷入迷茫吗?</p> <p>我把作者的答案摘录在这里,希望对找不到追求的人,能有所启发:</p> <blockquote> <p>我究竟想做什么呢?</p> <p>当然,我们可以埋头苦干,让自己没时间胡思乱想。但我建议大家多去受点刺激。 学习、信息、人......这些都是刺激。 接受的刺激越多,自然会产生这样那样的憧憬:“我想成为那样的人!”“我想做那样的工作!” 有些人能找到明确的目标,有些人则会发现目标的模糊轮廓。</p> <p>无论你属于上述哪种情况,都能在不断接受刺激(我把它称为“打击”)的过程中,逐渐将自己的目标具象化,这才是重中之重。</p> </blockquote> <hr /> <p>&lt;small&gt;人的一生也许都在自我探索&lt;/small&gt;</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/3-8lifestyle/#post-comment/</comments>
</item>
<item>
<title>如何学习源码、如何高效学习一个新知识</title>
<link>https://www.scarsu.com/how_to_learn_wheels_source_code/</link>
<guid isPermaLink="true">https://www.scarsu.com/how_to_learn_wheels_source_code/</guid>
<description>学习轮子源码是提升自我技术的有效途径,也是高阶程序员的必备技能。这套方法也适用于绝大多数知识体系的学习~</description>
<pubDate>Thu, 14 May 2020 00:00:00 GMT</pubDate>
<content:encoded><p><img src="/images/learning2.png" alt="" /></p> <h2>什么时候看源码</h2> <p>对于复杂的开源项目,一上来就看源码是不合理的,可能导致效率低下,适得其反。</p> <p>往往看一个开源项目源码前,我们会经历以下几个阶段:</p> <ul> <li>刚接触一个开源项目,跟着官方文档,运行一些demo实例</li> <li>在工作项目中应用、实践、踩坑</li> <li>能够熟练使用,了解它的一些设计思想,但是还不知道设计原理</li> </ul> <p>经历过以上几个阶段后,就是开始看源码的最佳时期</p> <h2>如何看源码</h2> <h3>1. 检索收集信息</h3> <p>如果你不是一个走在行业最前端的人,那么你踩过的坑,一定有前人踩过。你想学的东西,也一定有前辈早已研究透彻。</p> <p>如果一定有人走过我们要走的路,那么我们就应该利用好这个互联网大世界,在踏出征途前,先从无数优秀前辈身上,汲取一些“旅行攻略”。</p> <p>不光是学习源码,对于绝大多数我们即将要做的事情来说,<strong>检索收集信息</strong>都应该是第一步,甚至要放在计划制定之前。</p> <p>学习开源项目源码之前,带着它的名称 + “如何学习” 作为关键词,检索信息,对于我们程序员,甚至可以先搜一搜这个项目相关的面试题。</p> <p>这有助于我们用最短的时间,去了解这个项目最值得我们学习的地方,让我们更加清楚我们想要什么;也有助于我们收集学习资料,提高学习效率。</p> <h3>2. 宏观了解</h3> <p>从全局的视角去了解整个项目,这有助于形成整体的知识结构,上来就从细微处硬啃,效率极低。</p> <p>可以从以下几个方面着手:</p> <ul> <li>项目的背景、项目作者亲述的背后的故事、项目纪录片</li> <li>项目解决的问题</li> <li>浏览代码仓库,了解其Issue报告规则、PR规则、贡献规则、开发环境...</li> <li>源码的目录结构</li> <li>项目的元数据。例如package.json,看看项目的依赖/脚本</li> <li>构建方式,运行环境,入口,构建输出</li> <li>项目的历史版本和当前版本的区别,未来的发展方向</li> <li>项目的技术选型:项目的技术依赖,优化方案,类型控制,格式检查,代码规范,API接口设计,单元测试等</li> </ul> <h3>3. 重点切入</h3> <p>有了你对项目的熟练使用,有了对项目设计思想的了解,有了对项目整体的认知,那么我们就可以开始带着问题细啃源码,去了解这个项目的重点的实现原理。</p> <ul> <li>比如这个项目最重要的核心思想,是如何实现的;</li> <li>比如你在实践中经常踩坑的点,是如何产生的;</li> <li>比如那道最高频的面试题,面试官到底想考我们什么;</li> <li>比如那些你在实践中经常用到的特性,是如何实现的</li> <li>...</li> </ul> <p>带着这些切入点去看源码,逐一击破,最终就可以建立一个完整的知识体系。</p> <h3>4. 模仿实现</h3> <p>当掌握了项目的宏观结构 + 重点特性的实现原理后。就可以开始自己动手,尝试实现一个类似的简单小项目。</p> <p>这个项目不需要完整的重复造轮子,不需要完美的关注细节,只需要把我们所学到的结构应用其中,把关键特性模仿实现即可。</p> <p>这个过程有助于我们查漏补缺,在自己动手踩坑的过程当中,把学到知识融会贯通。</p> <h3>5. 开源贡献</h3> <p>当我们掌握了知识之后,根据<strong>费曼</strong>的<strong>以教为学</strong>的方法,我们最后应该做的就是<code>输出</code>。比如:</p> <ul> <li>输出学习总结</li> <li>反馈项目社区:参与共建,做开源贡献,解决issue,做插件开发</li> </ul> <h2>举一反三</h2> <p><code>这套方法其实适用于绝大多数知识体系的学习</code></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/how_to_learn_wheels_source_code/#post-comment/</comments>
</item>
<item>
<title>Vue消息插件开发 & npm发布</title>
<link>https://www.scarsu.com/vue_message_plugin/</link>
<guid isPermaLink="true">https://www.scarsu.com/vue_message_plugin/</guid>
<description>手写一个基于 Vue.js 的消息插件,按照 ElementUI / message的接口实现</description>
<pubDate>Thu, 14 May 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>vue-message-plugin</h2> <ul> <li>一个基于 Vue.js 的消息插件,按照 ElementUI / message的接口实现</li> <li><a>插件地址</a></li> <li><a>源码地址</a></li> </ul> <p><img src="/images/picgo/vue-message-plugin.gif" alt="vue-message-plugin预览" /></p> <h2>源码目录结构</h2> <p><img src="/images/vue-message-plugin.png" alt="vue-message-plugin源码目录结构" /></p> <h2>package.json配置</h2> <pre><code>{ "name": "vue-message-plugin", "version": "1.0.0", "description": "A message plugin based on Vue.js which works like ElementUI/Message.", "author": "scarsu &lt;scarsu001@gmail.com&gt;", "private": false,//用于公开发布 "license": "MIT", "main": "dist/vue-message-plugin.js",//npm引用入口 "repository": {//仓库 "type": "git", "url": "https://www.github.com/scarsu/vue-message-plugin" }, "scripts": { "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot", "build": "cross-env NODE_ENV=production webpack --progress --hide-modules" }, "dependencies": { "vue": "^2.5.2" }, "keywords": [ "vue", "toast", "code", "vue plugin", "message", "vue-message-plugin" ], "devDependencies": { "babel-core": "^6.26.0", "babel-loader": "^7.1.2", "babel-preset-env": "^1.6.0", "babel-preset-stage-3": "^6.24.1", "cross-env": "^5.0.5", "css-loader": "^0.28.7", "file-loader": "^1.1.4", "html-webpack-plugin": "^2.30.1", "vue-loader": "^13.0.5", "vue-template-compiler": "^2.4.4", "webpack": "^3.6.0", "webpack-dev-server": "^2.9.1" }, "engines": { "node": "&gt;= 6.0.0", "npm": "&gt;= 3.0.0" }, "browserslist": [ "&gt; 1%", "last 2 versions", "not ie &lt;= 8" ] } </code></pre> <h2>主应用 vue安装插件</h2> <pre><code>import Vue from "vue"; import App from "./App"; import Message from "./lib"; Vue.config.productionTip = false; Vue.use(Message); //Vue.use用于安装插件,插件中必须包含install方法,必须在创建根实例前安装插件 /* eslint-disable no-new */ new Vue({ el: "#app", components: { App }, template: "&lt;App/&gt;", }); </code></pre> <h2>Message/index.js</h2> <pre><code>import Message from "./src/main.js"; export default Message; </code></pre> <h2>Message/src/main.js</h2> <pre><code>/* * 参数 说明 类型 可选值 默认值 * message 消息文字 string / VNode — — * type 主题 string success/warning/info/error info * dangerouslyUseHTMLString 是否将 message 属性作为 HTML 片段处理 boolean — false * customClass 自定义类名 string — — * duration 显示时间, 毫秒。设为 0 则不会自动关闭 number — 3000 * showClose 是否显示关闭按钮 boolean — false * center 文字是否居中 boolean — false * onClose 关闭时的回调函数, 参数为被关闭的 message 实例 function — — * offset Message 距离窗口顶部的偏移量 number — 20 * * 调用 Message 或 this.$msg 会返回当前 Message 的实例。如果需要手动关闭实例,可以调用它的 close 方法。 * * 方法名 说明 * close 关闭当前的 Message */ import message from "./main.vue"; import { isVNode } from "@/utils"; //用于export的对象 const Message = {}; let instances = []; let seed = 0; const types = { success: "success", info: "info", warning: "warning", error: "error", }; //Vue插件必须包含install方法 Message.install = function (Vue) { const Message = Vue.component("message", message); Vue.prototype.$message = function (opt) { // 参数处理 if (typeof opt === "string" || isVNode(opt)) { opt = { message: opt }; } opt.id = "id" + seed++; opt.type = types[opt.type] || types.info; opt.userOnClose = opt.onClose; // message组件实例 let instance = new Message({ data: opt, //将配置选项传入给实例的data }); //处理VNode类型message(使用$slots插槽分发数据 if (isVNode(instance.message)) { instance.$slots.default = [instance.message]; instance.message = ""; } //挂载dom 并 实例的dom加入body中 instance.$mount(); document.body.append(instance.$el); // close方法 instance.close = function () { this.show = false; if (this.userOnClose) this.userOnClose(); }; // 显示 instance.show = true; // 定时隐藏 let duration = opt.duration || 3000; instance.timer = setTimeout(() =&gt; { instance.close(); }, duration); instances.push(instance); // 返回message组件实例 return instance; }; }; export default Message; </code></pre> <h2>isVNode方法</h2> <pre><code>function isVNode(node) { //通过VNode必包含的属性componentOptions来判断 return ( !!node &amp;&amp; typeof node === "object" &amp;&amp; node.hasOwnProperty("componentOptions") ); } </code></pre> <h2>Message/src/main.vue</h2> <pre><code>&lt;!-- * 参数 说明 类型 可选值 默认值 * message 消息文字 string / VNode — — * type 主题 string success/warning/info/error info * dangerouslyUseHTMLString 是否将 message 属性作为 HTML 片段处理 boolean — false * customClass 自定义类名 string — — * duration 显示时间, 毫秒。设为 0 则不会自动关闭 number — 3000 * showClose 是否显示关闭按钮 boolean — false * center 文字是否居中 boolean — false * onClose 关闭时的回调函数, 参数为被关闭的 message 实例 function — — * offset Message 距离窗口顶部的偏移量 number — 20 * * 调用 Message 或 this.$msg 会返回当前 Message 的实例。如果需要手动关闭实例,可以调用它的 close 方法。 * * 方法名 说明 * close 关闭当前的 Message --&gt; &lt;template&gt; &lt;transition name="message-fade"&gt; &lt;div :class="[ 'message', `message-${type}`, center?'is-center':'', customClass]" :style="positionStyle" @mouseenter=stopTimer @mouseleave=startTimer v-if="show"&gt; &lt;slot&gt;//插槽分发v-html数据 &lt;span v-if="message &amp;&amp; !dangerouslyUseHTMLString"&gt;{{message}}&lt;/span&gt; &lt;div v-else v-html="message"&gt;&lt;/div&gt; &lt;/slot&gt; &lt;i v-if="showClose" @click="closeMsg" class="message-close-btn"&gt;x&lt;/i&gt; &lt;/div&gt; &lt;/transition&gt; &lt;/template&gt; &lt;script&gt; export default{ components: {}, data () { //message组件默认数据 return { message: '', type: 'info', dangerouslyUseHTMLString: false, customClass: '', showClose: false, center: false, onClose: null, offset: 20, show: false, timer: null } }, computed: { positionStyle () { return `margin-top:${this.offset}px` } }, watch: {}, created () {}, mounted () {}, methods: { closeMsg () { this.close() }, startTimer () { const _this = this this.timer = setTimeout(() =&gt; { _this.close() }, _this.duration) }, stopTimer () { clearTimeout(this.timer) this.timer = null } } } &lt;/script&gt; &lt;style scoped&gt; .message{ position: relative; margin-top: 15vh; width: 30%; margin: 0 auto; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.3); box-sizing: border-box; min-width: 200px; padding: 20px 40px; border-radius: 10px; } .is-center{ text-align: center; } .message-success{ background-color: #f0f9eb; border-color: #e1f3d8; color: #67c23a; } .message-info{ background-color: #edf2fc; border-color: #909399; color: #909399; } .message-warning{ background-color: #fdf6ec; border-color: #faecd8; color: #e6a23c; } .message-error{ background-color: #fef0f0; border-color: #fde2e2; color: #f56c6c; } .message-fade-enter-active, .message-fade-leave-active { transition: all 0.1s ease-out; } .message-fade-enter-to { opacity: 1; transform: scale(1.2); } .message-fade-leave-to { opacity: 0; transform: scale(0.8); } .message-close-btn{ position: absolute; right: 10px; top: 3px; cursor: pointer; } &lt;/style&gt; </code></pre> <h2>webpack配置</h2> <pre><code>const path = require("path"); const webpack = require("webpack"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const resolve = (dir) =&gt; path.resolve(__dirname, dir); module.exports = { entry: "./src/main.js", //定义webpack的入口文件 output: { //定义webpack的输出 path: path.resolve(__dirname, "./dist"), //输出路径 filename: "vue-message-plugin.js", //输出文件名 libraryTarget: "umd", //把写的library打包成umd文件,把库暴露给当前使用的模块定义系统,同时适用commonJs 模块,AMD模块,也可以导出到 global 下的变量,library指定模块名或变量名 library: "vue-message-plugin", //以库的形式导出入口文件 umdNamedDefine: true, //在 UMD 库中使用命名的 AMD 模块 }, module: { //module选项决定了如何处理项目中的不同类型的模块 rules: [ //array,创建模块时,匹配请求的规则数组。这些规则能够修改模块的创建方式。这些规则能够对模块(module)应用 loader,或者修改解析器(parser)。 { test: /\.css$/, //rule条件:resource,请求文件的绝对路径。它已经根据 resolve 规则解析。(Rule.resource.test 的简写 use: [ //应用于模块的 UseEntries 列表。每个入口(entry)指定使用一个 loader。 "vue-style-loader", "css-loader", ], }, { test: /\.vue$/, loader: "vue-loader", options: { loaders: {}, }, }, { test: /\.js$/, loader: "babel-loader", exclude: /node_modules/, }, { test: /\.(png|jpg|gif|svg)$/, loader: "file-loader", options: { name: "[name].[ext]?[hash]", }, }, ], }, resolve: { //resolve选项能设置模块如何被解析 alias: { //定义 import 或 require 的别名,来确保模块引入变得更简单 vue$: "vue/dist/vue.esm.js", "@": resolve("src"), }, extensions: ["*", ".js", ".vue", ".json"], //自动解析确定的扩展。能够使用户在引入模块时不带扩展 }, devServer: { historyApiFallback: true, //当使用 HTML5 History API 时,任意的 404 响应都可能需要被替代为 index.html noInfo: true, //启用 noInfo 后,「启动时和每次保存之后,那些显示的 webpack 包(bundle)信息」的消息将被隐藏。错误和警告仍然会显示。 overlay: true, //出现编译器错误或警告时,在浏览器中显示全屏覆盖。 open: true, //自动打开浏览器 port: 3100, //设置端口 hot: true, //启用热更新 }, performance: { hints: false, //关闭提示 }, devtool: "#eval-source-map", //原始源代码生成 source map }; if (process.env.NODE_ENV === "production") { module.exports.devtool = "#source-map"; //原始源代码生成 source map module.exports.plugins = (module.exports.plugins || []).concat([ new webpack.DefinePlugin({ "process.env": { NODE_ENV: '"production"', }, }), new webpack.optimize.UglifyJsPlugin({ sourceMap: true, compress: { warnings: false, }, }), new webpack.LoaderOptionsPlugin({ minimize: true, }), ]); } else if (process.env.NODE_ENV === "development") { module.exports.devtool = "#eval-source-map"; module.exports.plugins = (module.exports.plugins || []).concat([ new webpack.DefinePlugin({ //插件:允许在编译时(compile time)配置的全局常量 "process.env": { NODE_ENV: '"development"', }, }), new webpack.optimize.UglifyJsPlugin({ //可以控制项目中 UglifyJS 的版本 sourceMap: true, compress: { warnings: false, }, }), new webpack.LoaderOptionsPlugin({ //用于从 webpack 1 迁移到 webpack 2 minimize: true, }), new HtmlWebpackPlugin({ //简单创建 HTML 文件,用于服务器访问 filename: "index.html", template: "index.html", inject: true, //注入打包的文件 }), ]); } </code></pre> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/vue_message_plugin/#post-comment/</comments>
</item>
<item>
<title>函数式编程</title>
<link>https://www.scarsu.com/functional_programing/</link>
<guid isPermaLink="true">https://www.scarsu.com/functional_programing/</guid>
<description>改变引发错误,最小化改变</description>
<pubDate>Fri, 08 May 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>函数式编程</h2> <ul> <li>函数式编程是一种解决方案简单,功能独立,对作用域外没有任何副作用的<strong>编程范式</strong>。</li> <li><code>INPUT -&gt; PROCESS -&gt; OUTPUT</code></li> <li>函数式编程是一种基于函数计算的软件开发方法。</li> <li>像数学一样,函数在编程中通过输入产生输出。</li> <li>可以通过多种方式组合基本功能来构建越来越复杂的程序。</li> <li>函数式编程式将程序分成小的、可测试的部分</li> </ul> <h2>函数式编程原则</h2> <h3>功能独立,显式声明依赖关系</h3> <p>不依赖程序状态或全局变量,<strong>只依赖于传递给它们的参数进行计算</strong></p> <p>如果函数依赖于一个变量或对象,那么将该变量或对象作为参数直接传递到函数中。</p> <ol> <li>不要更改变量或对象——创建新变量和对象,并在需要时从函数返回它们。</li> <li>声明函数参数——<strong>函数内的任何计算仅取决于参数,而不取决于任何全局对象或变量</strong>。</li> </ol> <h3>有限的副作用</h3> <p>可以严格地限制函数外部对状态的更改导致的状态变化</p> <p>在变量,数组或对象上调用一个函数,这个函数可能会改变对象中的变量或其他东西。 函数式编程的核心原则之一是不改变任何东西,<strong>变化会导致错误</strong>。 如果一个函数不改变传入的参数、全局变量等数据,那么它造成问题的可能性就会小很多。</p> <p>在函数式编程中,改变或变更叫做<strong>mutation</strong></p> <p>这种改变的结果叫做“副作用”(<strong>side effect</strong></p> <p>理想情况下,函数应该是不会产生任何副作用的纯函数(<strong>pure function</strong></p> <h3>纯函数</h3> <p>同一个输入永远能得到同一个输出</p> <h3>限制更改程序状态</h3> <p>避免更改保存数据的全局对象</p> <h2>不改变原数组的 数组方法:</h2> <h3>concat 连接数组</h3> <h3>slice 提取数组一部分(代替splice从数组删除元素</h3> <h3>map 迭代数组返回新数组(callback return 新元素</h3> <h3>filter 迭代数组返回新数组(callback return true/false</h3> <h3>reduce 是 JavaScript 所有数组操作中最通用的方法。</h3> <p>几乎可以用reduce方法解决所有数组处理问题。 filter和map方法不支持对数组中两个不同元素的交互。举个例子,如果你想把数组中的元素拿来比较或者相加,用filter和map是做不到的。 reduce方法允许更通用的数组处理方式,而且filter和map方法都可以当作是reduce的特殊实现。 reduce(acc,cur,idx,arr)</p> <h3>sort排序 会改变原数组:利用concat([])返回新数组排序</h3> <pre><code>var globalArray = [5, 6, 3, 2, 9]; function nonMutatingSort(arr) { return arr.concat([]).sort((a, b) =&gt; a - b); } nonMutatingSort(globalArray); </code></pre> <h3>every方法,检查数组每个元素都通过检验,返回boolean</h3> <h3>some方法,检查数组有元素通过检验,返回boolean</h3> <h2>不改变String的方法:</h2> <h3>split</h3> <h3>toUpperCase</h3> <h3>trim</h3> <h3>+-运算</h3> <h2>函数柯里化</h2> <p>arity是函数所需的形参的数量。函数Currying意思是把接受多个arity的函数变换成接受单一arity的函数。</p> <p>重构函数让它接收一个参数,然后返回接收下一个参数的函数,依此类推。</p> <pre><code>//Un-curried function function unCurried(x, y) { return x + y; } // 柯里化函数 function curried(x) { return function (y) { return x + y; }; } curried(1)(2); // 返回 3 </code></pre> <p>柯里化在不能一次为函数提供所有参数情况下很有用。因为它可以将每个函数的调用保存到一个变量中,该变量将保存返回的函数引用,该引用在下一个参数可用时接受该参数。下面是使用curried函数的例子:</p> <pre><code>// Call a curried function in parts: var funcForY = curried(1); console.log(funcForY(2)); // 打印 3 </code></pre> <p><strong>partial application</strong>的意思是一次对一个函数应用几个参数,然后返回另一个应用更多参数的函数。</p> <pre><code>//Impartial function function impartial(x, y, z) { return x + y + z; } var partialFn = impartial.bind(this, 1, 2); partialFn(10); // 返回 13 </code></pre> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/functional_programing/#post-comment/</comments>
</item>
<item>
<title>正则自检清单</title>
<link>https://www.scarsu.com/dive_into_regular_expression/</link>
<guid isPermaLink="true">https://www.scarsu.com/dive_into_regular_expression/</guid>
<description>正则是程序员必备的效率生产力知识~</description>
<pubDate>Wed, 06 May 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>资源</h2> <ul> <li><a>正则教程</a></li> <li><a>正则可视化</a></li> <li><a>正则实例</a></li> </ul> <h2>备忘录</h2> <p><img src="/images/regexp.png" alt="alt text" /></p> <h2>正则原型<code>test</code>方法</h2> <pre><code>let myString = "Hello, World!"; let myRegex = /Hello/; let result = myRegex.test(myString); </code></pre> <h2>或操作符<code>|</code></h2> <pre><code>let waldoIsHiding = "Somewhere Waldo is hiding in this text."; let waldoRegex = /Waldo/; let result = waldoRegex.test(waldoIsHiding); </code></pre> <h2>正则标志</h2> <ul> <li>标志<code>i</code>:忽略大小写</li> <li>标志<code>g</code>:全局匹配(多次匹配)</li> </ul> <h2>字符串原型方法:<code>match</code></h2> <ul> <li>在字符串上使用<code>.match()</code>方法将返回一个数组,其中包含它匹配的字符串及其捕获组。</li> </ul> <pre><code>"Hello, World!".match(/Hello/); // Returns ["Hello"] </code></pre> <h2>通配符:<code>.</code>(点)</h2> <h2>字符集匹配:<code>[]</code></h2> <pre><code>let vowelRegex = /[aeiou]/gi; let result = quoteSample.match(vowelRegex); </code></pre> <h2>字符集 连字符:<code>-</code> 字符范围</h2> <pre><code>let quoteSample = "The quick brown fox jumps over the lazy dog."; let alphabetRegex = /[a-z]/gi; let result = quoteSample.match(alphabetRegex); </code></pre> <h2>否定字符集:<code>^</code></h2> <ul> <li>/[^1-9]/g 匹配所有非数字字符</li> </ul> <h2><code>+*?^$</code></h2> <ul> <li>+:一次或多次</li> <li>*:0次或多次</li> <li>?:0次或1次</li> <li>字符串开头:^</li> <li>字符串结尾:$</li> </ul> <h2>贪婪匹配 &amp; 惰性匹配</h2> <ul> <li>贪婪匹配:正则默认贪婪匹配,匹配满足表达式的最长部分</li> <li>惰性匹配:匹配满足表达式的最小部分:加?</li> </ul> <pre><code>let text = "&lt;h1&gt;Winter is coming&lt;/h1&gt;"; let myRegex = /&lt;.*?1&gt;/; let result = text.match(myRegex); console.log(result); </code></pre> <h2>字符集</h2> <ul> <li><code>\w</code> : [A-Za-z0-9_] 数字字母下划线</li> <li><code>\W</code>: [^A-Za-z0-9_] 反匹配模式</li> <li><code>\d</code>: [0-9] 数字</li> <li><code>\D</code>: [^0-9] 非数字</li> <li><code>\s</code>: [\r\t\f\n\v] 空格 回车 制表符 换行 换页</li> <li><code>\S</code>: [^\r\t\f\n\v]</li> </ul> <h2>匹配的数量上下限</h2> <ul> <li><code>{m,n}</code>最少m个,最多n个</li> <li><code>{m}</code>指定m个</li> <li><code>{m,}</code>最少m个</li> <li><code>{,n}</code>最多n个</li> </ul> <h2>先行断言:在字符串中向前查找的匹配模式。</h2> <ul> <li><code>正向先行断言</code>:会查看并确保搜索匹配模式中的元素存在,但实际上并不匹配。</li> <li>用法是(<code>?=</code>...),其中...就是需要存在但不会被匹配的部分。</li> <li><code>负向先行断言</code>:会查看并确保搜索匹配模式中的元素不存在。</li> <li>用法是(<code>?!</code>...),其中...是你希望不存在的匹配模式。如果负向先行断言部分不存在,将返回匹配模式的其余部分。</li> </ul> <p>例子:</p> <ul> <li>3 到 6 个字符且至少包含一个数字:</li> </ul> <pre><code>let password = "abc123"; let checkPass = /(?=\w{3,6})(?=\D*\d)/; checkPass.test(password); // Returns true </code></pre> <ul> <li>至少5个字符且有连续两个数字的密码:</li> </ul> <pre><code>let sampleWord = "astronaut"; let pwRegex = /(?=\w{5,})(?=\D*\d{2}\D*)/; let result = pwRegex.test(sampleWord); </code></pre> <ul> <li>在vscode中正则搜索“未添加scoped属性的<code>&lt;style&gt;</code>标签”</li> </ul> <pre><code>&lt;style(?!.*scoped) </code></pre> <h2>捕获组:重用子字符串</h2> <ul> <li>用<code>()</code>来表示捕获组,匹配第一次出现的子字符串</li> <li>用<code> \n</code>来表示第n个捕获组,n是数字,表示第n个捕获组</li> </ul> <pre><code>let repeatStr = "regex regex"; let repeatRegex = /(\w+)\s\1/; repeatRegex.test(repeatStr); // Returns true repeatStr.match(repeatRegex); // Returns ["regex regex", "regex"] </code></pre> <h2>字符串原型方法replace:捕获组 搜索/替换</h2> <ul> <li> <p><code>.replace()</code>的输入首先是你想要搜索的正则表达式匹配模式,</p> </li> <li> <p>第二个参数是用于替换匹配的字符串或用于执行某些操作的函数。</p> </li> <li> <p>第二个参数中,可以用<code>$n</code>访问替换字符串中的捕获组(即用括号括起来的组)</p> </li> <li> <p>其中n表示<code>第n个捕获组</code></p> </li> <li> <p>例子:</p> </li> </ul> <pre><code>"Code Camp".replace(/(\w+)\s(\w+)/, "$2 $1"); // Returns "Camp Code" </code></pre> <ul> <li>去除字符串两端的空格</li> </ul> <pre><code>let hello = " Hello, World! "; let wsRegex = /^\s+(\S.*\S)\s+$/; let result = hello.replace(wsRegex, "$1"); </code></pre> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/dive_into_regular_expression/#post-comment/</comments>
</item>
<item>
<title>ML15 | Python与Js模型互转</title>
<link>https://www.scarsu.com/fed_ml_15_py_model/</link>
<guid isPermaLink="true">https://www.scarsu.com/fed_ml_15_py_model/</guid>
<description>Javascript玩转机器学习15</description>
<pubDate>Thu, 30 Apr 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>Python模型</h2> <ul> <li>通过 Python版 Tensorflow/ Keras生成模型</li> <li>类型包括: Tensorflow Saved Model、 Keras HDF5mode等</li> <li>获取:开源网站下载/算法同事提供</li> </ul> <h2>Javascript模型</h2> <ul> <li>可以在 TensorflowJs中运行的模型</li> <li>类型包括: tijs layers model, tojs graph model等</li> <li>获取:开源网站/通过TFJS生成/由 Python模型转化而来</li> </ul> <h2>为什么要互转</h2> <ul> <li>Python to JavaScript: JavaScript模型可以在浏览器中运行</li> <li>JavaScript to Python:少见,为了在更多平台运行</li> <li>JavaScript to JavaScript:分片/量化/加速</li> </ul> <h2>TensorFlow.js Converter</h2> <ul> <li>命令行转换器</li> <li>依赖Python-3.6.8(可以使用Anaconda工具创建环境</li> <li>在命令行指定输入输出的路径和模型格式即可</li> <li><a>地址</a></li> </ul> <h2>JavaScript:分片/量化/加速</h2> <ul> <li>分片:将模型切分,提升加载速度</li> <li>量化:通过牺牲一部分精度,压缩模型的大小</li> <li>加速:将模型转换为tfjs_graph_model格式可以加速模型</li> </ul> <hr /> <p><a>代码仓库</a></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/fed_ml_15_py_model/#post-comment/</comments>
</item>
<item>
<title>Vue2状态管理 & Vuex总结</title>
<link>https://www.scarsu.com/vue_store_and_vuex/</link>
<guid isPermaLink="true">https://www.scarsu.com/vue_store_and_vuex/</guid>
<description>多组件下 共享状态 的解决方案</description>
<pubDate>Thu, 30 Apr 2020 00:00:00 GMT</pubDate>
<content:encoded><h1>Vue状态管理 &amp; Vuex</h1> <h3>单向数据流</h3> <ul> <li>**state:**驱动应用的数据源;</li> <li>**view:**以声明方式将 <strong>state</strong> 映射到视图;</li> <li>**actions:**响应在 <strong>view</strong> 上的用户输入导致的state变化。</li> </ul> <p><img src="/images/vuex1.png" alt="" /></p> <h3>多组件共享状态的需求:</h3> <ul> <li>多个视图依赖于同一状态:传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力</li> <li>来自不同视图的行为需要<strong>变更同一状态</strong>:父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码</li> </ul> <p>(共享状态,不仅仅是多组件<strong>读取</strong>同一状态,也包含多组件<strong>变更</strong>同一状态)</p> <h2>基于state的简单状态管理</h2> <ul> <li>在vue实例外的作用域,定义一个state对象,作为共享状态</li> </ul> <pre><code>let publicState = {}; let vm1 = new Vue({ name: "vm1", data: publicState, }); let vm2 = new Vue({ name: "vm2", data: publicState, }); </code></pre> <ul> <li>简单的store模式</li> </ul> <pre><code>let store = { state: { a: "", }, setStateA() {}, clearStateA() {}, }; //把store.state放在vue实例的data里 let vm1 = new Vue({ name: "vm1", data: { privateState: {}, //组件的私有状态 publicState: store.state, //实例外的共有状态 }, }); let vm2 = new Vue({ name: "vm2", data: { privateState: {}, publicState: store.state, }, }); </code></pre> <p>组件们可以共享store中的状态,也可以通过actions变更状态</p> <p>因为共享状态放在组件的data里,store变化也会驱动组件view变更</p> <p><img src="/images/vuex2.png" alt="" /></p> <h2>Vuex基本思想</h2> <p>把组件的共享状态抽取出来,以一个全局单例模式管理</p> <p>在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为</p> <p>通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,我们的代码将会变得更结构化且易维护。</p> <p><img src="/images/vuex3.png" alt="" /></p> <h2>Vuex的使用&amp;子组件注入</h2> <p>src/store/index.js</p> <pre><code>import Vue from "vue"; import Vuex from "vuex"; Vue.use(Vuex); export default new Vuex.Store({ state: { count: 0, }, mutations: { increment(state) { state.count++; }, decrement(state) { state.count--; }, }, }); </code></pre> <p>/src/main.js</p> <pre><code>import Vue from "vue"; import store from "@/store"; import router from "@/router"; import App from "@/App"; // store作为选项传入根组件,是将$store注入所有子组件 // 子组件都可以通过this.$store访问全局store // eslint-disable-next-line no-new new Vue({ el: "#app", store, router, render: (h) =&gt; h(App), }); </code></pre> <h2>Vuex的核心思想一:state</h2> <p>Vuex 使用单一状态树——用一个对象(store)就包含了全部的应用层级状态。</p> <p>至此它便作为一个“唯一数据源 (SSOT)”而存在。</p> <p>这也意味着,每个应用将仅仅包含一个 store 实例。</p> <p>单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。</p> <h3>子组件获取state &amp; mapState辅助函数</h3> <p>/src/page/home.vue</p> <pre><code> &lt;template&gt; &lt;div id="home"&gt; &lt;div&gt;count:{{count}}&lt;/div&gt; &lt;div&gt;count1:{{count1}}&lt;/div&gt; &lt;div&gt;count3:{{count3}}&lt;/div&gt; &lt;div&gt;count4:{{count4}}&lt;/div&gt; &lt;div&gt;count5:{{count5}}&lt;/div&gt; &lt;button @click="increment"&gt;+&lt;/button&gt; &lt;button @click="decrement"&gt;-&lt;/button&gt; &lt;/div&gt; &lt;/template&gt; &lt;script&gt; import { mapState } from 'vuex' export default { name: 'home', data () { return { message: 'hello', localCount: 1 } }, computed: { // 方式1:直接从Vue原型链上获取$store count1 () { return this.$store.state.count }, // 方式2:mapState方法传状态名数组 ...mapState(['count']), ...mapState({ // 方式3:mapState传对象,键为状态别名,值为状态名 count3: 'count', // 方式4:mapState传对象,键为getter函数,参数是state,值为箭头函数 count4: state =&gt; state.count, // 方式5:mapState传对象,键为getter函数,参数是state,值为普通函数(因为要再函数体内用this) count5 (state) { return this.localCount + state.count } }) }, methods: { increment () { this.$store.commit('increment') }, decrement () { this.$store.commit('decrement') } } } &lt;/script&gt; </code></pre> <h2>Vuex核心思想二:getter</h2> <h3>派生状态</h3> <p>类似于vue组件的计算属性,可以从store的state中派生出一些状态</p> <pre><code>export default new Vuex.Store({ state: { todos: [ { id: 1, desc: "test1", done: false }, { id: 2, desc: "test2", done: true }, { id: 3, desc: "test3", done: false }, ], }, getters: { //getter中可以接受其他getter作为参数 maxTodoId(state, getters) { return state.todos.sort((a, b) =&gt; { return b.id - a.id; })[0].id; }, doneTodoCount(state) { return state.todos.filter((todo) =&gt; todo.done === true).length; }, }, }); </code></pre> <h3>通过this.$store.state.getters属性 / mapGetters访问派生状态</h3> <pre><code>computed: { ...mapGetters(['doneTodoCount']), doneTodoCount2 () { return this.$store.getters.doneTodoCount } }, </code></pre> <h3>getter传参:让getter返回函数</h3> <pre><code>getters: { getTodoBySearch: (state) =&gt; (s) =&gt; { return state.todos.filter((todo) =&gt; { return (todo.id + todo.desc).indexOf(s) &gt;= 0; }); }; } </code></pre> <h2>Vuex核心思想三:mutation</h2> <h3>提交mutation</h3> <p>组件不能直接更改Vuex store中的状态,而是要提交(commit)变更(mutations)</p> <pre><code>export default { name: "home", data() { return {}; }, methods: { addTodo(e) { if (e.keyCode === 13 &amp;&amp; this.model.desc) { this.$store.commit("addTodo", this.model.desc); this.model.desc = ""; } }, }, }; </code></pre> <p>其中<strong>addTodo</strong>就是在store的mutation中定义的一种变更:</p> <pre><code>mutations: { addTodo (state, desc) { const maxTodoId = state.todos.sort((a, b) =&gt; { return b.id - a.id })[0].id const todo = { desc, id: maxTodoId + 1, done: false } state.todos.push(todo) } } </code></pre> <h3><strong>提交载荷(Payload)</strong></h3> <p>可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload):</p> <pre><code>// src/store/index.js mutations: { increment (state, payload) { } } // src/page/home.vue let payload={a:1,b:2} store.commit('increment', payload) </code></pre> <h3>Mutation 需遵守 Vue 的响应规则</h3> <p>Vuex 的 store 中的状态是响应式的,</p> <p>当我们变更状态时,</p> <p>监视状态的 Vue 组件也会自动更新,</p> <p>因此 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项</p> <ol> <li> <p>最好提前在你的 store 中初始化好所有所需属性。</p> </li> <li> <p>当需要在对象上添加新属性时,应该</p> <ul> <li>使用 <code>Vue.set(obj, 'newProp', 123)</code></li> <li>以新对象替换老对象。例如,利用**<a>对象展开运算符</a>**:</li> </ul> <pre><code>state.obj = { ...state.obj, newProp: 123 }; </code></pre> </li> </ol> <h3>使用常量替代 Mutation 事件类型</h3> <pre><code>// mutation-types.js export const SOME_MUTATION = 'SOME_MUTATION' // store.js import Vuex from 'vuex' import { SOME_MUTATION } from './mutation-types' const store = new Vuex.Store({ state: { ... }, mutations: { // 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名 [SOME_MUTATION] (state) { // mutate state } } }) </code></pre> <h3>Mutation 必须是同步函数</h3> <p>devtools捕捉会mutations记录,每次记录前一状态+后一状态的快照</p> <p>如果mutation里是异步的函数,很可能快照捕捉时,状态还未更改</p> <p>在回调函数中进行的状态的改变都是不可追踪的</p> <p>因此很<strong>不利于调试</strong></p> <h2>Vuex核心思想四:Action</h2> <h3>Action与Mutation类似,不同点:</h3> <ul> <li>Action 提交(commit)的是 mutation,而<strong>不是直接变更状态</strong>。</li> <li>Action 可以包含任意<strong>异步</strong>操作。</li> </ul> <h3>action函数的定义</h3> <pre><code>//... actions: { addTodo (context) { // 可以通过context参数去调用commit,获取state和getters // context区别于state(module中会讲到 setTimeout(() =&gt; { context.commit('addTodo') // context.state // context.getters }, 1000) }, addTodo2 ({ commit, state, getters }) { // 也可以直接用参数解构的方法获取commit,state,getters setTimeout(() =&gt; { commit('addTodo') }, 1000) } } //... </code></pre> <h3>组件分发action(可以带载荷/参数</h3> <pre><code>methods: { addTodo (e) { this.$store.dispatch('addTodo', payload) this.$store.dispatch({ type: 'addTodo', ...payload }) } } //action接收payload参数 //action内部也可以dispatch其他action actions: { addTodo2 ({ commit, state, getters, dispatch }, payload) { // 也可以直接用参数解构的方法获取commit,state,getters setTimeout(() =&gt; { commit('addTodo') //dispatch }, 1000) } } </code></pre> <h3>组合action</h3> <ul> <li>action可以返回一个promise函数</li> </ul> <pre><code>actions: { actionA ({ commit }) { return new Promise((resolve, reject) =&gt; { setTimeout(() =&gt; { commit('someMutation') resolve() }, 1000) }) } } </code></pre> <ul> <li>dispatch可以处理action返回的promise,并仍然返回promise</li> </ul> <pre><code>store.dispatch("actionA").then(() =&gt; { // ... }); </code></pre> <ul> <li>利用await/async编写组合action更加简洁</li> </ul> <pre><code>// 假设 getData() 和 getOtherData() 返回的是 Promise actions: { async actionA ({ commit }) { commit('gotData', await getData()) }, async actionB ({ commit, dispatch }) { await dispatch('actionA') commit('gotOtherData', await getOtherData()) } } </code></pre> <h2>Vuex核心思想五:Module</h2> <p>当应用较复杂时,应用所有状态集中在一个(store)对象上很臃肿</p> <p>因此Vuex允许将store按模块来划分,</p> <p>每个store拥有自己的state、getter、mutations、actions、子模块</p> <pre><code>// src/store/module/moduleA.js export default { state: {}, getter: {}, mutations: {}, actions: {} } // src/store/index.js import Vue from 'vue' import Vuex from 'vuex' import moduleA from 'module/moduleA' Vue.use(Vuex) export default new Vuex.Store({ modules: { a: moduleA }, ... }) </code></pre> <h3>模块内的局部状态state(getter mutation action获取state</h3> <p><strong>对于模块内的getter、mutation函数</strong>:</p> <p>接收的第一个参数:state,指向的是模块内的局部状态</p> <p>getter函数接收的<strong>第三个</strong>参数是根节点状态:<strong>rootState</strong></p> <p><strong>对于模块内的action函数:</strong></p> <p>context.state指向的也是模块的局部状态,根节点的状态为<strong>context.rootState</strong></p> <h3>全局命名空间(组件获取getter mutation action</h3> <p>默认情况:模块内部的 action、mutation 和 getter 是注册在<strong>全局命名空间</strong>的——这样使得多个模块能够对同一 mutation 或 action 作出响应。</p> <h3>带命名空间的模块</h3> <p>如果希望你的模块具有更高的<strong>封装度和复用性</strong>,你可以通过添加 <strong>namespaced: true</strong> 的方式使其成为带命名空间的模块。</p> <pre><code>const store = new Vuex.Store({ modules: { account: { namespaced: true, // 模块内容(module assets) state: { ... }, // 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响 getters: { isAdmin () { ... } // -&gt; getters['account/isAdmin'] }, actions: { login () { ... } // -&gt; dispatch('account/login') }, mutations: { login () { ... } // -&gt; commit('account/login') }, // 嵌套模块 modules: { // 没加namespaced属性,所以继承父模块的命名空间 myPage: { state: { ... }, getters: { profile () { ... } // -&gt; getters['account/profile'] } }, // 进一步嵌套命名空间 posts: { namespaced: true, state: { ... }, getters: { popular () { ... } // -&gt; getters['account/posts/popular'] } } } } } }) </code></pre> <p>启用了命名空间的 getter 和 action 会<strong>收到局部化的 getter,dispatch 和 commit</strong>。</p> <p>换言之,在使用模块内容(module assets,即指模块内的state、getter、mutation、action)时不需要在同一模块内额外添加空间名前缀。</p> <p>所以:更改 namespaced 属性后不需要修改模块内的代码</p> <h3>带命名空间的模块内访问全局内容(Global Assets)</h3> <p>Global Assets即全局的state,getter,mutation,action</p> <ul> <li>getter的第三、第四参数:rootState、rootGetters</li> <li>action的context参数包含:rootState、rootGetters</li> <li>全局commit、dispatch:传入参数root:true</li> </ul> <h3>带命名空间的模块注册全局 action</h3> <p>传入root选项,值为true</p> <pre><code>... someAction:{ root:true, handler:()=&gt;{} } ... </code></pre> <h3>mapState, mapGetters, mapActions 和 mapMutations操作命名空间:</h3> <pre><code>// 方法一:直接在状态名前加命名空间 computed: { ...mapState({ a: state =&gt; state.some.nested.module.a, b: state =&gt; state.some.nested.module.b }) }, methods: { ...mapActions([ 'some/nested/module/foo', // -&gt; this['some/nested/module/foo']() 'some/nested/module/bar' // -&gt; this['some/nested/module/bar']() ]) } // 方法二:也可以把共有的命名空间传给函数第一个参数 computed: { ...mapState('some/nested/module', { a: state =&gt; state.a, b: state =&gt; state.b }) }, methods: { ...mapActions('some/nested/module', [ 'foo', // -&gt; this.foo() 'bar' // -&gt; this.bar() ]) } //方法三:利用createNamespacedHelpers,传入命名空间,会返回已经绑定命名空间的map方法 import { createNamespacedHelpers } from 'vuex' const { mapState, mapActions } = createNamespacedHelpers('some/nested/module') </code></pre> <h3>动态注册模块</h3> <p>在store已经实例化后,如果想添加模块,可以用registerModule方法</p> <pre><code>import Vuex from "vuex"; const store = new Vuex.Store({ /* 选项 */ }); // 注册模块 `myModule` store.registerModule("myModule", { // ... }); // 注册嵌套模块 `nested/myModule` store.registerModule(["nested", "myModule"], { // ... }); </code></pre> <p>卸载动态模块:unregisterModule(不能卸载静态模块</p> <p>判断模块是否存在:hasModule</p> <h2>纯对象state&amp;函数声明state</h2> <p>纯对象state可以通过引用被访问,造成状态对象被修改时 store 或模块间数据互相污染的问题。</p> <p>因此可以和vue组件内的data一样,使用函数来声明state:</p> <pre><code>const MyReusableModule = { state() { return { foo: "bar", }; }, // mutation, action 和 getter 等等... }; </code></pre> <h2>严格模式</h2> <p>在非生产环境开启严格模式,在任何尝试不通过mutation直接修改state的操作时,都会抛出错误</p> <h2>v-model &amp; Vuex的state</h2> <p>v-model直接绑定Vuex上的state,在严格模式下会报错,因为双向绑定的机制会直接尝试修改state,而不是通过mutation,解决方法是,绑定一个设置了getter和setter的计算属性:</p> <pre><code>... computed:{ attr:{ getter(){ return this.$store.state.attr }, setter(val){ this.$store.commit('updateAttr',val) } } } </code></pre> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/vue_store_and_vuex/#post-comment/</comments>
</item>
<item>
<title>ML14 | 声控轮播图 - 语音识别迁移学习</title>
<link>https://www.scarsu.com/fed_ml_14_slider/</link>
<guid isPermaLink="true">https://www.scarsu.com/fed_ml_14_slider/</guid>
<description>Javascript玩转机器学习14</description>
<pubDate>Wed, 29 Apr 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>在浏览器中收集中文语音训练数据</h2> <ul> <li>html</li> </ul> <pre><code>&lt;script src="script.js"&gt;&lt;/script&gt; &lt;button onclick="collect(this)"&gt;上一张&lt;/button&gt; &lt;button onclick="collect(this)"&gt;下一张&lt;/button&gt; &lt;button onclick="collect(this)"&gt;背景噪音&lt;/button&gt; &lt;button onclick="save()"&gt;保存&lt;/button&gt; &lt;pre id="count"&gt;&lt;/pre&gt; &lt;button onclick="train()"&gt;训练&lt;/button&gt; &lt;br /&gt;&lt;br /&gt; 监听开关:&lt;input type="checkbox" onchange="toggle(this.checked)" /&gt; </code></pre> <ul> <li>js</li> </ul> <pre><code>import * as speechCommands from "@tensorflow-models/speech-commands"; import * as tfvis from "@tensorflow/tfjs-vis"; const MODEL_PATH = "http://127.0.0.1:8080"; let transferRecognizer; window.onload = async () =&gt; { const recognizer = speechCommands.create( "BROWSER_FFT", //浏览器的傅里叶变换(将声音转为声谱数据 null, MODEL_PATH + "/speech/model.json", MODEL_PATH + "/speech/metadata.json", ); await recognizer.ensureModelLoaded(); //使用createTransfer接口创建迁移模型 transferRecognizer = recognizer.createTransfer("轮播图"); }; window.collect = async (btn) =&gt; { btn.disabled = true; const label = btn.innerText; //用collectExample接口收集语音数据,传入语音命令名称,背景音名称是固定的_background_noise_ await transferRecognizer.collectExample( label === "背景噪音" ? "_background_noise_" : label, ); btn.disabled = false; //将收集的数据可视化 document.querySelector("#count").innerHTML = JSON.stringify( transferRecognizer.countExamples(), null, 2, ); }; </code></pre> <h2>语音训练数据的保存</h2> <pre><code>window.save = () =&gt; { //用serializeExamples接口将收集的样例数据序列化 const arrayBuffer = transferRecognizer.serializeExamples(); const blob = new Blob([arrayBuffer]); const link = document.createElement("a"); link.href = window.URL.createObjectURL(blob); link.download = "data.bin"; link.click(); }; </code></pre> <h2>加载数据,用speech commands包行迁移学习,训练</h2> <pre><code>window.onload = async () =&gt; { const recognizer = speechCommands.create( "BROWSER_FFT", null, MODEL_PATH + "/speech/model.json", MODEL_PATH + "/speech/metadata.json", ); await recognizer.ensureModelLoaded(); transferRecognizer = recognizer.createTransfer("轮播图"); //用fetch方法从本静态服务器拿到样例数据 const res = await fetch(MODEL_PATH + "/slider/data.bin"); //转为arrayBuffer格式 const arrayBuffer = await res.arrayBuffer(); //模型加载样例数据 transferRecognizer.loadExamples(arrayBuffer); //模型训练 await transferRecognizer.train({ epochs: 30 }); console.log("done"); }; </code></pre> <h2>轮播图html</h2> <ul> <li>html</li> </ul> <pre><code>&lt;script src="script.js"&gt;&lt;/script&gt; 监听开关:&lt;input type="checkbox" onchange="toggle(this.checked)" /&gt; &lt;style&gt; .slider { width: 600px; overflow: hidden; margin: 10px auto; } .slider &gt; div { display: flex; align-items: center; } &lt;/style&gt; &lt;div class="slider"&gt; &lt;div&gt; &lt;img loading="lazy" decoding="async" src="https://cdn.pixabay.com/photo/2019/10/29/15/57/vancouver-4587302__480.jpg" alt="" width="600" /&gt; &lt;img loading="lazy" decoding="async" src="https://cdn.pixabay.com/photo/2019/10/31/07/14/coffee-4591159__480.jpg" alt="" width="600" /&gt; &lt;img loading="lazy" decoding="async" src="https://cdn.pixabay.com/photo/2019/11/01/11/08/landscape-4593909__480.jpg" alt="" width="600" /&gt; &lt;img loading="lazy" decoding="async" src="https://cdn.pixabay.com/photo/2019/11/02/21/45/maple-leaf-4597501__480.jpg" alt="" width="600" /&gt; &lt;img loading="lazy" decoding="async" src="https://cdn.pixabay.com/photo/2019/11/02/03/13/in-xinjiang-4595560__480.jpg" alt="" width="600" /&gt; &lt;img loading="lazy" decoding="async" src="https://cdn.pixabay.com/photo/2019/11/01/22/45/reschensee-4595385__480.jpg" alt="" width="600" /&gt; &lt;/div&gt; &lt;/div&gt; </code></pre> <h2>监听&amp;控制轮播</h2> <pre><code>await transferRecognizer.listen( (result) =&gt; { const { scores } = result; const labels = transferRecognizer.wordLabels(); const index = scores.indexOf(Math.max(...scores)); window.play(labels[index]); }, { overlapFactor: 0, probabilityThreshold: 0.5, }, ); window.play = (label) =&gt; { const div = document.querySelector(".slider&gt;div"); if (label === "上一张") { if (curIndex === 0) { return; } curIndex -= 1; } else { if (curIndex === document.querySelectorAll("img").length - 1) { return; } curIndex += 1; } div.style.transition = "transform 1s"; div.style.transform = `translateX(-${100 * curIndex}%)`; }; </code></pre> <hr /> <p><a>代码仓库</a></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/fed_ml_14_slider/#post-comment/</comments>
</item>
<item>
<title>高效使用VSCode</title>
<link>https://www.scarsu.com/customize_vscode/</link>
<guid isPermaLink="true">https://www.scarsu.com/customize_vscode/</guid>
<description>VSCode高效使用,来自创造VSCode的Microsoft的Azure团队的BurkeHolland的分享</description>
<pubDate>Tue, 28 Apr 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>Links</h2> <ul> <li><a>全文</a></li> <li><a>视频</a></li> <li><a>插件vs-code-can-do-that</a></li> </ul> <h2>记录几个高光点</h2> <ul> <li><strong>Setting Sync插件</strong>:使用gist,同步一切你的个性化配置(user settings,not workspace settings,workspace settings建议存在项目的代码仓库里使团队成员有统一的配置),即使切换环境,也可以在几分钟内得到一个一模一样的完全得心应手的IDE(gist已经被墙</li> <li><strong>Project Manager插件</strong>:在侧边栏一键切换/多开工作区/项目,只需要一个简单的配置文件</li> <li>侧边栏建议放在右侧,放在左侧时,侧边栏的隐藏/显示,会使整个代码区移动</li> </ul> <hr /> <p>&lt;small&gt;视频讲的很细很全,不做赘述。很多有用的tips&lt;/small&gt;</p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/customize_vscode/#post-comment/</comments>
</item>
<item>
<title>ML13 | 用tf官方的预训练模型-语音识别</title>
<link>https://www.scarsu.com/fed_ml_13_speech_recognition/</link>
<guid isPermaLink="true">https://www.scarsu.com/fed_ml_13_speech_recognition/</guid>
<description>Javascript玩转机器学习13</description>
<pubDate>Tue, 28 Apr 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>语音识别</h2> <ul> <li>模型接受声音信息,输出分类信息</li> <li>声音在计算机里是声谱图,因此也可以使用卷积神经网络</li> </ul> <h2>加载预训练语音识别模型(tf官网的模型)</h2> <ul> <li>开本地静态服务器,获取语音识别模型文件</li> <li>使用tfjs-models的speech-commands包加载模型 (tfjs-models是tf官方的模型库)</li> </ul> <h2>进行语音识别</h2> <ul> <li>html</li> </ul> <pre><code>&lt;script src="script.js"&gt;&lt;/script&gt; &lt;style&gt; #result &gt; div { float: left; padding: 20px; } &lt;/style&gt; &lt;div id="result"&gt;&lt;/div&gt; </code></pre> <ul> <li>js</li> </ul> <pre><code>// 引入tf-models库提供的语音命令npm包 import * as speechCommands from "@tensorflow-models/speech-commands"; //本地静态文件服务器地址 const MODEL_PATH = "http://127.0.0.1:8080/speech"; window.onload = async () =&gt; { // speechCommands文档: // https://github.com/tensorflow/tfjs-models/tree/master/speech-commands const recognizer = speechCommands.create( "BROWSER_FFT", //傅里叶变换 null, MODEL_PATH + "/model.json", MODEL_PATH + "/metadata.json", ); //加载模型 await recognizer.ensureModelLoaded(); //显示模型能识别的语音类型 const labels = recognizer.wordLabels().slice(2); const resultEl = document.querySelector("#result"); resultEl.innerHTML = labels .map( (l) =&gt; ` &lt;div&gt;${l}&lt;/div&gt; `, ) .join(""); //浏览器监听语音 recognizer.listen( (result) =&gt; { const { scores } = result; const maxValue = Math.max(...scores); //拿到分类中 可能性最大的单词 const index = scores.indexOf(maxValue) - 2; //突出显示 resultEl.innerHTML = labels .map( (l, i) =&gt; ` &lt;div style="background: ${i === index &amp;&amp; "green"}"&gt;${l}&lt;/div&gt; `, ) .join(""); }, { overlapFactor: 0.3, //识别频率 probabilityThreshold: 0.9, //准确度阈值,超过0.9的准确度 就执行参数一的函数 }, ); }; </code></pre> <h2>效果</h2> <p><img src="/images/ai/003.gif" alt="语音指令识别" /></p> <hr /> <p><a>代码仓库</a></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/fed_ml_13_speech_recognition/#post-comment/</comments>
</item>
<item>
<title>ML12 | 基于迁移学习的图片分类-商标识别</title>
<link>https://www.scarsu.com/fed_ml_12_transfer_learning/</link>
<guid isPermaLink="true">https://www.scarsu.com/fed_ml_12_transfer_learning/</guid>
<description>Javascript玩转机器学习12</description>
<pubDate>Mon, 27 Apr 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>迁移学习</h2> <ul> <li><strong>是什么</strong>:把已训练好的模型参数迁移到新的模型来帮助新模型训练</li> <li><strong>为什么</strong>:深度学习模型参数多,从头训练成本高</li> <li><strong>怎么做</strong>:删除原始模型的最后一层,基于此截断模型的输出训练一个新的(通常相当浅的)模型</li> </ul> <h2>加载商标训练数据并可视化</h2> <ul> <li> <p>商标训练素材 <img src="/images/ai/63.png" alt="训练素材" /></p> </li> <li> <p>在本地为素材建立静态http服务器</p> </li> </ul> <pre><code>hs data --cors </code></pre> <ul> <li>编写JS脚本加载训练图片及其标签</li> </ul> <pre><code>// index.html &lt;script src="script.js"&gt;&lt;/script&gt; &lt;input type="file" onchange="predict(this.files[0])" /&gt; &lt;button onclick="download()"&gt;下载模型&lt;/button&gt; </code></pre> <pre><code>// data.js const loadImg = (src) =&gt; { return new Promise((resolve) =&gt; { const img = document.createElement("img"); img.crossOrigin = "anonymous"; img.src = src; img.width = 224; //以mobileNet为截断模型,其接收图片尺寸为224 img.height = 224; img.onload = () =&gt; reslove(img); }); }; // 返回Promise export const getInputs = async () =&gt; { const loadImgs = []; const labels = []; for (let i = 0; i &lt; 30; i += 1) { ["android", "apple", "windows"].forEach((label) =&gt; { const imgP = loadImg( `http://127.0.0.1:8080/brand/train/${label}-${index}.jpg`, ); loadImgs.push(imgP); labels.push([ label === "android" ? 1 : 0, label === "apple" ? 1 : 0, label === "windows" ? 1 : 0, ]); }); } const inputs = await Promise.all(loadImgs); return { inputs, labels, }; }; </code></pre> <pre><code>// script.js import * as tf from "@tensorflow/tfjs"; import * as tfvis from "@tensorflow/tfjs-vis"; import { getInputs } from "./data"; import { img2x, file2img } from "./utils"; const MOBILENET_MODEL_PATH = "http://127.0.0.1:8080/mobilenet/web_model/model.json"; const NUM_CLASSES = 3; const BRAND_CLASSES = ["android", "apple", "windows"]; window.onload = async () =&gt; { const { inputs, labels } = await getInputs(); // console.log([inputs,labels]) //将加载的图片素材可视化 const surface = tfvis .visor() .surface({ name: "输入示例", styles: { height: 250 } }); inputs.forEach((img) =&gt; { surface.drawArea.appendChild(img); }); }; </code></pre> <ul> <li>可视化训练图片: <img src="/images/ai/64.png" alt="可视化训练图片" /></li> </ul> <h2>加载预训练好的模型Mobilenet</h2> <pre><code>//加载预训练好的模型Mobilenet const mobilenet = await tf.loadLayersModel(MOBILENET_MODEL_PATH); //mobilenet的方法,给出其神经网络的概览 mobilenet.summary(); </code></pre> <p><img src="/images/ai/65.png" alt="mobilenet模型概览" /></p> <h2>定义截断模型</h2> <pre><code>//获取中间层 const layer = mobilenet.getLayer("conv_pw_13_relu"); //定义一个截断模型truncatedMobilenet const truncatedMobilenet = tf.model({ inputs: mobilenet.inputs, outputs: layer.output, }); </code></pre> <h2>定义双层的迁移模型</h2> <pre><code>//定义一个模型 const model = tf.sequential(); //添加一个flatten层(将截断模型提取的高维特征提取成一维向量,这一层没有参数,起转换作用 model.add( tf.layers.flatten({ inputShape: layer.outputShape.slice(1), }), ); //添加一个全链接层:用于训练我们的商标图片 model.add( tf.layers.dense({ units: 10, activation: "relu", }), ); //添加一个全链接层:用于做多分类 model.add( tf.layers.dense({ units: NUM_CLASSES, activation: "softmax", }), ); //设置损失函数:分类交叉熵损失函数,优化器为adam model.compile({ loss: "categoricalCrossentropy", optimizer: tf.train.adam() }); </code></pre> <h2>先用截断模型训练数据,转为可以用于迁移模型的数据</h2> <pre><code>//训练数据 先经过截断模型,转为可以用于迁移模型的数据 const { xs, ys } = tf.tidy(() =&gt; { const xs = tf.concat( inputs.map((imgEl) =&gt; truncatedMobilenet.predict(img2x(imgEl))), ); const ys = tf.tensor(labels); return { xs, ys }; }); </code></pre> <h2>训练迁移模型</h2> <pre><code>//训练迁移模型 await model.fit(xs, ys, { epochs: 20, callbacks: tfvis.show.fitCallbacks({ name: "训练效果" }, ["loss"], { callbacks: ["onEpochEnd"], }), }); </code></pre> <p><img src="/images/ai/66.png" alt="迁移模型训练效率高" /></p> <h2>预测</h2> <pre><code>window.predict = async (file) =&gt; { const img = await file2img(file); document.body.appendChild(img); const pred = tf.tidy(() =&gt; { const x = img2x(img); const input = truncatedMobilenet.predict(x); return model.predict(input); }); const index = pred.argMax(1).dataSync()[0]; setTimeout(() =&gt; { alert(`预测结果:${BRAND_CLASSES[index]}`); }, 0); }; </code></pre> <p><img src="/images/picgo/002.gif" alt="预测效果" /></p> <h2>模型的保存和加载</h2> <ul> <li>保存:把训练好的模型保存成文件或者 local storage变量</li> </ul> <pre><code>window.download = async () =&gt; { await model.save('downloads://model'); }; </code></pre> <ul> <li>加载:从文件或者 local storage中加载模型</li> <li>原因:无需重复训练,便于复用到其他应用中</li> </ul> <hr /> <p><a>代码仓库</a></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/fed_ml_12_transfer_learning/#post-comment/</comments>
</item>
<item>
<title>ML11 | 使用预训练模型 图片分类</title>
<link>https://www.scarsu.com/fed_ml_11_pre_training_model/</link>
<guid isPermaLink="true">https://www.scarsu.com/fed_ml_11_pre_training_model/</guid>
<description>Javascript玩转机器学习11</description>
<pubDate>Sun, 26 Apr 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>预训练模型是什么</h2> <ul> <li>预先训练好的模型,无需训练,即可预测</li> <li>在Tensorflow.js中可以调用Web格式的模型文件</li> </ul> <h2>MobileNet模型</h2> <ul> <li>一种卷积神经网络模型,能识别1000种物体图片</li> <li>模型文件小,响应速度块,准确度略低</li> </ul> <h4>引入模型文件</h4> <ul> <li>为资源启动本地静态资源服务器(文件位于本地代码仓库/data下)</li> </ul> <pre><code>hs data --cors </code></pre> <ul> <li>引入资源</li> </ul> <pre><code>const MOBILENET_MODEL_PATH = 'http://127.0.0.1:8080/mobilenet/web_model/model.json'; </code></pre> <ul> <li>引入物体类型</li> </ul> <pre><code>import { IMAGENET_CLASSES } from './imagenet_classes'; </code></pre> <h4>用tfjs加载模型</h4> <pre><code>//用tf的loadLayersModel加载模型 const model = await tf.loadLayersModel(MOBILENET_MODEL_PATH); </code></pre> <h4>前端输入带预测数据</h4> <ul> <li>html</li> </ul> <pre><code>&lt;script src="script.js"&gt;&lt;/script&gt; &lt;input type="file" onchange="predict(this.files[0])" /&gt; </code></pre> <h4>使用模型进行预测</h4> <pre><code>// ./util.js export function file2img(f) { return new Promise((resolve) =&gt; { const reader = new FileReader(); reader.readAsDataURL(f); reader.onload = (e) =&gt; { const img = document.createElement("img"); img.src = e.target.result; img.width = 224; img.height = 224; img.onload = () =&gt; resolve(img); }; }); } // ./script.js window.predict = async (file) =&gt; { //从文件转换为htmlElement const img = await file2img(file); document.body.appendChild(img); const pred = tf.tidy(() =&gt; { //tidy优化webGl内存 const input = tf.browser .fromPixels(img) //转换为tensor .toFloat() //整数转为浮点数 .sub(255 / 2) //归一化 .div(255 / 2) .reshape([1, 224, 224, 3]); //一个图片的格式 return model.predict(input); //预测 }); const index = pred.argMax(1).dataSync()[0]; // setTimeout 0 使ui不被脚本阻塞 setTimeout(() =&gt; { alert(`预测结果:${IMAGENET_CLASSES[index]}`); }, 0); }; </code></pre> <h2><img src="/images/ai/61.png" alt="预测效果" /></h2> <p><a>代码仓库</a></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/fed_ml_11_pre_training_model/#post-comment/</comments>
</item>
<item>
<title>ML10 | 训练卷积神经网络 识别手写数字</title>
<link>https://www.scarsu.com/fed_ml_10_handwriting_number/</link>
<guid isPermaLink="true">https://www.scarsu.com/fed_ml_10_handwriting_number/</guid>
<description>Javascript玩转机器学习10</description>
<pubDate>Sat, 25 Apr 2020 00:00:00 GMT</pubDate>
<content:encoded><p><img src="/images/picgo/001.gif" alt="先看一下简单训练的预测效果" /></p> <h2>加载MNIST数据集</h2> <ul> <li> <p>MNIST:巨大的训练集雪碧图,以手写数字图片组成</p> </li> <li> <p>资源文件位置</p> </li> </ul> <pre><code>/js-ml-code/data/mnist mnist_images.png mnist_labels_uint8 </code></pre> <ul> <li>给资源文件建立服务器供解析脚本访问</li> </ul> <pre><code>hs data --cors </code></pre> <p>其中--cors表示允许跨域访问</p> <ul> <li>加载20组数据</li> </ul> <pre><code>import * as tf from "@tensorflow/tfjs"; import * as tfvis from "@tensorflow/tfjs-vis"; import { MnistData } from "./data"; window.onload = async () =&gt; { const data = new MnistData(); await data.load(); //加载资源 const examples = data.nextTestBatch(20); //获取20组验证集数据 console.log(examples); }; </code></pre> <ul> <li> <p>打印出的examples: <img src="/images/ai/55.png" alt="" /> <img src="/images/ai/57.png" alt="" /></p> </li> <li> <p>tensorflow的splice api <img src="/images/ai/58.png" alt="" /></p> </li> <li> <p>用tensorflow的api和canvas显示出20组图片</p> </li> </ul> <pre><code>const surface = tfvis.visor().surface({ name: "输入示例" }); for (let i = 0; i &lt; 20; i += 1) { //截取出单个图片:从第1维的第i项+第二维的第1项开始截取,第一维截取长度是1,第二维截取长度是784 //console.log(examples.xs.slice([i, 0], [1, 784])) //tf.tidy:用于优化webGl内存,防止tensor数据量过大导致内存泄漏 //tf.browser.toPixels:转换成浏览器能识别的像素格式,传入二位参数就是黑白图片,三维就是彩色的 //tensor.reshape:tensor格式转换 const imageTensor = tf.tidy(() =&gt; { return examples.xs.slice([i, 0], [1, 784]).reshape([28, 28, 1]); //将一维数组转换成三维黑白图片格式 }); const canvas = document.createElement("canvas"); canvas.width = 28; canvas.height = 28; canvas.style = "margin: 4px"; await tf.browser.toPixels(imageTensor, canvas); surface.drawArea.appendChild(canvas); } </code></pre> <ul> <li>显示效果:</li> </ul> <p><img src="/images/ai/56.png" alt="" /></p> <h2>卷积神经网络</h2> <h4>为什么要用卷积神经网络</h4> <ul> <li>图片数据量大,运算量大,例如一个200*200像素的彩色图片:200*200*3=120,000</li> <li>卷积神经网络能模拟人类的视觉处理流程,高效提取特征</li> </ul> <h4>卷积神经网络的结构</h4> <h5>卷积层</h5> <ul> <li><a>image kernels网站了解图像卷积核</a></li> <li>图像卷积核是一个小的矩阵,用于施加一些效果,例如在Photoshop中可能会看到的效果,例如模糊,锐化,勾勒出轮廓或压花。它们还用于机器学习中的“特征提取”,这是一种确定图像最重要部分的技术。在这种情况下,该过程通常被称为“卷积”</li> <li><img src="/images/ai/59.png" alt="卷积" /></li> <li>图片上的3X3的小矩阵,就是用于卷积以提取图像特征的<strong>图像卷积核</strong></li> <li>使用多个卷积核(filter/kernel)对图像进行卷积操作,提取多种特征并组合</li> <li><strong>卷积层</strong>有权重,需要训练,其权重就是<strong>卷积核</strong></li> </ul> <h5>池化层</h5> <ul> <li>优化层</li> <li>最大池化层用于提取<strong>最强的特征</strong></li> <li>扩大感受视野,减少计算量</li> <li>池化层是固定的,不需要训练</li> </ul> <h5>dense全链接层</h5> <ul> <li>作为输出层</li> <li>作为分类器</li> <li>有权重,需要训练</li> </ul> <h2>构建卷积神经网络代码</h2> <pre><code>const model = tf.sequential(); //添加一个二位卷积层 model.add( tf.layers.conv2d({ inputShape: [28, 28, 1], kernelSize: 5, //卷积核的大小是5X5的矩阵 filters: 8, //应用8种图像卷积核 strides: 1, //移动步长,每一个像素单元都进行卷积操作 activation: "relu", //激活函数,移除掉无用的特征(特征&lt;0就废弃 kernelInitializer: "varianceScaling", //可以不设置,设置了可以加快收敛速度 }), ); //最大池化层 model.add( tf.layers.maxPool2d({ poolSize: [2, 2], //尺寸是2X2 strides: [2, 2], //移动步长,每隔两个像素单元进行一次卷积操作 }), ); // 重复上述两个层 model.add( tf.layers.conv2d({ kernelSize: 5, filters: 16, //需要提取更多特征 strides: 1, activation: "relu", kernelInitializer: "varianceScaling", }), ); model.add( tf.layers.maxPool2d({ poolSize: [2, 2], strides: [2, 2], }), ); //flatten层用于将多维的特征数据,转换为一维的分类数据,传入dense层 model.add(tf.layers.flatten()); model.add( tf.layers.dense({ units: 10, //最终输出0-9十个分类 activation: "softmax", kernelInitializer: "varianceScaling", }), ); </code></pre> <h2>训练模型</h2> <pre><code>//训练参数 model.compile({ loss: "categoricalCrossentropy", //交叉熵损失函数 optimizer: tf.train.adam(), //优化器 metrics: ["accuracy"], //准确度度量 }); //训练集数据 const [trainXs, trainYs] = tf.tidy(() =&gt; { const d = data.nextTrainBatch(1000); return [d.xs.reshape([1000, 28, 28, 1]), d.labels]; }); //验证集数据 const [testXs, testYs] = tf.tidy(() =&gt; { const d = data.nextTestBatch(200); return [d.xs.reshape([200, 28, 28, 1]), d.labels]; }); //训练 await model.fit(trainXs, trainYs, { validationData: [testXs, testYs], batchSize: 500, epochs: 50, callbacks: tfvis.show.fitCallbacks( { name: "训练效果" }, ["loss", "val_loss", "acc", "val_acc"], { callbacks: ["onEpochEnd"] }, ), }); </code></pre> <ul> <li>训练效果: <img src="/images/ai/60.png" alt="卷积训练" /></li> </ul> <h2>使用模型预测识别canvas绘制数字</h2> <ul> <li>html:</li> </ul> <pre><code>&lt;script src="script.js"&gt;&lt;/script&gt; &lt;canvas width="300" height="300" style="border: 2px solid #666;"&gt;&lt;/canvas&gt; &lt;br&gt; &lt;button onclick="window.clear();" style="margin: 4px;"&gt;清除&lt;/button&gt; &lt;button onclick="window.predict();" style="margin: 4px;"&gt;预测&lt;/button&gt; </code></pre> <ul> <li>js:</li> </ul> <pre><code>const canvas = document.querySelector("canvas"); canvas.addEventListener("mousemove", (e) =&gt; { if (e.buttons === 1) { const ctx = canvas.getContext("2d"); ctx.fillStyle = "rgb(255,255,255)"; ctx.fillRect(e.offsetX, e.offsetY, 25, 25); } }); //黑底画板 window.clear = () =&gt; { const ctx = canvas.getContext("2d"); ctx.fillStyle = "rgb(0,0,0)"; ctx.fillRect(0, 0, 300, 300); }; clear(); </code></pre> <ul> <li>进行预测:</li> </ul> <pre><code>window.predict = () =&gt; { const input = tf.tidy(() =&gt; { return tf.image .resizeBilinear( //转换图像tensor尺寸 tf.browser.fromPixels(canvas), //canvas转换为tensor [28, 28], //转换成28*28 true, ) .slice([0, 0, 0], [28, 28, 1]) //canvas图片是彩色图片,通过slice转换为黑白图片 .toFloat() //训练数据进行过归一化,因此预测值也要归一化 .div(255) //归一化 .reshape([1, 28, 28, 1]); //和神经网络第一层的输入格式统一 }); const pred = model.predict(input).argMax(1); alert(`预测结果为 ${pred.dataSync()[0]}`); }; </code></pre> <p><img src="/images/picgo/001.gif" alt="预测效果" /></p> <hr /> <p>&lt;small&gt;总结:这一节有两个难点,一是卷积神经网络的构建,重在理解图像卷积核;二是图像与tensor格式的转换,需要多加练习与斟酌;&lt;br/&gt; 本地训练结果正确率大概70%,可以通过增加训练集数据和训练次数来提升效果&lt;/small&gt;</p> <hr /> <p><a>代码仓库</a></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/fed_ml_10_handwriting_number/#post-comment/</comments>
</item>
<item>
<title>ML09 | 欠拟合&过拟合</title>
<link>https://www.scarsu.com/fed_ml_09_underoverfitting/</link>
<guid isPermaLink="true">https://www.scarsu.com/fed_ml_09_underoverfitting/</guid>
<description>Javascript玩转机器学习09</description>
<pubDate>Fri, 24 Apr 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>欠拟合</h2> <ul> <li>数据过于复杂,但是神经网络模型过于简单</li> </ul> <p><img src="/images/ai/47.png" alt="underFitting" /></p> <ul> <li>无论训练多久,训练损失始终降不下去</li> </ul> <p><img src="/images/ai/46.png" alt="underFitting" /></p> <h2>过拟合</h2> <ul> <li>模型过于复杂,把训练集噪声数据都拟合进去</li> </ul> <p><img src="/images/ai/48.png" alt="overFitting" /></p> <ul> <li>过拟合损失曲线,红色代表验证集,蓝色代表训练集</li> </ul> <p><img src="/images/ai/49.png" alt="overFitting" /></p> <p><img src="/images/ai/50.png" alt="overFitting" /></p> <h2>实操模拟 欠拟合&amp;过拟合</h2> <ul> <li>加载带有噪音的二分类数据集(训练集与验证集)</li> <li>使用不同神经网络演示 过拟合&amp;欠拟合</li> <li>过拟合应对法:早停法、权重衰减、丢弃法</li> </ul> <h2>加载带有噪音的二分类数据集(训练集与验证集)</h2> <h4>脚本原理</h4> <p>生成正态分布(高斯分布)的样本数据</p> <pre><code>function normalRandom(mean = 0, variance = 1) { let v1, v2, s; do { v1 = 2 * Math.random() - 1; v2 = 2 * Math.random() - 1; s = v1 * v1 + v2 * v2; } while (s &gt; 1); let result = Math.sqrt((-2 * Math.log(s)) / s) * v1; return mean + Math.sqrt(variance) * result; } </code></pre> <p>正态分布两边低的数据看作噪音数据,中间高的数据视为正常数据</p> <p>通过调整方差 调整噪音量</p> <h4>用脚本生成带有噪音的二分类数据集</h4> <pre><code>import * as tf from "@tensorflow/tfjs"; import * as tfvis from "@tensorflow/tfjs-vis"; import { getData } from "./data"; window.onload = async () =&gt; { const data = getData(200, 3); }; </code></pre> <h4>可视化数据集</h4> <pre><code>tfvis.render.scatterplot( { name: "训练数据" }, { values: [ data.filter((p) =&gt; p.label === 1), data.filter((p) =&gt; p.label === 0), ], }, ); </code></pre> <p><img src="/images/ai/51.png" alt="可视化结果" /></p> <h2>使用不同神经网络演示 过拟合</h2> <pre><code>const data = getData(200, 2); tfvis.render.scatterplot( { name: "训练数据" }, { values: [ data.filter((p) =&gt; p.label === 1), data.filter((p) =&gt; p.label === 0), ], }, ); const model = tf.sequential(); //第一层隐藏层 model.add( tf.layers.dense({ units: 10, inputShape: [2], //长度为2的一维数组 activation: "tanh", }), ); //输出层 model.add( tf.layers.dense({ units: 1, activation: "sigmoid", }), ); //设置损失函数&amp;优化器 model.compile({ loss: tf.losses.logLoss, optimizer: tf.train.adam(0.1), }); const inputs = tf.tensor(data.map((p) =&gt; [p.x, p.y])); const labels = tf.tensor(data.map((p) =&gt; p.label)); await model.fit(inputs, labels, { validationSplit: 0.2, epochs: 200, callbacks: tfvis.show.fitCallbacks( { name: "训练效果" }, ["loss", "val_loss"], { callbacks: ["onEpochEnd"] }, ), }); </code></pre> <p><img src="/images/ai/52.png" alt="过拟合训练结果" /></p> <h2>过拟合应对法:早停法</h2> <p>在训练出现过拟合时及时手动停止训练</p> <h2>过拟合应对法:权重衰减法(设置L2正则化</h2> <p>将过于复杂的模型权重降低</p> <pre><code>model.add( tf.layers.dense({ units: 10, inputShape: [2], //长度为2的一维数组 activation: "tanh", kernelRegularizer: tf.regularizers.l2({ l2: 1 }), //设置权重衰减 }), ); </code></pre> <p><img src="/images/ai/54.png" alt="权重衰减法训练结果" /></p> <h2>过拟合应对法:丢弃法</h2> <p>在隐藏层和输出层之间添加一个丢弃层</p> <pre><code>//添加丢弃层,降低训练集复杂度 model.add(tf.layers.dropout({ rate: 0.9 })); </code></pre> <p><img src="/images/ai/53.png" alt="丢弃法训练结果" /></p> <hr /> <p><a>代码仓库</a></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/fed_ml_09_underoverfitting/#post-comment/</comments>
</item>
<item>
<title>Notion为什么能让我放弃手帐</title>
<link>https://www.scarsu.com/e_journal_by_notion/</link>
<guid isPermaLink="true">https://www.scarsu.com/e_journal_by_notion/</guid>
<description>自我管理,记录,自省,用意识控制生活,而非本能</description>
<pubDate>Sun, 12 Apr 2020 00:00:00 GMT</pubDate>
<content:encoded><p>今天在逛今日热榜的时候,看到了一篇知乎的文章<a>“我的最后一款笔记应用-Notion”</a>,是种草notion的。</p> <p><img src="/images/notion/header.png" alt="Notion/header.png" /></p> <p>一两年前notion刚火的时候,因为被其极简可爱的颜值吸引,我试用过一次,那时候我已经是“有道云笔记”的深度用户了,备份类、笔记类、小应用类、电子书类、代码类全都放在有道云笔记上,开了年会员加持,容量大、网速稳定、体验感功能性都没有缺陷,觉得notion仅仅适合做笔记、做管理,并不适合我从有道云笔记转型,而且刚刚起步的产品,还有这很多细节上体验不好的地方。</p> <p>直到今天,notion这款应用又重新进入我的视野,我被吸引了。</p> <p>原因是,近两年来,我一直在尝试用<a>手帐</a>的方式去做自我管理:每年都要换本子,重新set up年目标、年总结、影单、书单、学习路径、愿望清单、资产、习惯、体重等等的追踪记录,每个月也要做set up的工作,包括月封面、月历、周历、每日记录......</p> <p>即使中间我从普通手帐,转型到了最简洁的Bullet Journal,差别也仅仅是风格变成了极简,不需要花哨的涂涂画画,但也需要耗时耗精力的精心维护,花了很多时间在重复的工作:重复的画track表格、画年历月历、每年新建一些需要长期维护的项目(例如愿望清单、书单影单都不适合以年为维度记录,我更倾向于认为这些是需要以人生为维度去记录积累的),还需要每天带着一堆文具和厚厚的一个本子。</p> <p>低效、冗余、耗精力这些弊端都一直是我的心头草,仅仅是靠着对手帐的兴趣才维持了两年时间。</p> <p>两年后再接触到notion,又有了新的体验,这两年notion团队做出了卓越的努力,不断的优化更新,让当初新露头角毛毛糙糙的notion,在用户体验上有了华丽变身,更细致,更贴近用户,客户端也全端兼容了。</p> <p>当然,对于我来说,notion的亮点不光在于颜值和用户体验,更重要的,是它的“模块化”的思想,设计新颖又实用的“数据库”模式,文档(Notion Page)之间的灵活链接,以及对<strong>markdown</strong>的友好支持。</p> <p>模块化思想,把整个文档拆分成“块”(block),可以随意拖动排版,所有“块”都支持30多种媒体类型,包括文字、标题、多种list、文档链接(Notion Page)、团队成员、日期/提醒、图片视频、地图、Github Gist片段、数据库链接等等,这些特性让Notion既灵活又功能丰富。</p> <p>数据库模式,可以在一张数据表上保留所有数据记录。以表格、看板、画廊、日历等视图展现,一次创建,多处引用。例如创建一张待办事项表,就可以通过简单的引用数据表+新增视图+筛选,展现出“今日待办事项、团队协作看板、待办日历”等视图。例如创建一张财务收支表,可以展现出“年收入支出、月收入支出、支出类别占比”等视图,这些特性让Notion既高效又细致入微。举个栗子:以下的三张表其实都是同一张数据源。</p> <p><img src="/images/notion/ds.png" alt="Notion/数据库模式" /></p> <p>页面之间的灵活链接,使Notion跳出了“以文件夹格式逐层管理“的固定模式,用户完全可以创建一张灵活排布的目录Page,任意设计分类、排版、跳转。例如我的手帐主页:</p> <p><img src="/images/notion/home.png" alt="Notion/页面灵活排版" /></p> <hr /> <p>最后,我的示例和观点,只展示出了星星点点的用法,还有更多有意思的用法,等待开发~</p> <p>这是我的<a>邀请链接</a>,欢迎注册使用Notion</p> <hr /> <p>注:关于手账的意义:</p> <ul> <li>自我管理,自我规划,自律</li> <li>记录、温习回忆</li> <li>自省</li> <li>记录、调节情绪,解压</li> <li>用意识控制生活,而非本能</li> </ul> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/e_journal_by_notion/#post-comment/</comments>
</item>
<item>
<title>Devtools 老司机养成 - 番外篇 - Devtools中的”VM“</title>
<link>https://www.scarsu.com/vm_in_devtools/</link>
<guid isPermaLink="true">https://www.scarsu.com/vm_in_devtools/</guid>
<description>为什么经常有脚本的“文件名”是"[VM](XXXX "??</description>
<pubDate>Mon, 06 Apr 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>引言</h2> <p>What are those strange and mysterious scripts titled "[VM](XXXX " and where do they come from?</p> <h2>what's vm(xxxx)</h2> <p><a>VM</a> has no special meaning. It's a dummy name to help us to distinguish code which are not directly tied to a file name, such as code created using eval and friends.</p> <p>为了标识不能和具体文件直接关联的脚本的虚拟名称,并不是真正的文件,例如 eval 方法所执行的脚本、匿名函数,脚本会被抛入Chrome调试器虚拟机中</p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/vm_in_devtools/#post-comment/</comments>
</item>
<item>
<title>Devtools 老司机养成 - 第七篇- Memory 内存</title>
<link>https://www.scarsu.com/devtools_07_memory/</link>
<guid isPermaLink="true">https://www.scarsu.com/devtools_07_memory/</guid>
<description>你开的网页会卡吗?来Memory面板了解一下内存分析&内存泄漏</description>
<pubDate>Sun, 05 Apr 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>内存 &amp;&amp; 内存泄露</h2> <p>内存占用:</p> <ol> <li>allocate 分配内存(eg 声明变量</li> <li>使用内存</li> <li>release 释放内存</li> </ol> <p>内存泄漏:</p> <ul> <li><code>内存泄露-Memory Leak</code>:内存被占用后无法被 release,且无法被垃圾回收器回收</li> <li>内存泄漏会引起性能问题,且时间越久越严重,因为被占用且无法回收的内存只会增加不会减少</li> <li><code>垃圾回收-Garbage Collect-GC</code>:浏览器收回内存。 浏览器决定何时进行垃圾回收。 回收期间,所有脚本执行都将暂停。因此,如果浏览器经常进行垃圾回收,脚本执行就会被频繁暂停</li> </ul> <h2>造成内存泄露常见原因</h2> <ul> <li><code>fogotten timer</code>被遗忘的计时器:例如调用 setInterval()方法一定要加结束条件</li> <li><code>Dettached HTMLElement</code>分离的 dom 节点:在 dom 被移除后,dom 变量仍然存在</li> </ul> <h2>内存监控 1-Task manager 任务管理器</h2> <ul> <li>chorme 浏览器 -&gt; task manager 任务管理器工具中,可以监控每个 tab 页的 js 内存占用大小</li> </ul> <p><img src="https://i.loli.net/2019/05/07/5cd194ba3a655.png" alt="" /></p> <ul> <li><code>Memory</code> 列表示原生内存。DOM 节点存储在原生内存中。 如果此值正在增大,则说明正在创建 DOM 节点。</li> <li><code>JavaScript Memory</code>列表示 JS 堆。此列包含两个值。 实际大小表示页面上的对象正在使用的内存量。 如果此数字在增大,要么是正在创建新对象,要么是现有对象正在增长。</li> </ul> <h2>内存监控 2-Devtools Performance 面板</h2> <ul> <li>在<code>Performance</code>面板记录性能时,勾选<code>memory</code>即可在分析结果中看到 memory 占用情况</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccee6f4b968d.png" alt="" /></p> <pre><code>//示例1:正常的内存占用与GC var x = []; function grow() { for (var i = 0; i &lt; 10000; i++) { document.body.appendChild(document.createElement("div")); } x.push(new Array(1000000).join("x")); } setInterval(grow, 100); </code></pre> <p><img src="https://i.loli.net/2019/05/07/5cd19db41fbbc.png" alt="" /></p> <pre><code>//示例2:不可被GC的内存泄漏 function grow() { // for (var i = 0; i &lt; 10000; i++) { // document.body.appendChild(document.createElement("div")); // } // x.push(new Array(1000000).join("x")); var ul = document.createElement("ul"); for (var i = 0; i &lt; 10; i++) { var li = document.createElement("li"); ul.appendChild(li); } detachedTree = ul; } setInterval(grow, 1000); </code></pre> <p><img src="https://i.loli.net/2019/05/07/5cd1a62aa1bfd.png" alt="" /></p> <h2>内存监控 3-Devtools Memory 面板</h2> <p><img src="https://i.loli.net/2019/05/07/5cd18fa5d8489.png" alt="" /></p> <ul> <li>如上图所示,在右侧三种内存分析模式选择一种后,即可点击左上角<code>record</code>开始记录内存</li> </ul> <ol> <li><code>Heap snapshot</code>堆快照,记录当前时间点内存中页面 js 对象和 dom 节点的分配情况</li> <li><code>Allocation instrumentation on timeline</code>按时间轴记录内存,可以选记录内存分配调用栈(可以帮助定位到具体分配内存的源码)</li> <li><code>Allocation sampling</code>使用抽样方法记录内存分配。具有最小的性能开销,可用于长时间运行的操作。提供了由 JavaScript 执行堆栈细分的良好近似分配。</li> </ol> <ul> <li> <p>左上角的垃圾桶图标<code>Collect garbage</code>是强制执行一次垃圾回收,内存监控的最佳实践是在监控内存前执行一次强制垃圾回收</p> </li> <li> <p>利用上述示例 2 代码,执行时间线 Memory 分析:</p> </li> </ul> <p><img src="https://i.loli.net/2019/05/07/5cd1a7db0cfe0.png" alt="" /></p> <h2>扩展</h2> <ul> <li><a>内存相关术语</a></li> <li><a>深入内存分析</a></li> </ul> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/devtools_07_memory/#post-comment/</comments>
</item>
<item>
<title>Devtools 老司机养成 - 第六篇 Performance 性能面板</title>
<link>https://www.scarsu.com/devtools_06_performance/</link>
<guid isPermaLink="true">https://www.scarsu.com/devtools_06_performance/</guid>
<description>中高级前端都应该懂的性能分析&优化,都在Performance面板</description>
<pubDate>Sun, 29 Mar 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>Performance面板概览</h2> <ul> <li>performance 面板可以用于分析<code>运行时性能</code>(运行时强调的是与页面加载性能相区分)</li> <li>以隐身模式打开网页 (隐身模式可确保 Chrome 以干净的状态运行。例如,排除扩展对性能测量的影响</li> <li><a>Junky Animation demo :性能测试 demo</a></li> <li>视图 overview:</li> </ul> <p><img src="https://i.loli.net/2019/04/23/5cbf1d586fe21.png" alt="performance.png" /></p> <h2>RAIL 模型</h2> <ul> <li> <p><a>RAIL 模型</a>是一种性能模型,定义了四个维度的性能分析指标</p> </li> <li> <p><code>Response</code>:在<code>100 毫秒</code>以内响应(例如从点按到绘制)</p> </li> <li> <p><code>Animation</code>: 每秒生成 60 帧,每个帧的工作(从 JS 到绘制)完成时间小于 16 毫秒,达到人眼顺滑(例如滚动 拖动都是动画类型)(因为浏览器需要花费时间将新帧绘制到屏幕上,只有 <code>10 毫秒</code>来执行代码)</p> </li> <li> <p><code>Idle</code>:利用空闲时间完成推迟的工作(要实现第一条 response 在 100ms 内响应,Main 主线程 JS 工作应该小于 <code>50ms</code>,剩余的时间将主线程的控制从 js 返回给浏览器执行其像素管道、对用户输入作出反应等,因此最佳实践是将 js 的工作分成不大于 50 毫秒的块,如果用户开始交互,优先级最高的事项是响应用户。</p> </li> <li> <p><code>Load</code>:在 <code>1000 毫秒</code>以内呈现内容(无需完整加载,启用渐进式渲染,将非必需的加载推迟到空闲时间段</p> </li> <li> <p>通过 performance 面板,可以得到这四个维度的分析数据</p> </li> </ul> <h2>控制区</h2> <p><img src="https://i.loli.net/2019/05/01/5cc9642fa35b5.png" alt="" /></p> <ul> <li>点击<code>录制按钮</code>或者<code>开始录制并刷新页面按钮</code>,可以在控制区下方得到全部性能分析结果</li> <li>其中除了最下方的详细信息窗格以外,分析结果都是以时间为轴</li> <li>可以在 overview 窗格拖动鼠标,选择某段时间的分析结果</li> <li>滚动鼠标滚轮,缩放/移动选中事件</li> <li>在火焰图窗格,按住<code>shift</code>,滚动鼠标滚轮,可以上下</li> <li>在火焰图窗格,也可以直接左右拖动图表</li> <li>或者用<code>W A S D</code>按键控制缩放移动</li> <li><code>Disable JavaScript samples</code>默认情况,在<code>Main</code>主线程的火焰图中,会详细记录 js 函数之间的调用栈,可以开启此选项禁用调用栈记录</li> <li><code>Enable advanced paint instrumentation</code>启用高级绘图工具,可以在分析结果的<code>Frames</code>中的每一帧的详细结果中看到<code>Layer</code>选项卡,其中有选中帧的详细图层信息;也可以在<code>Main</code>主线程火焰图中选中绿色的<code>Paint</code>事件,在最底部详细信息的<code>Paint Profile</code>选项卡中,看到详细的页面绘制过程分析</li> <li><code>Collect garbage</code>控制器最右的垃圾桶图标,是强制执行垃圾回收,对于监控内存比较有用</li> </ul> <h2>FPS 图表 - Frames Per Seconds</h2> <p><img src="https://i.loli.net/2019/05/05/5ccee0f3335be.png" alt="" /></p> <ul> <li>FPS 图表中,绿色代表帧率高低,参考<code>RAIL</code>模型,帧率&gt;=60 时,用户能体验的顺滑的网页</li> <li>红色出现 代表有掉帧情况</li> </ul> <h2>CPU 图表</h2> <p><img src="https://i.loli.net/2019/05/05/5ccee13cd4479.png" alt="" /></p> <ul> <li>CPU 图表中,不同的颜色代表不同事件对 CPU 的占用,颜色信息如图</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccee05903554.png" alt="" /></p> <ul> <li>当 CPU 长时间被占满,就是当前网页性能需要优化的信号</li> </ul> <h2>SCREENSHOTS</h2> <ul> <li>鼠标在<code>FPS,CPU,NET</code>图表悬浮时,会展示出鼠标对应时间点的网页截屏,左右移动鼠标可以看到网页变化的重播效果</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccee37b9a4b3.gif" alt="" /></p> <h2>HEAP</h2> <p><img src="https://i.loli.net/2019/05/05/5ccee6f4b968d.png" alt="" /></p> <ul> <li>在 HEAP 图表中可以看到 JS 内存占用情况,与下方的 memory 窗格中的<code>JS Heap</code>相对应</li> <li>在 Memory 窗格还可以看到 Document 文档、Nodes DOM 节点、监听器、GPU 内存的习份内存统计</li> </ul> <h2>Frames</h2> <ul> <li>点击三角箭头展开<code>Frames</code>区域,鼠标悬浮/点击绿色方块,可以看到该特定帧的帧率和渲染耗时,当 FPS 低于 60,表明当前帧的渲染效率较低</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccee92a52b29.png" alt="" /></p> <h2>FPS 仪表工具</h2> <ul> <li>通过<code>more -&gt; more tools -&gt; Rendering</code> 或者 <code>ctrl+shift+p -&gt; rendering</code> 打开<code>Rendering</code>面板</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccee9d226d2e.png" alt="" /></p> <ul> <li>启用<code>FPS meter</code>,即可看到的页面实时帧率</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5cceeb3144e12.gif" alt="" /></p> <h2>Mian</h2> <ul> <li>点击三角箭头展开<code>Main</code>区域,可以看到主线程上事件的<code>火焰图</code></li> <li>x 轴是时间,每一块代表一个事件,y 轴代表堆栈,事件的上下堆叠,代表上层事件引发/调用了下层事件</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5cceec8b11f7f.png" alt="" /></p> <ul> <li>通过调用堆栈,可以找出导致低性能的事件及其源码位置</li> <li>当事件块出现红色三角,可以点击三角查看该事件的性能相关警告信息,并定位到引起警告的代码</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5cceef6801439.png" alt="" /></p> <p><img src="https://i.loli.net/2019/05/05/5ccef1a7c2c2a.gif" alt="" /></p> <ul> <li>点击<code>Animation Frame Fired</code>事件,可以在最下方<code>Summary</code>窗格查看触发动画事件的详细信息,点击<code>Initiator</code>后的<code>reveal</code>链接,会高亮到引起动画事件的事件</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccef012a3dba.gif" alt="" /></p> <h2>性能相关扩展</h2> <ul> <li><a>网页性能-性能模型/加载/渲染/审计/优化</a></li> <li><a>the-anatomy-of-a-frame - 一个帧的剖析</a></li> <li><a>常见的时间线事件参考</a></li> </ul> <h2>浏览器并发请求数</h2> <ul> <li> <p>现象: 同一时间针对同一域名下的请求有一定数量限制。超过限制数目的请求会被阻塞。</p> </li> <li> <p>原因: 基于端口数量和线程切换开销的考虑,浏览器不可能无限量的并发请求。</p> </li> <li> <p>导致: 有大量请求的站点,响应较慢,因为并发请求会被阻塞。</p> </li> <li> <p><img src="https://i.loli.net/2019/07/29/5d3e56236ee0b54748.png" alt="不同浏览器的限制数" /></p> </li> <li> <p>解决方法:</p> <ol> <li> <p>用不同域名(hash domain,cookie free) 例如知乎的图片都是放在zhiimg.com域名下获取的。 cookie free是指,例如知乎主站zhihu.com域名下有很多cookie,换成zhihuimg.com请求图片时,就不会把zhihu上的cookie发过去,减小所需带宽。</p> </li> <li> <p>减少请求数 雪碧图 合并压缩css/js(另一个原因是为了减少重绘) 利用Cache-Control等缓存静态资源,在更新静态资源时使用不同url或文件名带上版本 懒加载,出现再加载</p> </li> </ol> </li> </ul> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/devtools_06_performance/#post-comment/</comments>
</item>
<item>
<title>别做正常的傻瓜:让你的每一个行为都得到最优解</title>
<link>https://www.scarsu.com/behavior_decision/</link>
<guid isPermaLink="true">https://www.scarsu.com/behavior_decision/</guid>
<description>豆瓣8.1的行为决策学入门书籍,通过心理学原理、一些实验数据,指出了常人的一些决策误区,以及如何达到决策理性,让你的每一个行为都得到最优解。</description>
<pubDate>Fri, 27 Mar 2020 00:00:00 GMT</pubDate>
<content:encoded><p><img src="//images/picgo/behavior.jpg" alt="题图" /></p> <h2>简介</h2> <p>作者:奚恺元(Christopher K.Hsee)生长于中国上海,后旅美求学,1993年获耶鲁大学博士学位,现为芝加哥大学商学院终身教授(chair professor)。</p> <p>他是当代最有成就的行为决策学研究者之一,其研究涉及心理学、行为经济学,管理学、市场学以及幸福学等诸多领域。</p> <p>他的著作在许多国际期刊上发表,2002年诺贝尔经济学奖得主卡尼曼教授在他的获奖致辞中还特别提到了奚教授的研究贡献。</p> <p>在北美和中国,他被许多一流大学邀请做过演讲。并广受好评,奚教授有十多年的管理教学经验,他在芝加哥大学开设的管理决策课程备受欢迎。</p> <p>这本书是<a>豆瓣8.1</a>的<strong>行为决策学</strong>入门书籍。</p> <p>通过心理学原理、一些实验数据,指出了常人会犯的一些决策错误,以及如何达到决策理性,让你的每一个行为都得到最优解。</p> <h2>TL; DR —— 先看总结</h2> <p>这是我从3月28号开始,用了接近两个月时间看完的一本书。</p> <p>总体来说,这本书并没有很强的系统性,不需要建立知识体系,比较适合<strong>碎片阅读</strong>。</p> <p>书中十几章内容,分别介绍了不同的决策误区,误区产生背后的心理学原理,以及如何应对。</p> <p>书中介绍的一些理论,比如<strong>人类心理账户及其对行为的影响</strong>、<strong>消费决策只应该考虑<code>成本=&gt;价值</code></strong>、<strong>边际递减效应</strong>、<strong>适应性偏见</strong>、<strong>第一印象相关的定位偏见</strong>、<strong>联合评估与单独评估的选择</strong>...都能对实际生活中的决策起到实际性的、可行的理论指导。</p> <p>书中介绍的决策误区,都是<strong>常人会有</strong>的,因为从原理上来看,是人类的<strong>本性使然</strong>。</p> <p>但是如果能了解这些误区,知道自己可能犯的错误,就能及时的检视自己,从而做出更多理性的决策。</p> <p>所以总结来说,这本书还是值得一看的✨。</p> <h2>1. 10元等于两个5元吗? —— <strong>心理账户&amp;决策一致性</strong></h2> <ul> <li> <p>心理账户对行为的影响 在我们的日常生活中,经常需要做各种各样的决策,在做决策的时候,我们总是为求做到理性,以尽可能地使我们的收益最大化。如何成为一名理性的决策者呢?一名理性的决策者究竟需要具备怎样的基本素质呢?</p> </li> <li> <p>由于心理账户的存在,正常人常有一些误区:</p> <ol> <li>将等价的钱,根据来源/时间/用途不同,打上不同标记</li> <li>赌场盈利效应:赢来的钱更倾向于高风险投资</li> <li>把赢来的钱消费掉,把赚来的钱存起来</li> <li>大钱小花,小钱大花</li> </ol> </li> <li> <p>心理账户,导致了行为决策不具有一致性</p> </li> <li> <p>应该:让钱在不同心理账户之间流通</p> </li> <li> <p>应该:等价的钱,不因为来源/时间/用途不同而打上不同标记</p> </li> </ul> <h2>2. 你会买没用的东西吗? —— <strong>消费决策的误区</strong></h2> <ul> <li>消费决策中常见的误区 我们购买一样东西,衡量是该物品给我们带来的效用和它的价格,然后看是不是值得购买,可是在我们做购买决策的时候,往往会受到交易效用偏见、比例偏见和适应偏见的影响,从而做出不理性的消费决策行为。</li> <li>做交易决策的无关参考值: <ul> <li>参考价-实际价格</li> <li>优惠比例</li> <li>历史促销价格</li> </ul> </li> <li>做决策,不应受到<strong>成本-&gt;价值</strong>外的其他任何因素影响</li> <li>不因为成本过高而不买有价值的东西,也不因为成本低而买不需要的东西</li> </ul> <h2>3. 坚持到底一定是胜利吗? —— <strong>沉没成本</strong></h2> <ul> <li><strong>沉没成本</strong>:已经无法收回的支出</li> <li>沉没成本误区 人们在决定是否去做一件事的时候,不仅是看这件事对自己有没有好处,而且也看过去已经在这件事情上面有过投入,很多人去挽回已经发生却无法挽回的所谓的成本而做出很多不理性的行为。</li> <li>应该<strong>及时止损</strong></li> <li>应该根据<strong>将来会不会有好处</strong>做决策</li> <li>不让沉没成本困住前进的步伐</li> <li><strong>保本</strong>是错误观念</li> </ul> <h2>4. 你有自知之明吗? —— <strong>过于自信与自知</strong></h2> <blockquote> <p>知人者智,知己者明</p> </blockquote> <ul> <li>绝大多数人,都有过于自信的问题,很多时候,人们并不如自己想象的那么优秀。</li> <li>做出好的决策,不光要有知识,还要有“知识的知识”,也就是自知:知道自己的知识有哪些局限,哪些是准确的,哪些的需要质疑的</li> <li><strong>证实偏见</strong>:为自己的观点找理由,只关注自己观点一致的证据,不关注不收集与自己决策相对立的证据</li> <li>过于自信的一个例子:<strong>不上相</strong>,潜台词就是“我本人长得很美丽,只是照片没有把这些体现出来”,但是事实上,照片是真实的,你本人就是和照片上一样丑</li> </ul> <p>过于自信的优点:</p> <ul> <li>使人积极开心</li> <li>产生“自我实现预言”效应,即产生良性的心理暗示,引导好的结果</li> <li>过于自信的人,不会太拘泥于细节,善于抓住问题的大方向</li> </ul> <p>过于自信的缺点:</p> <ul> <li>规划误区:过于自信,对问题或任务轻视,导致延期等规划不合理的问题</li> <li>对自己的金融知识与判断过于自信会导致在金融市场过于频繁交易(越频繁交易,损失越大</li> <li>打无准备之仗,松懈,持侥幸心理</li> </ul> <p>应该怎么做:</p> <ul> <li>避免证实偏见,为自己决策的对立面寻找证据,两相比较</li> </ul> <h2>5. 你会习以为常吗?—— <strong>适应性偏见</strong></h2> <ul> <li><strong>适应性</strong>:人类对外界的刺激,会随着时间的推移而减弱。(是普遍存在的现象</li> <li><strong>适应性偏见</strong>:人类<strong>低估</strong>自己的适应性,从而高估某些事情在一段时间后对自己的影响。</li> <li><strong>适应性偏见例子</strong>:人类以为物质条件的提升,会给自己带来长久的快乐,但其实很快就会适应。</li> </ul> <p><strong>三类难以适应的东西</strong>:</p> <ul> <li>极端的东西</li> <li>人际比较</li> <li>变化</li> </ul> <p><strong>如何对待适应性偏见</strong>:</p> <ul> <li>了解自己对物质性东西的适应性</li> <li>不要对物质看得过重,有过高期望</li> <li>多关注精神和心灵层面的东西</li> </ul> <h2>6. 存银行还是买股票? —— <strong>风险决策</strong></h2> <p><strong>数学期望值</strong> = 选项的价值✖选项的概率</p> <p><strong>期望值理论</strong>:做决策时,选期望值最大的选项</p> <ul> <li><strong>风险中性</strong>:期望值相同的情况,对风险大小无所谓</li> <li><strong>风险规避</strong>:期望值相同的情况,偏好于风险小收益小</li> <li><strong>风险喜好</strong>:期望值相同的情况,偏好与风险大收益大</li> </ul> <p><strong>效用</strong>:指消费者从某商品中得到的满足感(主管衡量)</p> <p><strong>边际效用递减</strong>:一种普遍规律,随消费的增多,消费者从每个单位产品的消费中得到的<strong>效用</strong>逐渐递减。(与上一章所讲的适应性有一定关联)</p> <p><strong>风险规避</strong>与<strong>边际效用递减</strong>:边际效用递减是风险规避的理论依据</p> <p><strong>期望效用理论</strong>:</p> <ul> <li>选择效用最大的选项</li> <li>计算方法:某选项的<strong>效用</strong> ✖ 概率</li> <li>效用的计算:由于边际递减规律,其计算可以选择求根函数,把选项的价值作为参数</li> </ul> <p><strong>前景理论</strong>:最贴合现实中人类的选择</p> <ul> <li>在<strong>得到</strong>时,倾向于风险规避</li> <li>在<strong>失去</strong>时,倾向于风险喜好</li> <li>参照点的不同,会影响人类对于<strong>得失</strong>的判断</li> <li>通常遵循:损失规避(下一章会讲到)</li> </ul> <p>三种风险决策的理论依据:</p> <ul> <li>期望值理论(由于边际效用递减而不准确)</li> <li>期望效用理论(最为理性)</li> <li>前景理论(最贴近现实中人类的风险决策的理论)</li> </ul> <h2>7. 损失100元和得到100元,哪个对你影响更大? —— <strong>损失规避</strong></h2> <p><strong>损失规避</strong>:同样的东西,失去它所经历的痛苦程度,大于得到它所经历的高兴程度:|U(-x)|&gt;&gt;|U(x)|(得失不对称性)</p> <p><strong>投资决策的两个心理账户问题</strong>:</p> <ul> <li>短时间内评价一个账户的盈亏(不要频繁查看投资账户)</li> <li>把股票账面上的损失,和股票下跌变现的损失,划分到不同的心理账户</li> </ul> <p><strong>赋予效应</strong>: 同样的东西,得到时觉得不值钱,拥有了再放弃时就会感到其重要性(eg.无条件退款的营销策略就是利用了这个效应)</p> <p><strong>安于现状</strong>: 由于赋予效应,人们把现在拥有的东西加上了很高的价值,不愿意做决策去改变现状</p> <p><strong>语义效应</strong>: 用不同语义描述同一件事时,就会做出不同的决策,把一件事描述成“得”或“失”,可以有效的改变人们的选择</p> <h2>8. 损失100元和没有得到100元,那个让你更心痛? —— <strong>未得收益</strong></h2> <ul> <li>未得收益和直接损失,从理性的角度来看是一样的,未得收益应该得到重视</li> <li>盗版知识产品=&gt;也是对知识产权所有者未得收益的损害</li> </ul> <h2>9. 谈判中应该让对方先开价吗? —— <strong>定位调整偏见</strong></h2> <ul> <li><strong>定位效应</strong>:你对某人某事的<strong>第一印象</strong>就是一种可以定位的 <strong>“锚”(anchor)</strong>,一旦定下来,后面接受的信息通常会受到这个锚的影响,这种影响很多情况下是不被察觉的。即使你会根据新的信息来调整自己的判断,但这种调整往往是不充分的,最后你的判断仍然很难逃出第一印象的圈子。</li> <li><strong>定位调整</strong>:大部分判断和决策都建立在不完整的信息基础上,通常我们会先找到一个相关联的信息,再根据这个信息去对决策进行调整。这个过程就是定位调整。通常由于受到定位效应的影响,定位调整是不充分的。</li> <li>怎么避免:首先意识到自己可能会受到<strong>定位效应</strong>的影响,再去判断我们的定位调整够不够充分。</li> <li><strong>“先入为主”的营销策略</strong>:商家将单品单价开的很高,再给出所谓的优惠。这个很高的价格就是一个锚,被定很高的位置,商家知道消费者会把这个价格往下调整,但是这个调整通常是不充分的,因此给了商家盈利的空间。</li> <li>谈判中利用定位效应: <ol> <li>争取先开价</li> <li>开价越极端越好</li> <li>在开价之前先提醒对方所开的价是荒唐的,给对方谈价空间</li> </ol> </li> </ul> <h2>10. 你的孩子会长多高? —— <strong>违背概率规律</strong></h2> <ul> <li> <p>集合规律:条件越多,交集越小</p> </li> <li> <p>先验概率:不因为眼前的信息而忽视客观分布</p> </li> <li> <p>赌徒谬论:好运和坏运不是交替发生的,是依照概率发生的</p> </li> <li> <p>中值回归规律:极端事物随时间发展都有往中值回归的趋势</p> </li> <li> <p><strong>可获得性误区</strong>:人们总是对易获得的、突出的信息印象深刻,所以认为其是普遍现象</p> </li> <li> <p><strong>反向调整法</strong>:做判断前,检视自身的可获得性误区,了解自己的局限性,扩展信息获取渠道,尝试做出调整</p> </li> </ul> <h2>11. 多一定比少号码? —— 联合评估 &amp; 单独评估</h2> <ul> <li><strong>联合评估</strong>:有参照物,特征被发现、对比、评估,容易找到有价值的、真正值得对比的特征</li> <li><strong>单独评估</strong>:无参照物;易受到一些容易评价&amp;不重要的因素影响;易受极端案例影响而忽视统计数据</li> <li>不要过度追求联合评:很多东西在我们的生活中的使用场景,都是单独评估</li> <li><strong>奚式相亲原则</strong>: <ul> <li>优势在联合评估时更突出</li> <li>敌强我弱;敌强我强 =&gt; 单独评估</li> <li>敌弱我弱;敌若弱我强 =&gt; 联合评估</li> </ul> </li> </ul> <h2>12. 抓住老鼠的一定是好猫吗? —— 结果偏见</h2> <ul> <li>通常情况,过程是难以衡量的,过程的信息不一定可靠,而结果是鲜明可靠的。我们应该尽量基于可靠的信息来做决策</li> <li>但结果并不是最好的评价因素,因为通常情况,过程是可控的,结果往往有很多不确定因素</li> <li>如何解决:给过程添加更多记录和监督机制</li> </ul> <h2>13. 钱越多越幸福吗? —— 财富与幸福</h2> <blockquote> <p>财富的多少和幸福的程度并不成正比</p> </blockquote> <p><strong>不增加财富却可以增加幸福感的一些原则</strong>:</p> <ul> <li>好事一起享受不如分开享受(依据边际递减效应</li> <li>坏事分开忍受不如一起忍受(依据边际递减效应</li> <li>大好事小坏事分开经历不如一起经历(负面效应会被正面效应所冲淡</li> <li>大坏事小好事一起经历不如分开经历(正面效应才不会被负面效应的痛苦所淹没</li> <li>好事晚说不如早说(等待好事的过程是多巴胺活跃的过程</li> <li>坏事早说不如晚说(等待坏事的过程是最消磨人意志的</li> <li>静止的好事不如变动的好事(依据人的适应性规律,并不能为相同的物质方面的东西快乐很久</li> <li>变动的坏事不如静止的坏事(原理同上</li> </ul> <hr /> <p>完结撒花✨🎉🎈🎈</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/behavior_decision/#post-comment/</comments>
</item>
<item>
<title>Devtools 老司机养成 - 第五篇- Network 面板</title>
<link>https://www.scarsu.com/devtools_05_network/</link>
<guid isPermaLink="true">https://www.scarsu.com/devtools_05_network/</guid>
<description>chrome最重要之二的Network面板,给后端小哥甩锅?实锤都在这里...</description>
<pubDate>Sun, 22 Mar 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>概览</h2> <p><img src="https://i.loli.net/2019/04/22/5cbd4f884b14c.png" alt="network.png" /></p> <ul> <li>默认情况下,只要 DevTools 处于打开状态,DevTools 就会在 Network 面板中记录所有网络请求。</li> <li>左上红点按钮:停止记录网络请求</li> <li>第二个按钮:清空请求记录</li> <li>录像按钮:页面加载时捕获屏幕截图</li> <li>过滤按钮:显示/隐藏 过滤条件行</li> <li>View 中的两个按钮:第一个是切换请求列表中每行的显示样式(大小请求行),第二个是显示/隐藏瀑布图</li> <li>Group By Frame:是否根据不同的 frame 分类显示请求</li> <li>Preserve Log:保存显示跨页面的加载请求</li> <li>Disable Cache:禁用浏览器缓存,模拟新用户打开页面的体验</li> <li>Offline 是模拟断网离线的状态,其后的下拉框可以选择模拟其他网络状况,比如 2G,3G</li> </ul> <h2>筛选请求</h2> <ul> <li>filter 文本框中可输入请求的属性 对 请求进行过滤,多个属性用空格分隔</li> <li>支持过滤的属性: <ul> <li>domain。 仅显示来自指定域的资源。 可以使用通配符字符 (<code>*</code>) 纳入多个域。 例如,*.com 将显示来自以 .com 结尾的所有域名的资源。 DevTools 会使用其遇到的所有域填充自动填充下拉菜单。</li> <li>has-response-header。 显示包含指定 HTTP 响应标头的资源。 DevTools 会使用其遇到的所有响应标头填充自动填充下拉菜单。</li> <li>is。 使用 is:running 可以查找 WebSocket 资源。</li> <li>larger-than。 显示大于指定大小的资源(以字节为单位)。 将值设为 1000 等同于设置为 1k。</li> <li>method。 显示通过指定 HTTP 方法类型检索的资源。 DevTools 会使用其遇到的所有 HTTP 方法填充下拉菜单。</li> <li>mime-type。 显示指定 MIME 类型的资源。 DevTools 会使用其遇到的所有 MIME 类型填充下拉菜单。</li> <li>mixed-content。 显示所有混合内容资源 (mixed-content:all),或者仅显示当前显示的资源 (mixed-content:displayed)。</li> <li>scheme。 显示通过未保护 HTTP (scheme:http) 或受保护 HTTPS (scheme:https) 检索的资源。</li> <li>set-cookie-domain。 显示具有 Set-Cookie 标头并且 Domain 属性与指定值匹配的资源。 DevTools 会使用其遇到的所有 Cookie 域填充自动填充下拉菜单。</li> <li>set-cookie-name。 显示具有 Set-Cookie 标头并且名称与指定值匹配的资源。 DevTools 会使用其遇到的所有 Cookie 名称填充自动填充下拉菜单。</li> <li>set-cookie-value。 显示具有 Set-Cookie 标头并且值与指定值匹配的资源。 DevTools 会使用其遇到的所有 Cookie 值填充自动填充下拉菜单。</li> <li>status-code。 仅显示 HTTP 状态代码与指定代码匹配的资源。 DevTools 会使用其遇到的所有状态代码填充自动填充下拉菜单。</li> </ul> </li> <li>例如:mime-type:image/gif larger-than:1K 显示大于一千字节的所有 GIF</li> <li><code>Hide Data URLs</code>:隐藏 <a>data 类型的 url</a></li> </ul> <h2>瀑布图</h2> <ul> <li>瀑布图按时间线展示所有请求</li> <li>可以用鼠标拖动选中一段时间,只查看改时间线内的请求</li> <li>瀑布图中有两条竖线,一条蓝色,代表<a>DOMContentLoaded</a>事件发生的事件,一条红色代表<a>load</a>事件发生的时间点</li> </ul> <h2>分析请求/请求列表</h2> <ul> <li>重播请求:右键点击 Requests 表格中的请求 -&gt; <code>Replay XHR</code></li> <li>讲请求复制为 Fetch 代码 -&gt; <code>Copy As Fetch</code></li> <li>手动清除浏览器缓存:右键点击 Requests 表格中的任意位置 -&gt; 选择 <code>Clear Browser Cache</code></li> <li>手动清除浏览器 Cookie:右键点击 Requests 表格中的任意位置 -&gt; 选择 <code>Clear Browser Cookies</code></li> <li>自定义列表中展示的列</li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbd553d024cc.png" alt="network2.png" /></p> <ul> <li>请求行排序,默认按照瀑布图 start time 升序排序,即请求发起的时间点:</li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbd63427ece0.png" alt="networkOrder.png" /></p> <ul> <li> <p>每条请求,可以看到网络请求以及被清华求资源的全部信息:</p> <ul> <li>请求的一般信息:url、HTTP 方法(GET POST 等)、状态码、ip 地址</li> <li>请求相关:请求头、Initiator、Priority</li> <li>响应相关:响应头、响应内容</li> </ul> </li> <li> <p>Initiator:请求的来源/发起者。parser:一般来自解析器解析到的 html 页面内的请求;script:来自脚本文件的请求。鼠标悬浮到 Initiator 列中的文件名上,可以看到发起当前请求的堆栈轨迹,点击文件名,可以定位到直接发起请求的代码</p> </li> <li> <p>两个 size:在 size 列中,有两个数值,上面的较小值代表下载到的资源的大小,下面的较大值是资源解压后的大小。(例如 在 Content-Encoding 中可以看到的 gzip 和 br)</p> </li> <li> <p>按住<code>shift</code>鼠标悬浮在请求行上,变绿色的行是当前行的发起者,红色的行是当前行的依赖项。</p> </li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbd9945dd05b.png" alt="initiator.png" /></p> <ul> <li>Priority:High,Highest,Low。根据时间线中的蓝线和红线(DOMContentLoaded 和 load),以及请求的优先级,可以从结果的角度观察浏览器的加载流程。</li> </ul> <h2>Websocket</h2> <ul> <li>在 network 的 filter 条件后,选择<code>ws</code>类型的请求,即可看到所有 Websocket 请求</li> <li>在请求详情的 Message 栏中,可以看到 wensocket 全双工通信中客户端接收和发送的信息</li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbdbe96a4597.png" alt="networkWebsocket.png" /></p> <h2>Color Code:瀑布图中的几种颜色与代码</h2> <p><img src="https://i.loli.net/2019/04/22/5cbdc5acaff77.png" alt="colorCode.png" /></p> <ul> <li>Queueing 排队,请求未发出,正在等待。 浏览器在以下情况下对请求排队: <ul> <li>存在更高优先级的请求。</li> <li>此源已打开六个 TCP 连接,达到限值。 仅适用于 HTTP/1.0 和 HTTP/1.1(在 HTTP1 下浏览器一次最允许 6 个 TCP 连接,超出 6 个,就要 queue 排队)(优化 web 性能-&gt;避免 queue-&gt;合并资源请求)</li> <li>浏览器正在短暂分配磁盘缓存中的空间</li> </ul> </li> <li>Stalled/Blocking 停滞/阻塞,请求仍未发出。请求可能会因 Queueing 中描述的任何原因而停止。</li> <li>DNS Lookup dns 查找,浏览器正在解析请求的 IP 地址,每次有指向新 domian 的请求时,会有 dns 查找的时间消耗。</li> <li>Proxy negotiation 代理协商。 浏览器正在与代理服务器协商请求。</li> <li>initial connection/connecting 正在初始化连接 或 正在连接,包含 tcp 的三次握手的时间</li> <li>SSL 完成 SLL 握手所需要的时间</li> <li>Request sent/senting 正在发送请求,发请求所占的时间,通常只有几分之一毫秒。</li> <li>ServiceWorker Preparation。 浏览器正在启动 Service Worker。</li> <li>Request to ServiceWorker。 正在将请求发送到 Service Worker。</li> <li>Waiting (TTFB)。 浏览器正在等待响应的第一个字节。 TTFB 表示 Time To First Byte(至第一字节的时间)。 此时间包括 1 次往返延迟时间及服务器准备响应所用的时间。</li> <li>Content Download。 浏览器正在接收响应。</li> <li>Receiving Push。 浏览器正在通过 HTTP/2 服务器推送接收此响应的数据。</li> <li>Reading Push。 浏览器正在读取之前收到的本地数据。</li> </ul> <h2>相关附注</h2> <h3>DOMContentLoaded 和 load 事件</h3> <ul> <li>DOMContentLoaded — 浏览器已经完全加载了 HTML,DOM 树已经构建完毕,但是像是 <code>&lt;img loading="lazy" decoding="async"&gt;</code> 和样式表等外部资源可能并没有下载完毕。</li> <li>load — 浏览器已经加载了所有的资源(图像,样式表等)。</li> <li>beforeunload/unload -- 当用户离开页面的时候触发。</li> <li><a>更多</a></li> </ul> <h3>data URLs</h3> <ul> <li>即前缀为 data: 协议的的 URL,其允许内容创建者向文档中嵌入小文件,例如浏览器 API canvas 支持的 base64 编码格式图片,<a>更多相关</a></li> </ul> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/devtools_05_network/#post-comment/</comments>
</item>
<item>
<title>Devtools 老司机养成 - 第四篇Sources源文件面板</title>
<link>https://www.scarsu.com/devtools_04_sources/</link>
<guid isPermaLink="true">https://www.scarsu.com/devtools_04_sources/</guid>
<description>chrome重要的sources面板,可以做IDE?文件变更,覆盖调试...</description>
<pubDate>Sun, 15 Mar 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>概览</h2> <ul> <li>Debug : 在源代码面板中可以设置<strong>断点</strong>来调试 JavaScript ,比 console.log()调试更快速高效</li> <li>Devtools as IDE : 通过 Workspaces(工作区)连接本地文件来使用开发者工具的<strong>实时编辑器</strong></li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e54ad6595d17473.png" alt="0" /></p> <h2>七种断点类型</h2> <ol> <li> <p>行断点:代码运行到当前行之前暂停执行</p> <pre><code>在源代码添加debugger关键字 或者 点击Sources面板中的源代码的行号 </code></pre> </li> <li> <p>条件行断点:当满足条件时才会触发该断点</p> <pre><code>右击Sources面板中的源代码的行号 选择“Add conditional breakpoint” </code></pre> <p><img src="https://i.loli.net/2019/07/29/5d3e54bc1e26c94874.gif" alt="0" /></p> </li> <li> <p>DOM 断点</p> <pre><code>即Elements面板提及过的三种DOM断点: - 节点属性断点 - 节点删除断点 - 子树变更断点 </code></pre> <p><img src="https://i.loli.net/2019/07/29/5d3e54c7ee26f77001.gif" alt="0" /></p> </li> <li> <p>XHR/Fetch 断点</p> <pre><code>在页面发出XHR或Fetch请求前加断点 </code></pre> <p><img src="https://i.loli.net/2019/07/29/5d3e54d8de3ba68180.png" alt="0" /></p> </li> <li> <p>Event Listener 事件监听断点</p> <pre><code>可以在所有类型的事件函数被出发前加断点 </code></pre> <p><img src="https://i.loli.net/2019/07/29/5d3e54d8f005d73515.png" alt="0" /></p> </li> <li> <p>Exception 异常断点</p> <p><img src="https://i.loli.net/2019/07/29/5d3e54d90b04490413.gif" alt="0" /></p> </li> <li> <p>Function 函数断点</p> <pre><code>把想调试的函数名作为参数,调用debug()函数,可以在每次执行该函数前暂停执行代码 </code></pre> <p><img src="https://i.loli.net/2019/07/29/5d3e54db0062099787.gif" alt="0" /></p> </li> </ol> <h2>Debug</h2> <ul> <li>函数调用栈 Call Stack:Call Stack 是 time traveling 的,即点击栈中的任一节点,当前的作用域和局部变量等信息,都会模拟至该节点执行时的状态</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e556a3d2ff51804.png" alt="0" /></p> <ul> <li>全局作用域 Global ,局部作用域 Local ,闭包作用域 Closure</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e5579edff848268.png" alt="0" /></p> <ul> <li>step over next function</li> <li>step into next function</li> <li>step out current function</li> <li>step (与 step over/into 的区别就是,step 会优先尝试 step into,当没有可步入的代码时,就会执行 step over)</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e558950aa668631.png" alt="0" /></p> <ul> <li>long resume:恢复执行,并将断点停用 500ms</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e55951dbb174461.gif" alt="0" /></p> <ul> <li>Continue to here:继续执行至此行</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e55b1cbe1030881.gif" alt="0" /></p> <ul> <li>Restart Frame:重新执行函数调用堆栈中的某一帧</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e55be02afb66581.gif" alt="0" /></p> <ul> <li>行断点内的多个箭头:行内断点(行内的,可 step into 的 执行点</li> </ul> <p><img src="https://i.loli.net/2019/05/13/5cd969192e3cf64417.png" alt="" /></p> <h2>Devtools Nodejs debug</h2> <ul> <li>node 执行 js 文件,文件名前加--inspect 标志,启用浏览器 nodejs 调试</li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbd33c700aed.png" alt="nodeDebug.png" /></p> <ul> <li>点击 devtools 中,左上角的 devices mode 右侧的绿色按钮,即可启用 node 服务端中的脚本调试</li> <li><a>更多相关</a></li> </ul> <h2>BlackBox</h2> <ul> <li> <p>BlackBox 的用途:</p> <p>“BlackBox Script”可以在调试中忽略某些脚本(此处的 BlackBox 为动词),在 Call Stack 堆栈中会将该脚本隐藏,单步调试时也不会步入脚本中的任何函数</p> <pre><code>function animate() { prepare(); lib.doFancyStuff(); // A render(); } </code></pre> <p>例如以上代码的 A 行,调用的是第三方库的 doFancyStuff 函数</p> <p>如果我确认该第三方库没有 bug</p> <p>就可以 BlackBox 整个第三方库的 js 脚本,在调试中跳过这些代码的执行</p> </li> <li> <p>三种添加 BlackBox 的方法:</p> </li> </ul> <ol> <li> <p>在源代码窗格右键,选择"BlackBox Script" <img src="https://i.loli.net/2019/07/29/5d3e55d52054637081.gif" alt="0" /></p> </li> <li> <p>在 Call Stack 中右键某一帧,选择"BlackBox Script" <img src="https://i.loli.net/2019/07/29/5d3e55d3bd9da13494.gif" alt="0" /></p> </li> <li> <p>在设置中的 Blackboxing 面板添加<strong>正则表达式</strong>匹配<strong>文件名</strong></p> <p><img src="https://i.loli.net/2019/07/29/5d3e55d9e574935159.gif" alt="0" /></p> </li> </ol> <h2>Workspace:Devtools as IDE 将更改持久化</h2> <ul> <li>在 sources 左侧的面板中选择<code>Filesystem</code>,点击<code>Add folder to workspace</code>,将你本地运行的站点的相关源文件添加到 Devtools 的工作区,会自动识别 Page 下和工作区下相对应的文件,在 devtools 更改文件并保存,即持久化保存(目前只支持自动识别,不支持添加映射)</li> <li>绿标文件:成功的映射到本地的文件,在 Styles 和 Sources 中的文件名前,都会添加绿色圆点作为标识 <img src="https://i.loli.net/2019/04/22/5cbd0771e5e31.png" alt="workspace.png" /> <img src="https://i.loli.net/2019/04/22/5cbd07bf14dc8.png" alt="workspace2.png" /></li> <li>目前 Devtools 已经支持 sass/scss、UglifyJS、Grunt、Coffescript、Closure 等等,暂时还不支持 webpack,和其他现代的复杂框架,如 react</li> <li>所有sources面板的文件,都可以右键选择<code>local modifications</code>,查看所有更改</li> <li>对 DOM 树的更改不会持久化至 html 文件:因为 dom 的最终表现,受到 html、css、javascript 的共同影响,DOM 树 !== HTML,因此可以在 sources 中直接更改 html 文件并保存</li> </ul> <h2>Source Map</h2> <ul> <li>组合/压缩 css,js 文件是常见的性能优化方案,但是会对开发调试造成困扰</li> <li>Source Map 用于将生产代码映射至源代码,Chrome 和 firefox 都内置了对 Source Map 的支持</li> <li>在 Chorme devtools 中,settings -&gt; preferen -&gt; sources 中,选中<code>Enable Javascript source maps</code>和<code>Enable CSS source maps</code></li> <li>source map 映射信息存在 json 对象中,保存在 .map 文件中,可以由编译程序添加注释<code>//# sourceMappingURL=/path/to/script.js.map</code>至生产文件末尾,也可以由服务端在响应头中添加<code>X-SourceMap: /path/to/script.js.map</code>,将 map 文件与生产文件对应。<a>更多关于 source map 的介绍</a></li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbd10f324e07.png" alt="sourceMap.png" /></p> <h2>Local Overrides</h2> <ul> <li>用于覆盖网络请求: 在source/page右键save for override或直接edit,保存的文件都被存储到overrides 指定目录(按照域名建立文件夹). 这种改写是临时的</li> <li>在 Sources 面板左侧选择 Overrides,指定 DevTools 应保存更改的目录,当在 DevTools 中进行更改时,DevTools 会将修改后的文件的副本保存到所选的本地目录中,重新加载页面时,DevTools 提供本地修改的文件,而不是请求的网络资源。</li> <li>与 Workspace 相似的,不支持保存对 DOM 树的更改,需要直接更改 html 源文件。</li> <li>只能指定一个目录</li> <li>断点debug 时,实时修改文件,然后保存后会恢复到第一个断点,不用重新刷新</li> </ul> <h2>Snippets 代码片段</h2> <ul> <li>在 Sources 面板左侧选择 Snippets,或<code>crlt shift p</code>输入 snippet 打开 Snippets 面板,可以创建并保存常用的代码片段,和用 gist 类似</li> <li>snippets 中,选中代码并<code>ctrl enter</code>,或点击右下角的执行按钮,即可执行代码片段</li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbd147145955.png" alt="snippet.png" /></p> <h2>Content scripts</h2> <ul> <li>这部分脚本是浏览器插件的脚本,在特定网页的上下文中运行。(与插件运行在服务端的脚本,页面上引用的脚本,页面上 script 中的内嵌脚本都不同</li> <li>插件在服务端的脚本可以访问所有 WebExtension JavaScript API,但它们无法直接访问网页内容。</li> <li>Content scripts 只能访问 WebExtension API 的一小部分,但它们可以使用消息传递系统与后台脚本进行通信,从而间接访问 WebExtension API。</li> <li>如果有浏览器插件相关的工作,可以更深入<a>研究</a>,不赘述。</li> </ul> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/devtools_04_sources/#post-comment/</comments>
</item>
<item>
<title>Devtools 老司机养成 - 第三篇-Console 面板</title>
<link>https://www.scarsu.com/devtools_03_console/</link>
<guid isPermaLink="true">https://www.scarsu.com/devtools_03_console/</guid>
<description>Console 面板是浏览器的控制台,也是 Devtools 的灵魂,只会console.log就过分啦~</description>
<pubDate>Sun, 08 Mar 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>概览</h2> <p>Console 面板是浏览器的控制台,也是 Devtools 的灵魂。</p> <p>可以通过<strong>设置-&gt;Show Console drawer</strong>或者<strong>Esc 快捷键</strong>让 Console 在每个面板都能显示。 <img src="https://i.loli.net/2019/07/29/5d3e5381c290f84642.png" alt="0" /></p> <h2>message</h2> <ul> <li>在 console 中,可以看到来自<strong>浏览器</strong>/<strong>代码</strong>的五种类型的信息: <ul> <li>user message</li> <li>error</li> <li>warning</li> <li>info</li> <li>verbose</li> </ul> </li> <li>相同的消息默认是堆叠的,可以通过 ctrl+shift+p 输入 time 命令或者设置中找到<strong>timestamps</strong>命令,给消息加上时间戳</li> <li>通过选项<strong>Log XMLHttpRequest</strong>选择是否输出所有 XMLHttp 请求日志(可以监控页面所有 ajax 请求 定位其代码调用栈)</li> <li>通过<strong>Hide network</strong>选择显示/隐藏网络请求的错误信息(例如 GET xxx 404)</li> <li>通过<strong>Preserve log</strong>选择保留历史记录,即刷新页面后是否还显示先前的消息</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e53989dba574108.png" alt="0" /></p> <h2>javascript 实时执行环境</h2> <ul> <li>console 除了能输出调试信息,也是一个 javascript 实时执行环境。</li> <li>可以直接在这里输入任何<strong>全局变量名</strong>/内置对象名/函数名,会得到相应的值输出;在调试环境下的断点内,可以获取<strong>局部变量</strong>值</li> <li>右键选<strong>Store as global variable</strong>,可以将输出值存储为一个临时的全局变量</li> <li>双击对象的属性值,可以直接更改这个对象(持久化的更改,因为 console 存储下来的是对象的引用)</li> <li>console 中输出的 dom 元素 -&gt; 右键 -&gt; reveal in elements:快速定位到元素面板中的当前元素</li> </ul> <h2>选择执行环境</h2> <p>可以通过左上的下拉列表,选择不同的<strong>执行环境</strong></p> <p><img src="https://i.loli.net/2019/07/29/5d3e53a7d369f73554.png" alt="0" /></p> <p>top 是最外层的顶级页面,其他的是 iframe 子页面</p> <p>默认情况下</p> <ul> <li>子 frame 中:</li> </ul> <pre><code>(window === self) === self.window; //top.window是顶级页面top的全局变量window </code></pre> <ul> <li>top frame 中:</li> </ul> <pre><code>(((window === self) === self.window) === top) === top.window; </code></pre> <h2>console 中的<code>$</code>符号:</h2> <ul> <li>可以通过<code>$0</code>,获取当前在 Elements 面板所选中的元素节点</li> <li>如果 <code>$</code> 在当前页面没被占用,可以用来替代 document.querySlector 方法使用</li> <li><code>$$</code> 是 document.querySelectorAll 方法的更佳替代,因为 document.querySelectorAll 返回的是 nodeList(NodeList),而<code>$$</code>能直接返回数组(Array) <img src="https://i.loli.net/2019/07/29/5d3e53c18483c36428.png" alt="0" /></li> <li><code>$_</code>可以引用上一次执行的结果 <img src="https://i.loli.net/2019/07/29/5d3e53c198cdf46610.png" alt="0" /></li> <li>如果需要使用 npm 的包,可以安装 Console Importer 插件,用<code>$i</code>方法引入 npm 中的库 <img src="https://i.loli.net/2019/07/29/5d3e53c1ae52088165.gif" alt="0" /></li> </ul> <h2>console 下的方法:</h2> <ul> <li>除了被用烂了的<code>console.log()</code>(当然 console.log 也有特别一点的用法) <img src="https://i.loli.net/2019/07/29/5d3e53ec0c9c777415.png" alt="0" /></li> <li>console 对象还有 console.error/clear/debug/count/time/table/tarce 等等方法</li> <li>直接在 console 中输入 console,可以看到 console 对象下的所有方法 <img src="https://i.loli.net/2019/07/29/5d3e54117f36b48748.png" alt="0" /></li> <li>例如 console.table(obj)可以把你的对象以可视化的表格形式进行输出 <img src="https://i.loli.net/2019/07/29/5d3e541ed227433392.gif" alt="0" /></li> <li>例如可以使用 console.time()和 console.timeEnd()方法来测量时间差 <img src="https://i.loli.net/2019/07/29/5d3e542c27e8b99508.png" alt="0" /></li> <li>另:console 命令行还内置了一些 API 方法,例如 queryObjects(),可以返回指定类型的对象下所有的实例化的对象 <img src="https://i.loli.net/2019/07/29/5d3e5480317cd69237.png" alt="0" /></li> </ul> <pre><code>queryObjects(Object); //返回所有object对象 queryObjects(Function); //返回所有函数 queryObjects(Array); //返回所有数组 </code></pre> <ul> <li>monitor(function)方法来追踪函数调用信息,当函数被执行,会输出追踪信息 <img src="https://i.loli.net/2019/07/29/5d3e548f62a6723531.png" alt="0" /></li> <li>monitorEvents(el,eventType)方法来追踪事件 <img src="https://i.loli.net/2019/07/29/5d3e5494878e638089.png" alt="0" /></li> </ul> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/devtools_03_console/#post-comment/</comments>
</item>
<item>
<title>Devtools 老司机养成 - 第二篇-Elements 面板</title>
<link>https://www.scarsu.com/devtools_02_elements/</link>
<guid isPermaLink="true">https://www.scarsu.com/devtools_02_elements/</guid>
<description>样式顺手调,DOM实时改~</description>
<pubDate>Sun, 01 Mar 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>界面概览</h2> <p>使用 Chrome DevTools 的 Elements 面板检查和实时编辑页面的 HTML 与 CSS</p> <p><img src="https://i.loli.net/2019/07/29/5d3e521d6fbde79541.png" alt="Elements 面板" /></p> <h2>Inspect Mode</h2> <p>快捷键 ctrl shift c/点击面板左上角的按钮,进入元素选择模式 <img src="https://i.loli.net/2019/04/19/5cb9cb351d6a2.png" alt="inspect" /></p> <p>在新版本 chrome 中,选择元素时会显示更多元素信息 <img src="https://i.loli.net/2019/04/19/5cb9ca97739bb.png" alt="inspect" /></p> <h2>Device Mode 设备模式</h2> <ul> <li>模拟不同尺寸移动端设备下,网页的表现。</li> <li>是自适应网页调试利器。</li> <li>内置/可配置既有设备属性,例如 iphone/ipad</li> <li>支持调试媒体查询 media-query。</li> </ul> <p><img src="https://i.loli.net/2019/04/19/5cb9cc03d400a.png" alt="deviceMode" /></p> <h2>DOM 树</h2> <p>在元素面板左侧是当前页的 DOM 树 <img src="https://i.loli.net/2019/07/29/5d3e52339265738563.png" alt="0" /></p> <p>在 DOM 树中你可以:</p> <ul> <li> <p>直接增/删/改/复制/拖放移动 DOM 元素,查看实时效果(非持久化)</p> </li> <li> <p>添加元素断点(节点移除断点,属性变更断点,子树变更断点)</p> </li> <li> <p>模拟元素 focus/hover/actice 等状态</p> </li> <li> <p>选中元素后通过右键“Scroll into view”突出显示当前元素在页面的位置</p> </li> <li> <p>按快捷键<strong>h</strong>来快速隐藏/显示元素当前元素及其后代元素(原理是 visibility 设为 hidden,不影响其他元素,不引起重绘)</p> </li> <li> <p>按住 alt 键 点击 dom 元素前的箭头:全部折叠/展开当前元素及其后代元素</p> <p><img src="https://i.loli.net/2019/07/29/5d3e52c51ed0570682.png" alt="0" /></p> </li> </ul> <h2>Styles</h2> <p>在面板右侧 Styles 窗格中:</p> <ul> <li>会显示节点的各级样式</li> <li>每级样式的来源</li> <li>每条样式属性是否命中</li> <li>可以直接增/删/改元素样式,查看实时效果(非持久化)</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e524d5a48a76988.png" alt="0" /></p> <h2>color picker</h2> <p><img src="https://i.loli.net/2019/05/13/5cd95d7a5c09c98927.png" alt="" /></p> <ul> <li>在样式窗格中,devtools 给所有颜色属性值前添加了 color picker 工具</li> <li>按住 shift 点击色块,快速切换颜色格式 rgb/hsl/hex</li> </ul> <p><img src="https://i.loli.net/2019/05/13/5cd95e1abea2793787.png" alt="" /></p> <ul> <li>page colors:color picker 中会列出页面所有的颜色</li> <li>material colors:color picker 中会列出 google 设计推荐色系</li> </ul> <h2>Computed</h2> <p>在 Styles 右侧的 Computed 窗格中可以查看:</p> <ul> <li>元素的盒模型(双击值可编辑)</li> <li>元素所有样式的<strong>计算后最终值</strong>(即最终实际应用到元素的值)</li> <li>点开每一条最终值,可以看到所有该条样式的规则,以及代码来源</li> <li>勾选<strong>show all</strong>选项,会同时列出元素<strong>继承 / 默认</strong>样式</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e525f4f2a311954.png" alt="0" /></p> <h2>Event Listeners</h2> <ul> <li>在 Event Listeners 窗格中,可以看到元素的事件监听器</li> <li>例如"load","DOMContentLoaded","click"等,以及每个事件对应的事件处理函数</li> </ul> <p><img src="https://i.loli.net/2019/07/29/5d3e52728065d88131.png" alt="0" /></p> <p>在源代码中加 <strong>行 debugger 断点</strong>,或者<strong>debug(函数)断点</strong>(Sources 面板会提及这两种断点),是需要代码维护成本的,有时候还会忘记删除;</p> <p>或者你想调试别人开发的 你不拥有源码的 网页;</p> <p>这些时候可以利用 Event Listeners 窗格快速定位当前元素被绑定的所有的<strong>事件函数代码</strong>并调试。</p> <h2>DOM Breakpoints</h2> <p>在面板右侧 DOM Breakpoints 中,可以查看<strong>元素断点</strong></p> <p><img src="https://i.loli.net/2019/07/29/5d3e5282c491d43866.png" alt="0" /></p> <p>相应的在左侧 DOM 树右键点击元素,可以给元素添加断点</p> <p>元素断点有三种类型:属性变更,子树变更,节点删除</p> <p>例如添加“node removal”断点,就会在 有代码移除当前节点时,在当前行代码执行前暂停执行,并自动转换到 Sources 面板,以便做进一步调试 <img src="https://i.loli.net/2019/07/29/5d3e529117f6c69468.png" alt="0" /></p> <h2>Properties</h2> <p>Properties 面板会列出元素 DOM 底层相关属性 <img src="https://i.loli.net/2019/07/29/5d3e52b143cc424671.png" alt="0" /></p> <h2>Accessibility(可访问性)</h2> <ul> <li>在辅助功能树中查看元素的位置(可访问性树/无障碍树是 DOM 树的子集。它只包含来自 DOM 树的元素,这些元素可以展示在屏幕阅读器中页面的内容。</li> <li>查看元素的 ARIA 属性(ARIA 属性确保屏幕阅读器具有所需的所有信息,以便正确表示页面的内容。</li> <li>查看元素的计算辅助功能属性(某些辅助功能属性由浏览器动态计算。可以在“ 辅助功能”窗格的“ 计算属性”部分中查看这些属性</li> </ul> <p><img src="https://i.loli.net/2019/04/21/5cbc83e1561e4.png" alt="accessibility.png" /></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/devtools_02_elements/#post-comment/</comments>
</item>
<item>
<title>Devtools 老司机养成 - 第一篇Devtools介绍</title>
<link>https://www.scarsu.com/devtools_01_intro/</link>
<guid isPermaLink="true">https://www.scarsu.com/devtools_01_intro/</guid>
<description>前端开发调试第一利器,关于devtools的信息,都在这里</description>
<pubDate>Sun, 23 Feb 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>相关</h2> <ul> <li>本文作者:<a>ScarSu</a></li> <li>本文基于 chrome 浏览器版本 73.0.3683.103(正式版本)总结</li> <li>本文目的:关于【devtools 能做什么】建立完善的知识结构,至于怎么做,请查阅官方文档;工具类知识需要实践,建议阅读本文时打开 <a>sample</a>和 devtools 操作一遍</li> <li>参考 1:<a>google developers 官方文档</a></li> <li>参考 2:来自作者 Jon Kuoerman 在 FrontEndMaster 的 <a>Mastering Chrome Developer Tools v2 课程</a></li> <li>参考 3:来自 作者 Tomek Sułkowski 在 medium 的<a>系列文章</a></li> <li><a>Devtools脑图.png</a></li> </ul> <h2>web devtool 历史</h2> <ul> <li>view-source + alert 调试法</li> <li><a>Live DOM Viewer</a></li> <li><a>Firebug</a></li> </ul> <h2>Chrome相关介绍</h2> <h4>Chromium</h4> <pre><code>是谷歌的开源项目,由开源社区维护。 国产的所有 “双核浏览器”,都是基于 Chromium 开发的,甚至 Chrome 也是基于它。 我们下载的 Chromium 浏览器都是其源码未经修改的直接编译版本。 Chromium 的内核版本比 Chrome 明显领先,新的技术都是先在 Chromium 上应用。 几乎每天都在进行更新; </code></pre> <h4>Chrome</h4> <pre><code>基于 Chromium,但是它是闭源的! 所以有这样的一种说法:谷歌把核心技术都保留在了之家的 Chrome 中。 支持了一些商业的收费插件,这些是不会出现在开源软件中的: H.264编码、mp3编码 Chrome 内置了 Flash,Chromium 需要额外安装 据说?在网页渲染方面 Chrome 也悄悄有一些特别的优化。 集成了更多的谷歌服务(RanBinNuan),同时也有更多的限制,比如目前使用 Chrome 需要一定手段才能安装非商店的扩展,一旦被发现还会永远禁用,但 Chromium 就没有这些限制! </code></pre> <h4>Dev Canary Stable Beta</h4> <p>是Chrome的四个版本:</p> <ul> <li>Stable 稳定版(几月一次更新)</li> <li>Beta 测试版(1 月一次更新)</li> <li>Dev 开发者版(1 星期一次更新)</li> <li>Canary 金丝雀版(脚步几乎同步 Chromium,天天更新)图标采用了特别的土豪金版神奇宝贝球。</li> </ul> <p>新版发布速度递增 新功能数量递增 稳定性递减</p> <h2>Chrome Devtools 界面概览</h2> <p><img src="https://i.loli.net/2019/04/19/5cb955bed88ce.png" alt="000devtoolsAll.png" /></p> <h2>Tips and Tricks</h2> <ul> <li>快捷键:ctrl shift p:执行命令</li> <li>快捷键:ctrl p:打开文件</li> <li>快捷键:esc:显示/隐藏 drawer(第二行面板</li> <li>快捷键:ctrl shift c:选择元素</li> <li>more -&gt; focus debugee:切换至正在被调试的页面</li> <li>more -&gt; more tools:全部面板</li> <li>无痕模式打开网页 —&gt; 更纯净的调试环境,无扩展代码干扰</li> <li>实验性功能:</li> </ul> <pre><code> 打开url chrome://flags/ 搜索dev 打开Experimental Extension APIs开关 在settings中找到experiments可以找到相关实验性功能 shift按七次,显示隐藏的实验性功能(比如terminal </code></pre> <ul> <li>金丝雀版 chrome - <a>Canary - 开发者专用的每日更新版</a></li> <li>开发者版 chrome - <a>Dev - 开发者专用的每周更新版</a></li> </ul> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/devtools_01_intro/#post-comment/</comments>
</item>
<item>
<title>Devtools 入门</title>
<link>https://www.scarsu.com/devtools_rookie_intro/</link>
<guid isPermaLink="true">https://www.scarsu.com/devtools_rookie_intro/</guid>
<description>Devtools新手请看这篇,入门大全~</description>
<pubDate>Sun, 16 Feb 2020 00:00:00 GMT</pubDate>
<content:encoded><h1></h1> <h2>相关</h2> <ul> <li>本文作者:<a>ScarSu</a></li> <li><a>进阶系列文链接</a></li> <li>本文基于 chrome 浏览器版本 73.0.3683.103(正式版本)总结</li> <li>参考 :<a>google developers 官方文档</a></li> </ul> <h2>web devtool 历史</h2> <ul> <li>view-source + alert 调试法</li> <li><a>Live DOM Viewer</a></li> <li><a>Firebug</a></li> </ul> <h2>Chrome相关介绍</h2> <h4>Chromium</h4> <pre><code>是谷歌的开源项目,由开源社区维护。 国产的所有 “双核浏览器”,都是基于 Chromium 开发的,甚至 Chrome 也是基于它。 我们下载的 Chromium 浏览器都是其源码未经修改的直接编译版本。 Chromium 的内核版本比 Chrome 明显领先,新的技术都是先在 Chromium 上应用。 几乎每天都在进行更新; </code></pre> <h4>Chrome</h4> <pre><code>基于 Chromium,但是它是闭源的! 所以有这样的一种说法:谷歌把核心技术都保留在了之家的 Chrome 中。 支持了一些商业的收费插件,这些是不会出现在开源软件中的: H.264编码、mp3编码 Chrome 内置了 Flash,Chromium 需要额外安装 据说?在网页渲染方面 Chrome 也悄悄有一些特别的优化。 集成了更多的谷歌服务(RanBinNuan),同时也有更多的限制,比如目前使用 Chrome 需要一定手段才能安装非商店的扩展,一旦被发现还会永远禁用,但 Chromium 就没有这些限制! </code></pre> <h4>Dev Canary Stable Beta</h4> <pre><code>是Chrome的四个版本 Stable 稳定版(几月一次更新) Beta 测试版(1 月一次更新) Dev 开发者版(1 星期一次更新) Canary 金丝雀版(脚步几乎同步 Chromium,天天更新)图标采用了特别的土豪金版神奇宝贝球。 新版发布速度递增 新功能数量递增 稳定性递减 </code></pre> <h2>Chrome Devtools 界面概览</h2> <p><img src="https://i.loli.net/2019/04/19/5cb955bed88ce.png" alt="000devtoolsAll.png" />;</p> <h2>Tips and Tricks</h2> <ul> <li>快捷键:ctrl shift p:执行命令</li> <li>快捷键:ctrl p:打开文件</li> <li>快捷键:esc:显示/隐藏 drawer(第二行面板</li> <li>快捷键:ctrl shift c:选择元素</li> <li>more -&gt; focus debugee:切换至正在被调试的页面</li> <li>more -&gt; more tools:全部面板</li> <li>无痕模式打开网页 —&gt; 更纯净的调试环境,无扩展代码干扰</li> <li>实验性功能:</li> </ul> <pre><code> 打开url chrome://flags/ 搜索dev 打开Experimental Extension APIs开关 在settings中找到experiments可以找到相关实验性功能 shift按七次,显示隐藏的实验性功能(比如terminal </code></pre> <ul> <li>金丝雀版 chrome - <a>Canary - 开发者专用的每日更新版</a></li> <li>开发者版 chrome - <a>Canary - 开发者专用的每周更新版</a></li> </ul> <h2>Elements 面板</h2> <p>使用 Chrome DevTools 的 Elements 面板检查和实时编辑页面的 HTML 与 CSS</p> <p><img src="https://i.loli.net/2019/06/03/5cf4a9da59be527769.png" alt="Elements 面板" /></p> <h3>Inspect Mode</h3> <p>快捷键 ctrl shift c/点击面板左上角的按钮,进入元素选择模式 <img src="https://i.loli.net/2019/04/19/5cb9cb351d6a2.png" alt="inspect" /></p> <p>在新版本 chrome 中,选择元素时会显示更多元素信息 <img src="https://i.loli.net/2019/04/19/5cb9ca97739bb.png" alt="inspect" /></p> <h3>Device Mode 设备模式</h3> <ul> <li>模拟不同尺寸移动端设备下,网页的表现。</li> <li>是自适应网页调试利器。</li> <li>内置/可配置既有设备属性,例如 iphone/ipad</li> <li>支持调试媒体查询 media-query。</li> </ul> <p><img src="https://i.loli.net/2019/04/19/5cb9cc03d400a.png" alt="deviceMode" /></p> <h3>DOM 树</h3> <p>在元素面板左侧是当前页的 DOM 树 <img src="https://i.loli.net/2019/06/03/5cf4aa13906d615289.png" alt="0" /></p> <p>在 DOM 树中可以:</p> <ul> <li> <p>直接增/删/改/复制/拖放移动 DOM 元素,查看实时效果(非持久化)</p> </li> <li> <p>添加元素断点(节点移除断点,属性变更断点,子树变更断点)</p> </li> <li> <p>模拟元素 focus/hover/actice 等状态</p> </li> <li> <p>选中元素后通过右键“Scroll into view”突出显示当前元素在页面的位置</p> </li> <li> <p>按快捷键<strong>h</strong>来快速隐藏/显示元素当前元素及其后代元素(原理是 visibility 设为 hidden,不影响其他元素,不引起重绘)</p> </li> <li> <p>按住 alt 键 点击 dom 元素前的箭头:全部折叠/展开当前元素及其后代元素</p> <p><img src="https://i.loli.net/2019/06/03/5cf4aa2c66c6183499.png" alt="0" /></p> </li> </ul> <h3>Styles</h3> <p>在面板右侧 Styles 窗格中:</p> <ul> <li>会显示节点的各级样式</li> <li>每级样式的来源</li> <li>每条样式属性是否命中</li> <li>可以直接增/删/改元素样式,查看实时效果(非持久化)</li> </ul> <p><img src="https://i.loli.net/2019/06/03/5cf4aa3edd33430557.png" alt="0" /></p> <h3>color picker</h3> <p><img src="https://i.loli.net/2019/05/13/5cd95d7a5c09c98927.png" alt="" /></p> <ul> <li>在样式窗格中,devtools 给所有颜色属性值前添加了 color picker 工具</li> <li>按住 shift 点击色块,快速切换颜色格式 rgb/hsl/hex</li> </ul> <p><img src="https://i.loli.net/2019/05/13/5cd95e1abea2793787.png" alt="" /></p> <ul> <li>page colors:color picker 中会列出页面所有的颜色</li> <li>material colors:color picker 中会列出 google 设计推荐色系</li> </ul> <h3>Computed</h3> <p>在 Styles 右侧的 Computed 窗格中可以查看:</p> <ul> <li>元素的盒模型(双击值可编辑)</li> <li>元素所有样式的<strong>计算后最终值</strong>(即最终实际应用到元素的值)</li> <li>点开每一条最终值,可以看到所有该条样式的规则,以及代码来源</li> <li>勾选<strong>show all</strong>选项,会同时列出元素<strong>继承 / 默认</strong>样式</li> </ul> <p><img src="https://i.loli.net/2019/06/03/5cf4aa5b8838377487.png" alt="0" /></p> <h3>Event Listeners</h3> <ul> <li>在 Event Listeners 窗格中,可以看到元素的事件监听器</li> <li>例如"load","DOMContentLoaded","click"等,以及每个事件对应的事件处理函数</li> </ul> <p><img src="https://i.loli.net/2019/06/13/5d01e076e584425630.png" alt="0" /></p> <p>在源代码中加 <strong>行 debugger 断点</strong>,或者<strong>debug(函数)断点</strong>(Sources 面板会提及这两种断点),是需要代码维护成本的,有时候还会忘记删除;</p> <p>或者你想调试别人开发的 你不拥有源码的 网页;</p> <p>这些时候可以利用 Event Listeners 窗格快速定位当前元素被绑定的所有的<strong>事件函数代码</strong>并调试。</p> <h3>DOM Breakpoints</h3> <p>在面板右侧 DOM Breakpoints 中,可以查看<strong>元素断点</strong></p> <p><img src="https://i.loli.net/2019/06/03/5cf4aa7a33a2334307.png" alt="0" /></p> <p>相应的在左侧 DOM 树右键点击元素,可以给元素添加断点</p> <p>元素断点有三种类型:属性变更,子树变更,节点删除</p> <p>例如添加“node removal”断点,就会在 有代码移除当前节点时,在当前行代码执行前暂停执行,并自动转换到 Sources 面板,以便做进一步调试 <img src="https://i.loli.net/2019/06/03/5cf4aa879865e17312.png" alt="0" /></p> <h2>Console 面板</h2> <p>Console 面板是浏览器的控制台,也是 Devtools 的灵魂。</p> <p>可以通过<strong>设置-&gt;Show Console drawer</strong>或者<strong>Esc 快捷键</strong>让 Console 在每个面板都能显示。 <img src="https://i.loli.net/2019/06/03/5cf4aaa5f1e3422250.png" alt="0" /></p> <h3>message</h3> <ul> <li>在 console 中,可以看到来自<strong>浏览器</strong>/<strong>代码</strong>的五种类型的信息: <ul> <li>user message</li> <li>error</li> <li>warning</li> <li>info</li> <li>verbose</li> </ul> </li> <li>相同的消息默认是堆叠的,可以通过 ctrl+shift+p 输入 time 命令或者设置中找到<strong>timestamps</strong>命令,给消息加上时间戳</li> <li>通过选项<strong>Log XMLHttpRequest</strong>选择是否输出所有 XMLHttp 请求日志(可以监控页面所有 ajax 请求 定位其代码调用栈)</li> <li>通过<strong>Hide network</strong>选择显示/隐藏网络请求的错误信息(例如 GET xxx 404)</li> <li>通过<strong>Preserve log</strong>选择保留历史记录,即刷新页面后是否还显示先前的消息</li> </ul> <p><img src="https://i.loli.net/2019/06/03/5cf4aab869c8a85783.png" alt="0" /></p> <h3>javascript 实时执行环境</h3> <ul> <li>console 除了能输出调试信息,也是一个 javascript 实时执行环境。</li> <li>可以直接在这里输入任何<strong>全局变量名</strong>/内置对象名/函数名,会得到相应的值输出;在调试环境下的断点内,可以获取<strong>局部变量</strong>值</li> <li>右键选<strong>Store as global variable</strong>,可以将输出值存储为一个临时的全局变量</li> <li>双击对象的属性值,可以直接更改这个对象(持久化的更改,因为 console 存储下来的是对象的引用)</li> <li>console 中输出的 dom 元素 -&gt; 右键 -&gt; reveal in elements:快速定位到元素面板中的当前元素</li> </ul> <h3>选择执行环境</h3> <p>可以通过左上的下拉列表,选择不同的<strong>执行环境</strong></p> <p><img src="https://i.loli.net/2019/06/03/5cf4aac95398455074.png" alt="0" /></p> <p>top 是最外层的顶级页面,其他的是 iframe 子页面</p> <h3>console 中的<code>$</code>符号:</h3> <ul> <li>可以通过<code>$0</code>,获取当前在 Elements 面板所选中的元素节点</li> <li>如果 <code>$</code> 在当前页面没被占用,可以用来替代 document.querySlector 方法使用</li> <li><code>$$</code> 是 document.querySelectorAll 方法的更佳替代,因为 document.querySelectorAll 返回的是 nodeList(NodeList),而<code>$$</code>能直接返回数组(Array) <img src="https://i.loli.net/2019/06/03/5cf4aadf0381221831.png" alt="0" /></li> <li><code>$_</code>可以引用上一次执行的结果 <img src="https://i.loli.net/2019/06/03/5cf4aae17ead896661.png" alt="0" /></li> <li>如果需要使用 npm 的包,可以安装 Console Importer 插件,用<code>$i</code>方法引入 npm 中的库 <img src="https://i.loli.net/2019/06/03/5cf4aae3f1a0221583.gif" alt="0" /></li> </ul> <h3>console 下的方法:</h3> <ul> <li>除了被用烂了的<code>console.log()</code>(当然 console.log 也有特别一点的用法) <img src="https://i.loli.net/2019/06/03/5cf4ab4d3e91911373.png" alt="0" /></li> <li>console 对象还有 console.error/clear/debug/count/time/table/tarce 等等方法</li> <li>直接在 console 中输入 console,可以看到 console 对象下的所有方法 <img src="https://i.loli.net/2019/06/03/5cf4ab5e5d30e65867.png" alt="0" /></li> <li>例如 console.table(obj)可以把你的对象以可视化的表格形式进行输出 <img src="https://i.loli.net/2019/06/03/5cf4ab71e90e874049.gif" alt="0" /></li> <li>例如可以使用 console.time()和 console.timeEnd()方法来测量时间差 <img src="https://i.loli.net/2019/06/03/5cf4ab744d6a089649.png" alt="0" /></li> <li>另:console 命令行还内置了一些 API 方法,例如 queryObjects(),可以返回指定类型的对象下所有的实例化的对象 <img src="https://i.loli.net/2019/06/03/5cf4ab8a6b20972501.png" alt="0" /></li> </ul> <pre><code>queryObjects(Object); //返回所有object对象 queryObjects(Function); //返回所有函数 queryObjects(Array); //返回所有数组 </code></pre> <ul> <li>monitor(function)方法来追踪函数调用信息,当函数被执行,会输出追踪信息 <img src="https://i.loli.net/2019/06/03/5cf4ab9c55a3f55468.png" alt="0" /></li> <li>monitorEvents(el,eventType)方法来追踪事件 <img src="https://i.loli.net/2019/06/03/5cf4ab9eaba5f43869.png" alt="0" /></li> </ul> <h2>Sources 源文件面板</h2> <p>在 Sources 面板你可以:</p> <ul> <li>Debug : 在源代码面板中可以设置<strong>断点</strong>来调试 JavaScript ,比 console.log()调试更快速高效</li> <li>Devtools as IDE : 通过 Workspaces(工作区)连接本地文件来使用开发者工具的<strong>实时编辑器</strong></li> </ul> <h3>七种断点类型</h3> <ol> <li> <p>行断点:代码运行到当前行之前暂停执行</p> <pre><code>在源代码添加debugger关键字 或者 点击Sources面板中的源代码的行号 </code></pre> </li> <li> <p>条件行断点:当满足条件时才会触发该断点</p> <pre><code>右击Sources面板中的源代码的行号 选择“Add conditional breakpoint” </code></pre> <p><img src="https://i.loli.net/2019/06/03/5cf4eeebeb78835989.gif" alt="0" /></p> </li> <li> <p>DOM 断点</p> <pre><code>即Elements面板提及过的三种DOM断点: - 节点属性断点 - 节点删除断点 - 子树变更断点 </code></pre> <p><img src="https://i.loli.net/2019/06/03/5cf4abbb04c6c25181.gif" alt="0" /></p> </li> <li> <p>XHR/Fetch 断点</p> <pre><code>在页面发出XHR或Fetch请求前加断点 </code></pre> <p><img src="https://i.loli.net/2019/06/03/5cf4abc790a6244461.gif" alt="0" /></p> </li> <li> <p>Event Listener 事件监听断点</p> <pre><code>可以在所有类型的事件函数被出发前加断点 </code></pre> <p><img src="https://i.loli.net/2019/06/03/5cf4abc8c9efb50152.png" alt="0" /></p> </li> <li> <p>Exception 异常断点</p> <p><img src="https://i.loli.net/2019/06/03/5cf4abca96ac072660.png" alt="0" /></p> </li> <li> <p>Function 函数断点</p> <pre><code>把想调试的函数名作为参数,调用debug()函数,可以在每次执行该函数前暂停执行代码 </code></pre> <p><img src="https://i.loli.net/2019/06/03/5cf4abeb2a86948381.gif" alt="0" /></p> </li> </ol> <h3>Debug</h3> <ul> <li>函数调用栈 Call Stack:Call Stack 是 time traveling 的,即点击栈中的任一节点,当前的作用域和局部变量等信息,都会模拟至该节点执行时的状态</li> </ul> <p><img src="https://i.loli.net/2019/06/03/5cf4abfcc126341109.png" alt="0" /></p> <ul> <li>全局作用域 Global ,局部作用域 Local ,闭包作用域 Closure</li> </ul> <p><img src="https://i.loli.net/2019/06/03/5cf4ac0980d1016641.png" alt="0" /></p> <ul> <li>step over next function</li> <li>step into next function</li> <li>step out current function</li> <li>step (与 step over/into 的区别就是,step 会优先尝试 step into,当没有可步入的代码时,就会执行 step over)</li> </ul> <p><img src="https://i.loli.net/2019/06/03/5cf4ac1b7a4e440822.png" alt="0" /></p> <ul> <li>long resume:恢复执行,并将断点停用 500ms</li> </ul> <p><img src="https://i.loli.net/2019/06/03/5cf4ac3a7458f65851.png" alt="0" /></p> <ul> <li>Continue to here:继续执行至此行</li> </ul> <p><img src="https://i.loli.net/2019/06/03/5cf4ac4622fe745522.gif" alt="0" /></p> <ul> <li>Restart Frame:重新执行函数调用堆栈中的某一帧</li> </ul> <p><img src="https://i.loli.net/2019/06/03/5cf4ac556cc2358478.gif" alt="0" /></p> <ul> <li>行断点内的多个箭头:行内断点(行内的,可 step into 的 执行点</li> </ul> <p><img src="https://i.loli.net/2019/05/13/5cd969192e3cf64417.png" alt="" /></p> <h3>Workspace:Devtools as IDE 将更改持久化</h3> <ul> <li>在 sources 左侧的面板中选择<code>Filesystem</code>,点击<code>Add folder to workspace</code>,将你本地运行的站点的相关源文件添加到 Devtools 的工作区,会自动识别 Page 下和工作区下相对应的文件,在 devtools 更改文件并保存,即持久化保存(目前只支持自动识别,不支持添加映射)</li> <li>绿标文件:成功的映射到本地的文件,在 Styles 和 Sources 中的文件名前,都会添加绿色圆点作为标识 <img src="https://i.loli.net/2019/04/22/5cbd0771e5e31.png" alt="workspace.png" /> <img src="https://i.loli.net/2019/04/22/5cbd07bf14dc8.png" alt="workspace2.png" /></li> <li>目前 Devtools 已经支持 sass/scss、UglifyJS、Grunt、Coffescript、Closure 等等,暂时还不支持 webpack,和其他现代的复杂框架,如 react</li> <li>所有 sources 面板的文件,都可以右键选择<code>local modifications</code>,查看所有更改</li> <li>对 DOM 树的更改不会持久化至 html 文件:因为 dom 的最终表现,受到 html、css、javascript 的共同影响,DOM 树 !== HTML,因此可以在 sources 中直接更改 html 文件并保存</li> </ul> <h2>Network 面板</h2> <p><img src="https://i.loli.net/2019/04/22/5cbd4f884b14c.png" alt="network.png" /></p> <ul> <li>默认情况下,只要 DevTools 处于打开状态,DevTools 就会在 Network 面板中记录所有网络请求。</li> <li>左上红点按钮:停止记录网络请求</li> <li>第二个按钮:清空请求记录</li> <li>录像按钮:页面加载时捕获屏幕截图</li> <li>过滤按钮:显示/隐藏 过滤条件行</li> <li>View 中的两个按钮:第一个是切换请求列表中每行的显示样式(大小请求行),第二个是显示/隐藏瀑布图</li> <li>Group By Frame:是否根据不同的 frame 分类显示请求</li> <li>Preserve Log:保存显示跨页面的加载请求</li> <li>Disable Cache:禁用浏览器缓存,模拟新用户打开页面的体验</li> <li>Offline 是模拟断网离线的状态,其后的下拉框可以选择模拟其他网络状况,比如 2G,3G</li> </ul> <h3>筛选请求</h3> <ul> <li>filter 文本框中可输入请求的属性 对 请求进行过滤,多个属性用空格分隔</li> <li>支持过滤的属性: <ul> <li>domain。 仅显示来自指定域的资源。 可以使用通配符字符 (<code>*</code>) 纳入多个域。 例如,*.com 将显示来自以 .com 结尾的所有域名的资源。 DevTools 会使用其遇到的所有域填充自动填充下拉菜单。</li> <li>has-response-header。 显示包含指定 HTTP 响应标头的资源。 DevTools 会使用其遇到的所有响应标头填充自动填充下拉菜单。</li> <li>is。 使用 is:running 可以查找 WebSocket 资源。</li> <li>larger-than。 显示大于指定大小的资源(以字节为单位)。 将值设为 1000 等同于设置为 1k。</li> <li>method。 显示通过指定 HTTP 方法类型检索的资源。 DevTools 会使用其遇到的所有 HTTP 方法填充下拉菜单。</li> <li>mime-type。 显示指定 MIME 类型的资源。 DevTools 会使用其遇到的所有 MIME 类型填充下拉菜单。</li> <li>mixed-content。 显示所有混合内容资源 (mixed-content:all),或者仅显示当前显示的资源 (mixed-content:displayed)。</li> <li>scheme。 显示通过未保护 HTTP (scheme:http) 或受保护 HTTPS (scheme:https) 检索的资源。</li> <li>set-cookie-domain。 显示具有 Set-Cookie 标头并且 Domain 属性与指定值匹配的资源。 DevTools 会使用其遇到的所有 Cookie 域填充自动填充下拉菜单。</li> <li>set-cookie-name。 显示具有 Set-Cookie 标头并且名称与指定值匹配的资源。 DevTools 会使用其遇到的所有 Cookie 名称填充自动填充下拉菜单。</li> <li>set-cookie-value。 显示具有 Set-Cookie 标头并且值与指定值匹配的资源。 DevTools 会使用其遇到的所有 Cookie 值填充自动填充下拉菜单。</li> <li>status-code。 仅显示 HTTP 状态代码与指定代码匹配的资源。 DevTools 会使用其遇到的所有状态代码填充自动填充下拉菜单。</li> </ul> </li> <li>例如:mime-type:image/gif larger-than:1K 显示大于一千字节的所有 GIF</li> <li><code>Hide Data URLs</code>:隐藏 <a>data 类型的 url</a></li> </ul> <h3>瀑布图</h3> <ul> <li>瀑布图按时间线展示所有请求</li> <li>可以用鼠标拖动选中一段时间,只查看改时间线内的请求</li> <li>瀑布图中有两条竖线,一条蓝色,代表<a>DOMContentLoaded</a>事件发生的事件,一条红色代表<a>load</a>事件发生的时间点</li> </ul> <h3>分析请求/请求列表</h3> <ul> <li>重播请求:右键点击 Requests 表格中的请求 -&gt; <code>Replay XHR</code></li> <li>手动清除浏览器缓存:右键点击 Requests 表格中的任意位置 -&gt; 选择 <code>Clear Browser Cache</code></li> <li>手动清除浏览器 Cookie:右键点击 Requests 表格中的任意位置 -&gt; 选择 <code>Clear Browser Cookies</code></li> <li>自定义列表中展示的列</li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbd553d024cc.png" alt="network2.png" /></p> <ul> <li>请求行排序,默认按照瀑布图 start time 升序排序,即请求发起的时间点:</li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbd63427ece0.png" alt="networkOrder.png" /></p> <ul> <li> <p>每条请求,可以看到网络请求以及被清华求资源的全部信息:</p> <ul> <li>请求的一般信息:url、HTTP 方法(GET POST 等)、状态码、ip 地址</li> <li>请求相关:请求头、Initiator、Priority</li> <li>响应相关:响应头、响应内容</li> </ul> </li> <li> <p>Initiator:请求的来源/发起者。parser:一般来自解析器解析到的 html 页面内的请求;script:来自脚本文件的请求。鼠标悬浮到 Initiator 列中的文件名上,可以看到发起当前请求的堆栈轨迹,点击文件名,可以定位到直接发起请求的代码</p> </li> <li> <p>两个 size:在 size 列中,有两个数值,上面的较小值代表下载到的资源的大小,下面的较大值是资源解压后的大小。(例如 在 Content-Encoding 中可以看到的 gzip 和 br)</p> </li> <li> <p>按住<code>shift</code>鼠标悬浮在请求行上,变绿色的行是当前行的发起者,红色的行是当前行的依赖项。</p> </li> </ul> <p><img src="https://i.loli.net/2019/04/22/5cbd9945dd05b.png" alt="initiator.png" /></p> <ul> <li>Priority:High,Highest,Low。根据时间线中的蓝线和红线(DOMContentLoaded 和 load),以及请求的优先级,可以从结果的角度观察浏览器的加载流程。</li> </ul> <h3>Color Code:瀑布图中的几种颜色与代码</h3> <p><img src="https://i.loli.net/2019/04/22/5cbdc5acaff77.png" alt="colorCode.png" /></p> <ul> <li>Queueing 排队,请求未发出,正在等待。 浏览器在以下情况下对请求排队: <ul> <li>存在更高优先级的请求。</li> <li>此源已打开六个 TCP 连接,达到限值。 仅适用于 HTTP/1.0 和 HTTP/1.1(在 HTTP1 下浏览器一次最允许 6 个 TCP 连接,超出 6 个,就要 queue 排队)(优化 web 性能-&gt;避免 queue-&gt;合并资源请求)</li> <li>浏览器正在短暂分配磁盘缓存中的空间</li> </ul> </li> <li>Stalled/Blocking 停滞/阻塞,请求仍未发出。请求可能会因 Queueing 中描述的任何原因而停止。</li> <li>DNS Lookup dns 查找,浏览器正在解析请求的 IP 地址,每次有指向新 domian 的请求时,会有 dns 查找的时间消耗。</li> <li>Proxy negotiation 代理协商。 浏览器正在与代理服务器协商请求。</li> <li>initial connection/connecting 正在初始化连接 或 正在连接,包含 tcp 的三次握手的时间</li> <li>SSL 完成 SLL 握手所需要的时间</li> <li>Request sent/senting 正在发送请求,发请求所占的时间,通常只有几分之一毫秒。</li> <li>ServiceWorker Preparation。 浏览器正在启动 Service Worker。</li> <li>Request to ServiceWorker。 正在将请求发送到 Service Worker。</li> <li>Waiting (TTFB)。 浏览器正在等待响应的第一个字节。 TTFB 表示 Time To First Byte(至第一字节的时间)。 此时间包括 1 次往返延迟时间及服务器准备响应所用的时间。</li> <li>Content Download。 浏览器正在接收响应。</li> <li>Receiving Push。 浏览器正在通过 HTTP/2 服务器推送接收此响应的数据。</li> <li>Reading Push。 浏览器正在读取之前收到的本地数据。</li> </ul> <h3>DOMContentLoaded 和 load 事件</h3> <ul> <li>DOMContentLoaded — 浏览器已经完全加载了 HTML,DOM 树已经构建完毕,但是像是 <code>&lt;img loading="lazy" decoding="async"&gt;</code> 和样式表等外部资源可能并没有下载完毕。</li> <li>load — 浏览器已经加载了所有的资源(图像,样式表等)。</li> <li>beforeunload/unload -- 当用户离开页面的时候触发。</li> <li><a>更多</a></li> </ul> <h2>Performance 性能面板</h2> <ul> <li>performance 面板可以用于分析<code>运行时性能</code>(运行时强调的是与页面加载性能相区分)</li> <li>以隐身模式打开网页 (隐身模式可确保 Chrome 以干净的状态运行。例如,排除扩展对性能测量的影响</li> <li><a>Janky Animation demo :性能测试 demo</a></li> <li>视图 overview:</li> </ul> <p><img src="https://i.loli.net/2019/04/23/5cbf1d586fe21.png" alt="performance.png" /></p> <h3>RAIL 模型</h3> <ul> <li> <p><a>RAIL 模型</a>是一种性能模型,定义了四个维度的性能分析指标</p> </li> <li> <p><code>Response</code>:在<code>100 毫秒</code>以内响应(例如从点按到绘制)</p> </li> <li> <p><code>Animation</code>: 每秒生成 60 帧,每个帧的工作(从 JS 到绘制)完成时间小于 16 毫秒,达到人眼顺滑(例如滚动 拖动都是动画类型)(因为浏览器需要花费时间将新帧绘制到屏幕上,只有 <code>10 毫秒</code>来执行代码)</p> </li> <li> <p><code>Idle</code>:利用空闲时间完成推迟的工作(要实现第一条 response 在 100ms 内响应,Main 主线程 JS 工作应该小于 <code>50ms</code>,剩余的时间将主线程的控制从 js 返回给浏览器执行其像素管道、对用户输入作出反应等,因此最佳实践是将 js 的工作分成不大于 50 毫秒的块,如果用户开始交互,优先级最高的事项是响应用户。</p> </li> <li> <p><code>Load</code>:在 <code>1000 毫秒</code>以内呈现内容(无需完整加载,启用渐进式渲染,将非必需的加载推迟到空闲时间段</p> </li> <li> <p>通过 performance 面板,可以得到这四个维度的分析数据</p> </li> </ul> <h3>控制区</h3> <p><img src="https://i.loli.net/2019/05/01/5cc9642fa35b5.png" alt="" /></p> <ul> <li>点击<code>录制按钮</code>或者<code>开始录制并刷新页面按钮</code>,可以在控制区下方得到全部性能分析结果</li> <li>其中除了最下方的详细信息窗格以外,分析结果都是以时间为轴</li> <li>可以在 overview 窗格拖动鼠标,选择某段时间的分析结果</li> <li>滚动鼠标滚轮,缩放/移动选中事件</li> <li>在火焰图窗格,按住<code>shift</code>,滚动鼠标滚轮,可以上下</li> <li>在火焰图窗格,也可以直接左右拖动图表</li> <li>或者用<code>W A S D</code>按键控制缩放移动</li> <li><code>Disable JavaScript samples</code>默认情况,在<code>Main</code>主线程的火焰图中,会详细记录 js 函数之间的调用栈,可以开启此选项禁用调用栈记录</li> <li><code>Enable advanced paint instrumentation</code>启用高级绘图工具,可以在分析结果的<code>Frames</code>中的每一帧的详细结果中看到<code>Layer</code>选项卡,其中有选中帧的详细图层信息;也可以在<code>Main</code>主线程火焰图中选中绿色的<code>Paint</code>事件,在最底部详细信息的<code>Paint Profile</code>选项卡中,看到详细的页面绘制过程分析</li> <li><code>Collect garbage</code>控制器最右的垃圾桶图标,是强制执行垃圾回收,对于监控内存比较有用</li> </ul> <h3>FPS 图表 - Frames Per Seconds</h3> <p><img src="https://i.loli.net/2019/05/05/5ccee0f3335be.png" alt="" /></p> <ul> <li>FPS 图表中,绿色代表帧率高低,参考<code>RAIL</code>模型,帧率&gt;=60 时,用户能体验的顺滑的网页</li> <li>红色出现 代表有掉帧情况</li> </ul> <h3>CPU 图表</h3> <p><img src="https://i.loli.net/2019/05/05/5ccee13cd4479.png" alt="" /></p> <ul> <li>CPU 图表中,不同的颜色代表不同事件对 CPU 的占用,颜色信息如图</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccee05903554.png" alt="" /></p> <ul> <li>当 CPU 长时间被占满,就是当前网页性能需要优化的信号</li> </ul> <h3>SCREENSHOTS</h3> <ul> <li>鼠标在<code>FPS,CPU,NET</code>图表悬浮时,会展示出鼠标对应时间点的网页截屏,左右移动鼠标可以看到网页变化的重播效果</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccee37b9a4b3.gif" alt="" /></p> <h3>HEAP</h3> <p><img src="https://i.loli.net/2019/05/05/5ccee6f4b968d.png" alt="" /></p> <ul> <li>在 HEAP 图表中可以看到 JS 内存占用情况,与下方的 memory 窗格中的<code>JS Heap</code>相对应</li> <li>在 Memory 窗格还可以看到 Document 文档、Nodes DOM 节点、监听器、GPU 内存的习份内存统计</li> </ul> <h3>Frames</h3> <ul> <li>点击三角箭头展开<code>Frames</code>区域,鼠标悬浮/点击绿色方块,可以看到该特定帧的帧率和渲染耗时,当 FPS 低于 60,表明当前帧的渲染效率较低</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccee92a52b29.png" alt="" /></p> <h3>Main</h3> <ul> <li>点击三角箭头展开<code>Main</code>区域,可以看到主线程上事件的<code>火焰图</code></li> <li>x 轴是时间,每一块代表一个事件,y 轴代表堆栈,事件的上下堆叠,代表上层事件引发/调用了下层事件</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5cceec8b11f7f.png" alt="" /></p> <ul> <li>通过调用堆栈,可以找出导致低性能的事件及其源码位置</li> <li>当事件块出现红色三角,可以点击三角查看该事件的性能相关警告信息,并定位到引起警告的代码</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5cceef6801439.png" alt="" /></p> <p><img src="https://i.loli.net/2019/05/05/5ccef1a7c2c2a.gif" alt="" /></p> <ul> <li>点击<code>Animation Frame Fired</code>事件,可以在最下方<code>Summary</code>窗格查看触发动画事件的详细信息,点击<code>Initiator</code>后的<code>reveal</code>链接,会高亮到引起动画事件的事件</li> </ul> <p><img src="https://i.loli.net/2019/05/05/5ccef012a3dba.gif" alt="" /></p> <h3>性能相关扩展</h3> <ul> <li><a>网页性能-性能模型/加载/渲染/审计/优化</a></li> <li><a>the-anatomy-of-a-frame - 一个帧的剖析</a></li> <li><a>常见的时间线事件参考</a></li> </ul> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/devtools_rookie_intro/#post-comment/</comments>
</item>
<item>
<title>给UI看的WEB字体指南</title>
<link>https://www.scarsu.com/web_fonts/</link>
<guid isPermaLink="true">https://www.scarsu.com/web_fonts/</guid>
<description>UI小姐姐动不动就丢给你奇奇怪怪的字体和各种尺寸的图标?快把这些文章丢改她看</description>
<pubDate>Sun, 02 Feb 2020 00:00:00 GMT</pubDate>
<content:encoded><h1>WEB中的字体</h1> <h3>前言</h3> <pre><code>某天,隔壁新来的漂亮UI小妹妹又优雅的丢给你一个压缩包,你满心欢喜的解压 才发现又是新页面的需求 然后你摸了摸光亮的脑门,捋了捋稀疏的鬓角,吭哧吭哧开始画页面... 咦?pingfangsc medium,pingfangsc bold,pingfangsc light...?? (同理可换成 sans serif,microsoft yahei) 常用windows的你傻傻分不清楚小妹妹选定的mac字体 这是同一个字体吗?font-weight还要写吗?不写的话win上显示就不一样了呀... 于是你只能再打开小妹妹的聊天面板,码下一大段话“不同系统默认字体不一样...巴拉巴拉...web安全字体...备选字体集...字体文件包” 然后在你的小本本上,画上第1025个圈圈,记录并预测下,到底还要跟多少UI做好字体交易... 虽然你会为跟小妹妹进行了一次深入性的技术沟通 而心情大好,但是 终将有一天,你的耐心会消耗殆尽,然后把这篇文章,丢到部门UI群 从那以后,UI小妹妹们... ... 给你授予了“最矫情的技术没有之一”的称号 并 丢了更多pingfangsc给你🐶 </code></pre> <h3>WEB 安全字体</h3> <p>不同操作系统内置的字体是不同的,甚至差异很大,例如: <img src="/images/picgo/web_font01.png" alt="OS字体差异图" /></p> <p><img src="/images/picgo/20230708232300.png" alt="WEB中文安全字体" /></p> <p>win7和mac下,只有十种字体重合,Windows XP中甚至没有其中的Palatino 和Trebuchet MS字体.....</p> <p>因此为了兼容性考虑,最安全的字体有:</p> <ul> <li>Arial</li> <li>Courier New</li> <li>Georgia</li> <li>Times New Roman</li> <li>Verdana</li> <li>...</li> <li>随着操作系统的发展更新,这个数据也不是最准确的,可选的可能比上面五个多一些,请以实际测试为准</li> </ul> <h3>备选字体组合</h3> <p>当不确定网页用户电脑上是否有某种字体时,可以使用字体组合,提供备选的字体:</p> <pre><code>font-family: "Times New Roman", Times, serif; </code></pre> <p>备选的意思可以参考备胎,就是:</p> <p>当浏览器在系统中找不到第一种字体时,会自动去使用第二种,依次类推...</p> <h3>自定义字体</h3> <p>如果对某种不通用字体有刚需,可以使用自定义字体。</p> <ol> <li>UI需要提供字体的woff和eot格式源文件(需要考虑文件太大会影响网页加载)</li> <li>前端需要在css中自定义@font-face(不用担心浏览器兼容性)</li> </ol> <p>至于为什么是woff和eot:</p> <pre><code>TureTpe(.ttf)格式: .ttf字体是Windows和Mac系统的最常见的字体,是一种RAW格式,不为网站优化 OpenType(.otf)格式: .otf字体被认为是一种原始的字体格式,其内置在TureType的基础上,所以也提供了更多的功能 Web Open Font Format(.woff)格式: .woff字体是Web字体中最佳格式,他是一个开放的TrueType/OpenType的压缩版本,同时也支持元数据包的分离 Embedded Open Type(.eot)格式: .eot字体是IE专用字体,可以从TrueType创建此格式字体 SVG(.svg)格式: .svg字体是基于SVG字体渲染的一种格式 这就意味着在@font-face中我们至少需要.woff,.eot两种格式字体,甚至还需要.svg等字体达到更多种浏览版本的支持。 </code></pre> <p>不同浏览器对不同字体文件格式的兼容性也不同:</p> <p><img src="https://www.scarsu.com/images/gitbook/web_font02.png" alt="OS字体文件兼容性图" /></p> <p><strong>总结来说:eot(供ie使用) + woff(供其他现代浏览器使用)是最佳组合,如果要兼容更多老版本浏览器/移动端浏览器可以加上ttf或svg)</strong></p> <p>定义font-face语法:</p> <pre><code>@font-face { font-family: &lt;YourWebFontName自定义的字体名&gt;; src: &lt;source&gt; [&lt;format&gt;][,&lt;source&gt; [&lt;format&gt;]]*; [font-weight: &lt;weight&gt;]; [font-style: &lt;style&gt;]; } /*source:字体文件路径*/ /*format:字体文件格式 eg. ttf,otf,woff,eot,svg...*/ /*示例*/ @font-face { font-family: 'YourWebFontName'; src: url('YourWebFontName.eot'); /* IE9兼容模式 */ src: url('YourWebFontName.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ url('YourWebFontName.woff') format('woff'), /* 现代浏览器 */ url('YourWebFontName.ttf') format('truetype'), /* Safari, Android, iOS */ url('YourWebFontName.svg#YourWebFontName') format('svg'); /* 老版本 iOS */ } </code></pre> <h3>总结</h3> <ol> <li>UI最好就用最安全的几种通用字体</li> <li>如果想用不通用的字体 <ul> <li>要么:提供备选字体</li> <li>要么:提供字体文件(eot+woff+[svg/ttf]),且要考虑选择字体源文件体积较小的字体</li> </ul> </li> </ol> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/web_fonts/#post-comment/</comments>
</item>
<item>
<title>ML08 | 多分类问题训练:IRIS鸢尾花分类问题</title>
<link>https://www.scarsu.com/fed_ml_08_iris/</link>
<guid isPermaLink="true">https://www.scarsu.com/fed_ml_08_iris/</guid>
<description>Javascript玩转机器学习08</description>
<pubDate>Thu, 09 Jan 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>多分类问题</h2> <ul> <li> <p>手写数字分类:10种分类</p> </li> <li> <p>图片分类:成千上万种分类</p> </li> <li> <p>多种特征:需要多层神经网络</p> </li> <li> <p>多种分类输出:需要在输出层加softMax函数</p> </li> </ul> <h2>鸢尾花(iris)分类问题</h2> <ul> <li>著名的数据集,诞生了很久,被无数科学家用来验证自己的算法</li> <li>三种分类(输出):山鸢尾,变色鸢尾,Virginica鸢尾</li> <li>四种特征(输入):花瓣长、宽、花萼长、宽</li> </ul> <h2>加载IRIS数据集(训练集与验证集)</h2> <ul> <li>用脚本生成IRIS数据集:训练集+验证集</li> </ul> <pre><code>//生成:训练集特征,训练集标签,验证集特征,验证集标签(数据类型为tensor) const [xTrain,yTrain,xTest,yTest] = getIrisData(0.15); xTrain.print(); yTrain.print(); xTest.print(); yTest.print(); console.log(IRIS_CLASSES); </code></pre> <ul> <li>打印结果:</li> </ul> <p><img src="/images/ai/42.png" alt="image" /></p> <h2>定义模型结构:带有softMax激活函数的多层神经网络</h2> <ul> <li>初始化一个神经网络模型</li> </ul> <pre><code>//初始化模型 const model = tf.sequential(); </code></pre> <ul> <li>为模型添加两个层</li> <li>设计层的神经元个数、inputShape、激活函数</li> </ul> <pre><code>//添加隐藏层:全链接层 model.add(tf.layers.dense({ units:10, //10个神经元,超参数 inputShape:[xTrain.shape[1]], activation:'sigmoid', })); //添加输出层:全链接层 model.add(tf.layers.dense({ units:3, //必须是输出类别的个数 // inputShape:[yTrain.shape], //除了第一层以外 都不需要设计inputShape,会根据上一层的输出自动设计 activation:'softmax', //softmax 激活函数 适用于多种分类输出层 })); </code></pre> <h2>交叉熵损失函数</h2> <ul> <li>交叉熵损失函数 <strong>Cross-Entropy</strong>:是LogLoss对数损失函数的多分类版本,都用于度量分类神经网络模型的性能。</li> <li>当分类数为2时,交叉熵损失=对数损失。</li> </ul> <p><img src="/images/ai/43.png" alt="image" /></p> <h2>定义损失函数、优化器、准确度度量</h2> <pre><code> //设置损失函数,增加训练过程中的“准确度”度量 model.compile({ loss:'categoricalCrossentropy', optimizer: tf.train.adam(0.1), metrics: ['accuracy'] }); </code></pre> <h2>训练模型并可视化</h2> <pre><code>//训练并可视化 await model.fit(xTrain,yTrain,{ epochs:100, validationData:[xTest,yTest], callbacks:tfvis.show.fitCallbacks( {name:''}, ['loss','val_loss','acc','val_acc'], {callbacks:['onEpochEnd']}, ), }) </code></pre> <ul> <li>训练过程:</li> </ul> <p><img src="/images/ai/44.png" alt="image" /></p> <h2>模型多分类预测</h2> <pre><code>window.predict = (form)=&gt;{ const input = tf.tensor([[ form.a.value * 1, form.b.value * 1, form.c.value * 1, form.d.value * 1, ]]); debugger; const pred = model.predict(input); pred.print(); alert(`预测结果${IRIS_CLASSES[pred.argMax(1).dataSync(0)]}`); } </code></pre> <p><img src="/images/ai/45.png" alt="image" /></p> <hr /> <p><a>代码仓库</a></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/fed_ml_08_iris/#post-comment/</comments>
</item>
<item>
<title>ML07 | XOR回归训练:多层神经网络</title>
<link>https://www.scarsu.com/fed_ml_07_xor_regression/</link>
<guid isPermaLink="true">https://www.scarsu.com/fed_ml_07_xor_regression/</guid>
<description>Javascript玩转机器学习07</description>
<pubDate>Tue, 07 Jan 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>XOR 异或逻辑回归</h2> <ul> <li>不是线性问题</li> <li>需要多层神经网络+激活函数来解决</li> </ul> <p><img src="/images/ai/36.png" alt="image" /></p> <h2><a>Google Playground网站</a></h2> <ul> <li>用TFJS写的 可视化学习机器学习的网站</li> </ul> <p><img src="/images/ai/37.png" alt="image" /></p> <h2>加载XOR数据集</h2> <pre><code>//调脚本接口生成模拟数据 const data = getData(400); console.log(data); </code></pre> <ul> <li>模拟数据 数据结构: <img src="/images/ai/38.png" alt="image" /></li> </ul> <pre><code>//可视化 tfvis.render.scatterplot( { name: "XOR训练数据" }, { values: [ data.filter(p =&gt; p.label === 1), data.filter(p =&gt; p.label === 0) ] } ); </code></pre> <ul> <li>可视化结果</li> </ul> <p><img src="/images/ai/39.png" alt="image" /></p> <h2>定义模型结构:多层神经网络</h2> <ul> <li>初始化一个神经网络模型</li> <li>为模型添加两个层:隐藏层+输出层</li> <li>设计层的激活函数、inputShape、神经元个数</li> </ul> <pre><code>//初始化一个 sequential model const mdoel = tf.sequential(); //添加一个隐藏层(全连接层) mdoel.add( tf.layers.dense({ units: 4, inputShape: [2], //只有第一层需要设置inputShape activition: "relu" }) ); //添加一个输出层(全连接层) model.add( tf.layers.dense({ units: 1, activition: "sigmoid" //需要输出[0,1]之间的概率所以选sigmoid }) ); </code></pre> <ul> <li>定义模型的损失函数和优化器</li> </ul> <pre><code>//定义模型的损失函数和优化器 model.compile({ loss: tf.losses.logLoss, optimizer: tf.train.adam(0.1) }); </code></pre> <h2>训练模型并预测</h2> <ul> <li>训练数据转换为tensor</li> </ul> <pre><code>//训练数据转换为tensor const inputs = tf.tensor(data.map(p =&gt; [p.x, p.y])); const labels = tf.tensor(data.map(p =&gt; p.label)); </code></pre> <ul> <li>训练模型并可视化训练过程</li> </ul> <pre><code>//训练 await model.fit(inputs, labels, { epochs: 10, callbacks: tfvis.show.fitCallbacks({ name: "XOR训练过程" }, ["loss"]) }); </code></pre> <ul> <li> <p>训练过程 <img src="/images/ai/40.png" alt="image" /></p> </li> <li> <p>进行预测</p> </li> </ul> <pre><code>//预测 window.predict = form =&gt; { const pred = model.predict( tf.tensor([[form.x.value * 1, form.y.value * 1]]) ); alert(`预测结果:${pred.dataSync()[0]}`); }; </code></pre> <ul> <li>预测结果</li> </ul> <p><img src="/images/ai/41.png" alt="image" /></p> <hr /> <p><a>代码仓库</a></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/fed_ml_07_xor_regression/#post-comment/</comments>
</item>
<item>
<title>ML06 | 逻辑回归训练</title>
<link>https://www.scarsu.com/fed_ml_06_logistic_regression/</link>
<guid isPermaLink="true">https://www.scarsu.com/fed_ml_06_logistic_regression/</guid>
<description>Javascript玩转机器学习06</description>
<pubDate>Mon, 06 Jan 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>逻辑回归简介</h2> <ul> <li>解决分类问题,输出一个概率[0,1]</li> </ul> <p><img src="/images/ai/30.png" alt="image" /></p> <h2>加载二分类数据集</h2> <ul> <li>使用脚本生成二分类数据集</li> </ul> <pre><code>//利用脚本生成400组二分类数据 const data = getData(400); console.log(data); </code></pre> <ul> <li>数据结构如图:</li> </ul> <p><img src="/images/ai/31.png" alt="image" /></p> <ul> <li>可视化二分类数据集(散点图)</li> </ul> <pre><code>//可视化为散点图 tfvis.render.scatterplot( {name:'二分类逻辑回归 训练数据'}, { values:[ data.filter(p=&gt;p.label === 1), data.filter(p=&gt;p.label === 0), ] } ) </code></pre> <ul> <li>可视化效果:</li> </ul> <p><img src="/images/ai/32.png" alt="image" /></p> <h2>定义模型结构:带有激活函数的单个神经元</h2> <ul> <li>初始化一个sequential神经网络模型</li> </ul> <pre><code>//添加一个sequential神经网络模型 const model = tf.sequential(); </code></pre> <ul> <li>为模型添加层,设计层的神经元个数、inputShape、激活函数(<code>model.add</code>)</li> </ul> <pre><code>//为模型添加一个 dense全链接层(点乘 偏置 激活函数 适合用于二分类回归) model.add(tf.layers.dense({ units:1, //神经元个数 inputShape:[2], //输入的tensor的shape:长度为2的一维数组 activation:'sigmoid', //sigmoid这种激活函数的曲线y值范围始终在[0,1] })); </code></pre> <h2>对数损失函数 Log Loss</h2> <ul> <li>利用<code>wiki.fast.ai</code>人工智能教学网站,理解<a>对数损失函数</a></li> <li>对数损失函数:用于测量预测值在[0,1]的分类模型的性能</li> <li>如下图为:标签为1的预测值的对数损失函数曲线,预测越接近真实值1,损失越小,越接近0 ,损失越大:</li> </ul> <p><img src="/images/ai/33.png" alt="image" /></p> <h2>用TFJS API设置损失函数为:LogLoss(<code>model.compile</code>)</h2> <pre><code>//设置损失函数为:LogLoss 对数损失函数 model.compile({loss:tf.losses.logLoss}); </code></pre> <h2>设置超参数,训练模型(<code>model.fit</code>)</h2> <pre><code>//设置超参数 训练模型 await model.fit(inputs, labels,{ batchSize:40, epochs:50, callbacks:tfvis.show.fitCallbacks( {name:'训练过程'}, ['loss'] ) }) </code></pre> <ul> <li>训练过程截图:</li> </ul> <p><img src="/images/ai/34.png" alt="image" /></p> <h2>预测</h2> <ul> <li>编写前端界面输入待预测数据</li> <li>使用训练好的模型进行预测(<code>model.predict</code>)</li> </ul> <pre><code>&lt;form action="" onsubmit="predict(this);return false;"&gt; x: &lt;input type="text" name="x" /&gt; y: &lt;input type="text" name="y" /&gt; &lt;button type="submit"&gt;预测&lt;/button&gt; &lt;/form&gt; </code></pre> <pre><code>window.predict = (form) =&gt; { const pred = model.predict(tf.tensor([[form.x.value * 1, form.y.value * 1]])); alert(`预测结果:${pred.dataSync()[0]}`); }; </code></pre> <ul> <li>输入2,2 预测结果:</li> </ul> <p><img src="/images/ai/35.png" alt="image" /></p> <hr /> <p><a>代码仓库</a></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/fed_ml_06_logistic_regression/#post-comment/</comments>
</item>
<item>
<title>ML05 | 归一化</title>
<link>https://www.scarsu.com/fed_ml_05_normalize/</link>
<guid isPermaLink="true">https://www.scarsu.com/fed_ml_05_normalize/</guid>
<description>Javascript玩转机器学习05</description>
<pubDate>Sun, 05 Jan 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>归一化:</h2> <ul> <li>将大数量级<code>特征</code>转化到较小的数量级下,通常是[0,1]或[-1,1]</li> </ul> <h2>为什么要归一化:</h2> <ul> <li>绝大多数TensorFlow.js的模型都不是给特别大的数设计的</li> <li>将不同数量级的<code>特征</code>转换到统一数量级,避免某个特征影响过大</li> </ul> <h2>归一化任务实例-身高体重预测:</h2> <ul> <li>准备身高体重数据,可视化</li> </ul> <pre><code>//模拟标签和特征 const heights=[150,160,170,180]; const weights=[40,50,60,70]; //可视化数据 tfvis.render.scatterplot( {name:'身高体重预测'}, {values:heights.map((x,i)=&gt;({x,y:weights[i]}))}, { xAxisDomain:[140,190], yAxisDomain:[30,80], } ) </code></pre> <ul> <li>用TFJS的API<code>归一化</code>数据</li> </ul> <pre><code>//将数据转换为tensor 并归一化 const inputs = tf.tensor(heights).sub(150).div(30); const labels = tf.tensor(weights).sub(40).div(30); inputs.print(); labels.print(); </code></pre> <ul> <li>归一化后数据:</li> </ul> <p><img src="/images/ai/28.png" alt="image" /></p> <ul> <li>训练模型并预测</li> </ul> <pre><code>//创造一个连续模型 const model = tf.sequential(); model.add(tf.layers.dense({units:1,inputShape:[1]})); //添加一个全连接层(点乘权重+偏置) model.compile({loss:tf.losses.meanSquaredError,optimizer:tf.train.sgd(0.1)}); //设置:损失函数为均方误差MSE,优化器为随机梯度下降SGD,学习速率为0.1,学习率是一个需要调整优化的超参数 await model.fit(inputs, labels, { batchSize: 4, //批量训练的数据集大小(超参数,需要不断调整试验) epochs: 100, //迭代实验次数(超参数,需要不断调整试验) callbacks: tfvis.show.fitCallbacks({ name: "训练过程" }, ["loss"]) }); //将待预测数据190转为Tensor,用训练好的模型进行预测 const output = model.predict(tf.tensor([190]).sub(150).div(30)); output.print(); </code></pre> <ul> <li>将结果反归一化为正常数据</li> </ul> <pre><code>//将输出的Tensor反归一化并转为普通数据并显示 alert(`如果身高是190cm,预测体重为${output.mul(30).add(40).dataSync()}kg`); </code></pre> <ul> <li>预测结果:</li> </ul> <p><img src="/images/ai/29.png" alt="image" /></p> <ul> <li>上述例子中,归一化的关键步骤就是:</li> </ul> <pre><code>减去 min(最小值) 除以 diff(最大值最小值的差) </code></pre> <ul> <li>反归一化的关键步骤就是归一化的反操作:</li> </ul> <pre><code>乘以 diff 加上 min </code></pre> <hr /> <p><a>代码仓库</a></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/fed_ml_05_normalize/#post-comment/</comments>
</item>
<item>
<title>ML04 | 线性回归训练</title>
<link>https://www.scarsu.com/fed_ml_04_linear_regression/</link>
<guid isPermaLink="true">https://www.scarsu.com/fed_ml_04_linear_regression/</guid>
<description>Javascript玩转机器学习04</description>
<pubDate>Thu, 02 Jan 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>线性回归是什么</h2> <ul> <li>一种统计分析方法</li> <li>用于确定两种(或以上)变量间相互依赖的<strong>定量关系</strong></li> <li>eg.身高体重预测(两种变量)、房价预测(多变量)</li> </ul> <h2>操作步骤</h2> <ul> <li>准备、可视化:训练数据</li> <li>用TensorFlow.js的API构建一个简单的神经网络</li> <li>训练模型 并 预测</li> </ul> <h2>前置条件</h2> <ul> <li>最新版本chrome</li> <li>代码编辑器(eg.VSCODE</li> <li>基础的前端、神经网络知识</li> </ul> <h2>准备、可视化:训练数据(实操)</h2> <ul> <li>准备线性回归训练数据(特征、标签)</li> <li>使用tfvis可视化训练数据(tfvis是一个神经网络可视化库)</li> </ul> <pre><code>&lt;!-- linear-regression/index.html--&gt; &lt;script src="script.js"&gt;&lt;/script&gt; </code></pre> <pre><code>// linear-regression/script.js import * as tfvis from "@tensorflow/tfjs-vis"; window.onload = () =&gt; { const xs = [1, 2, 3, 4]; //input const ys = [1, 3, 5, 7]; //output tfvis.render.scatterplot( { name: "线性回归训练数据" }, { values: xs.map((x, i) =&gt; ({ x, y: ys[i] })) }, { xAxisDomain: [0, 5], yAxisDomain: [0, 9] }, ); }; </code></pre> <pre><code>-- bash parcel li*/*.html </code></pre> <h2>可视化效果</h2> <p><img src="/images/ai/17.png" alt="可视化效果" /></p> <h2>定义单个神经元的神经网络模型</h2> <ul> <li>初始化一个神经网络模型(model)</li> <li>为模型添加<strong>层</strong>(layer)</li> <li>设计<strong>层</strong>的神经元个数和<strong>inputShape</strong></li> </ul> <pre><code>import * as tfjs from "@tensorflow/tfjs"; import * as tfvis from "@tensorflow/tfjs-vis"; window.onload = () =&gt; { const xs = [1, 2, 3, 4]; //input const ys = [1, 3, 5, 7]; //output tfvis.render.scatterplot( { name: "线性回归训练数据" }, { values: xs.map((x, i) =&gt; ({x, y:ys[i]})) }, {xAxisDomain:[0,5],yAxisDomain:[0,9]} ); const model = sf.sequential(); //创造一个连续模型 model.add(tf.layers.dense({units:1,inputShape:[1]})); //添加一个全连接层(点乘权重+偏置) }; </code></pre> <h2>损失函数:均方误差(MSE-MeanSquaredError)</h2> <ul> <li> <p>利用<a>google ML playground</a> 理解<strong>损失函数</strong>与<strong>均方误差</strong>:</p> </li> <li> <p><strong>损失函数</strong>用于计算预测值与实际值差距</p> </li> </ul> <p><img src="/images/ai/18.png" alt="预测值、实际值、损失" /></p> <ul> <li><strong>均方误差</strong>(meanSquaredError)是一种损失函数</li> </ul> <p><img src="/images/ai/19.png" alt="MSE" /></p> <ul> <li>在TensorFlow.js中设置损失函数</li> </ul> <pre><code>import * as tfjs from "@tensorflow/tfjs"; import * as tfvis from "@tensorflow/tfjs-vis"; window.onload = () =&gt; { const xs = [1, 2, 3, 4]; //input const ys = [1, 3, 5, 7]; //output tfvis.render.scatterplot( { name: "线性回归训练数据" }, { values: xs.map((x, i) =&gt; ({x, y:ys[i]})) }, {xAxisDomain:[0,5],yAxisDomain:[0,9]} ); const model = sf.sequential(); //创造一个连续模型 model.add(tf.layers.dense({units:1,inputShape:[1]})); //添加一个全连接层(点乘权重+偏置) model.compile({loss:tf.losses.meanSquaredError}) //设置损失函数为均方误差MSE }; </code></pre> <h2>优化器:随即梯度下降(SGD)</h2> <ul> <li> <p>利用<a>google ML playground</a> 理解<strong>优化器</strong>与<strong>随机梯度下降</strong>:</p> </li> <li> <p>迭代试错:</p> </li> </ul> <p><img src="/images/ai/20.png" alt="迭代试错" /></p> <ul> <li>梯度下降法:</li> </ul> <p><img src="/images/ai/21.png" alt="梯度下降法" /></p> <ul> <li>SGD</li> </ul> <p><img src="/images/ai/22.png" alt="SGD" /></p> <ul> <li>在TensorFlow.js中设置<strong>优化器</strong></li> </ul> <pre><code>import * as tfjs from "@tensorflow/tfjs"; import * as tfvis from "@tensorflow/tfjs-vis"; window.onload = () =&gt; { const xs = [1, 2, 3, 4]; //input const ys = [1, 3, 5, 7]; //output tfvis.render.scatterplot( { name: "线性回归训练数据" }, { values: xs.map((x, i) =&gt; ({x, y:ys[i]})) }, {xAxisDomain:[0,5],yAxisDomain:[0,9]} ); const model = sf.sequential(); //创造一个连续模型 model.add(tf.layers.dense({units:1,inputShape:[1]})); //添加一个全连接层(点乘权重+偏置) model.compile({loss:tf.losses.meanSquaredError,optimizer:tf.train.sgd}); //设置:损失函数为均方误差MSE,优化器为随机梯度下降SGD }; </code></pre> <h2>训练模型并可视化训练过程</h2> <ul> <li>将训练数据转为tensor</li> <li>训练模型</li> <li>用<strong>tfvis</strong>可视化训练过程</li> </ul> <pre><code>import * as tf from "@tensorflow/tfjs"; import * as tfvis from "@tensorflow/tfjs-vis"; window.onload = async () =&gt; { const xs = [1, 2, 3, 4]; //input const ys = [1, 3, 5, 7]; //output tfvis.render.scatterplot( { name: "线性回归训练数据" }, { values: xs.map((x, i) =&gt; ({x, y:ys[i]})) }, {xAxisDomain:[0,5],yAxisDomain:[0,9]} ); const model = tf.sequential(); //创造一个连续模型 model.add(tf.layers.dense({units:1,inputShape:[1]})); //添加一个全连接层(点乘权重+偏置) model.compile({loss:tf.losses.meanSquaredError,optimizer:tf.train.sgd(0.1)}); //设置:损失函数为均方误差MSE,优化器为随机梯度下降SGD,学习速率为0.1,学习率是一个需要调整优化的超参数 const inputs = tf.tensor(xs); const labels = tf.tensor(ys); await model.fit(inputs, labels,{ batchSize: 4, //批量训练的数据集大小(超参数,需要不断调整试验) epochs:100, //迭代实验次数(超参数,需要不断调整试验) callbacks:tfvis.show.fitCallbacks( {name:'训练过程'}, ['loss'], ) }); }; </code></pre> <ul> <li>批量处理size设置为1,训练初期会有明显抖动</li> </ul> <p><img src="/images/ai/23.png" alt="" /></p> <p><img src="/images/ai/24.png" alt="" /></p> <ul> <li>批量处理size设置为4,训练曲线比较平滑</li> </ul> <p><img src="/images/ai/25.png" alt="" /></p> <p><img src="/images/ai/26.png" alt="" /></p> <h2>进行预测</h2> <ul> <li>将待预测数据转为Tensor</li> <li>用训练好的模型进行预测</li> <li>将输出的Tensor转为普通数据并显示(模型的输入输出都是模型)</li> </ul> <pre><code> const output = model.predict(tf.tensor([5])); //将待预测数据5转为Tensor,用训练好的模型进行预测 output.print(); console.log(output.dataSync()); //将输出的Tensor转为普通数据并显示 </code></pre> <p><img src="/images/ai/27.png" alt="预测结果" /></p> <hr /> <p><a>代码仓库</a></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/fed_ml_04_linear_regression/#post-comment/</comments>
</item>
<item>
<title>贫穷的本质:我们为什么摆脱不了贫穷读书输出</title>
<link>https://www.scarsu.com/poor_economics/</link>
<guid isPermaLink="true">https://www.scarsu.com/poor_economics/</guid>
<description>2019诺贝尔经济学家获奖作品、贫穷的本质&如何逃离贫穷陷阱</description>
<pubDate>Thu, 02 Jan 2020 00:00:00 GMT</pubDate>
<content:encoded><h2>简介</h2> <ul> <li> <p>作者[印度]阿比吉特·班纳吉(Abhijit V.Banerjee)、[法]埃斯特·迪弗洛 (Esther Duflo)</p> </li> <li> <p>两位作者深入五大洲多个国家的穷人世界,调查贫困人群最集中的18个国家和地区,从穷人生活的多个方面,探寻贫穷真正的根源</p> </li> <li> <p>该书用九章大篇幅,从<strong>营养、健康、教育、生育、风险管理、贷款、存款、创业、政治参与</strong>等九个方面探讨穷人的生存、选择和突围,以及援助、制度对穷人的意义。</p> </li> <li> <p>为什么穷人吃不饱饭还要买电视?</p> </li> <li> <p>为什么他们的孩子即使上了学也不爱学习?</p> </li> <li> <p>为什么他们放着免费的健康生活不去享受,却要自己花钱买药?</p> </li> <li> <p>为什么他们能创业却难以守业?</p> </li> <li> <p>为什么大多数人认为小额信贷、穷人银行没什么效用?</p> </li> </ul> <hr /> <p>这本书太难啃了,未完待续</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/poor_economics/#post-comment/</comments>
</item>
<item>
<title>State of JS | 2019年度javascript行业报告</title>
<link>https://www.scarsu.com/2019_javascript_report/</link>
<guid isPermaLink="true">https://www.scarsu.com/2019_javascript_report/</guid>
<description>stateofjs团队曾以为Javascript生态圈已经趋于稳定,2018是他们的最后一次行业调查,但事实是,Javascript仍没有停下变化的脚步</description>
<pubDate>Tue, 31 Dec 2019 00:00:00 GMT</pubDate>
<content:encoded><h2>作者前言</h2> <ul> <li><a>stateofjs网址</a></li> <li>2018年,我第一次关注stateofjs调查,目的是通过真实数据,更真实广泛的了解Javascript生态圈的变化,便于自己对于主流技术的了解和<strong>自检</strong>。</li> <li>2018的调查,20,268参与者中,只有75位中国地区开发者,比例是0.37%。</li> <li>今年,我也参与到了调查当中,提供了一份我的数据。</li> <li>今年总共有21,717位开发者参与调查,其中有247位中国地区的开发者,比例是1.3%。</li> <li>中国地区开发者比例,说明这个调查并不能反映中国地区的Javascript真实发展状况,但是比例的增加从侧面说明了中国开发者正在向国际靠拢,希望有越来越多的中国开发者能跨越国界,走向世界技术圈</li> <li>⭐今年的报告,有一项新增的数据,引起了我的关注,就是<strong>Javascript开发者信息源</strong>,这是我根据报告数据整理出来的<a>Javascript开发者信息源聚合链接</a>,这项数据有助于我们时刻关注Javascript社区的主流信息</li> </ul> <h2>数据来源</h2> <p><strong>今年增加了一项参与调查途径的分布图</strong> 个人认为,这一项数据,对于我们了解前端主流信息源和社交渠道有一定的参考价值 <img src="/images/stateofjs/201908.png" alt="" /></p> <p><strong>调查参与者 国家分布图:</strong></p> <p><img src="/images/stateofjs/201903.png" alt="" /></p> <p><strong>调查参与者 薪资分布图:</strong></p> <p><img src="/images/stateofjs/201904.png" alt="" /></p> <p><strong>调查参与者 开发经验分布图:</strong></p> <p><img src="/images/stateofjs/201905.png" alt="" /></p> <p><strong>调查参与者 所属公司体量分布图:</strong></p> <p><img src="/images/stateofjs/201906.png" alt="" /></p> <p><strong>调查参与者 性别分布图:</strong></p> <p><img src="/images/stateofjs/201907.png" alt="" /></p> <h2>概览</h2> <p><img src="/images/stateofjs/201901.png" alt="" /></p> <p><img src="/images/stateofjs/201902.png" alt="" /></p> <h2>JavaScript 特性</h2> <ul> <li>这是今年新增的一项数据</li> <li>Javascript是一个不停更新的语言,每年都有新的Ecmascript版本发布,从箭头函数到解构,过去几年中添加的新特性现在已成为我们编写JavaScript不可或缺的一部分。</li> <li>因此,从今年开始,除了开发Javascript使用的工具外,增加了这项数据:JavaScript编写方式:所使用的模式,语法和特性</li> </ul> <h3>语法</h3> <p><img src="/images/stateofjs/201909.png" alt="箭头函数、解构、扩展运算符" /></p> <h3>语言</h3> <p><img src="/images/stateofjs/201911.png" alt="代理、异步promise、修饰器" /></p> <h3>数据结构</h3> <p><img src="/images/stateofjs/201912.png" alt="" /></p> <h3>浏览器API</h3> <p><img src="/images/stateofjs/201910.png" alt="fetch、i18n、websocket、localstorage..." /></p> <h3>其他特性</h3> <p><img src="/images/stateofjs/201913.png" alt="PWA、WASM" /></p> <h2>JavaScript Flavors</h2> <p>可以编译成 javasript 代码 的 各种语言/语法规范/javascript 超集</p> <p><img src="/images/stateofjs/201914.png" alt="" /></p> <h2>前端框架 Front-end Frameworks</h2> <p><img src="/images/stateofjs/201915.png" alt="" /></p> <h2>数据层 Data Layer</h2> <p><img src="/images/stateofjs/201916.png" alt="" /></p> <h2>后端框架 Back-end Frameworks</h2> <p><img src="/images/stateofjs/201917.png" alt="" /></p> <h2>测试 Testing</h2> <p><img src="/images/stateofjs/201918.png" alt="" /></p> <h2>移动端/客户端 Mobile &amp; Desktop</h2> <p><img src="/images/stateofjs/201919.png" alt="" /></p> <h2>函数库 Utility Libraries</h2> <p><img src="/images/stateofjs/201920.png" alt="" /></p> <p><img src="/images/stateofjs/201921.png" alt="" /></p> <h2>编辑器 Text Editors</h2> <p><img src="/images/stateofjs/201922.png" alt="" /></p> <p><img src="/images/stateofjs/201923.png" alt="" /></p> <h2>js 开发者使用的浏览器</h2> <p><img src="/images/stateofjs/201924.png" alt="" /></p> <p><img src="/images/stateofjs/201925.png" alt="" /></p> <h2>构建工具 Build Tools</h2> <p><img src="/images/stateofjs/201926.png" alt="" /></p> <p><img src="/images/stateofjs/201927.png" alt="" /></p> <h2>js 开发者使用的其他语言 Other Languages</h2> <p><img src="/images/stateofjs/201928.png" alt="" /></p> <p><img src="/images/stateofjs/201929.png" alt="" /></p> <h2>信息源(NEW*)</h2> <ul> <li>这是新年调查新增的一项数据</li> <li>这项数据显示了调查者依赖的信息源,包括博客和杂志、网站和课程、播客</li> <li><a>点击此处查看这些信息源的链接</a></li> </ul> <p><img src="/images/stateofjs/201930.png" alt="" /> <img src="/images/stateofjs/201931.png" alt="" /> <img src="/images/stateofjs/201932.png" alt="" /> <img src="/images/stateofjs/201933.png" alt="" /> <img src="/images/stateofjs/201934.png" alt="" /> <img src="/images/stateofjs/201935.png" alt="" /></p> <h2>开发者的感受</h2> <p><strong>“Javascript 正在往正确的方向发展”</strong></p> <p><img src="/images/stateofjs/201936.png" alt="" /></p> <p><strong>“当下构建 Javascript app 过于复杂惹”</strong></p> <p><img src="/images/stateofjs/201937.png" alt="" /></p> <p><strong>“Javascript 被过度使用”</strong></p> <p><img src="/images/stateofjs/201938.png" alt="" /></p> <p><strong>“我喜欢构建 JavaScript 应用程序”</strong></p> <p><img src="/images/stateofjs/201939.png" alt="" /></p> <p><strong>“我希望 JavaScript 成为我的主要编程语言”</strong></p> <p><img src="/images/stateofjs/201940.png" alt="" /></p> <p><strong>“JavaScript 生态系统变化太快”</strong></p> <p><img src="/images/stateofjs/201941.png" alt="" /></p> <h2>年度之最</h2> <ul> <li><strong>被采用最多的特性: Arrow Function</strong></li> </ul> <blockquote> <p>箭头函数是本年度使用最多的JavaScript功能,拥有97.8%的用户使用它。 &gt; promise &gt; 扩展运算符</p> </blockquote> <ul> <li><strong>使用最多的技术: React</strong></li> </ul> <blockquote> <p>React是今年使用最多的技术,拥有16099个用户。 &gt; Express &gt; Redux</p> </blockquote> <ul> <li><strong>满意度最高: Jest</strong></li> </ul> <blockquote> <p>有96.4%的用户愿意再次使用它,Jest再次证明了它不是在开玩笑。 &gt; GraphQL &gt; Cypress</p> </blockquote> <ul> <li><strong>最感兴趣: GraphQL</strong></li> </ul> <blockquote> <p>听说过GraphQL的开发人员中有89.6%希望学习它。 那是很重要的兴趣! &gt; Jest &gt; Apollo</p> </blockquote> <ul> <li><strong>最广泛的信息源: Stack Overflow</strong></li> </ul> <blockquote> <p>拥有17942个用户的Stack Overflow是今年使用最多的资源。 &gt; MDN &gt; CSS Tricks</p> </blockquote> <ul> <li><strong>黑马奖: Svelte</strong></li> </ul> <blockquote> <p>斯维尔特(Svelte)在今年的调查中首次亮相,我们迫不及待想知道它的去向 &gt; Next.js &gt; Stencil</p> </blockquote> <h2>总结</h2> <p>stateofjs团队在总结中说:</p> <blockquote> <p>You know how you sometimes start tweaking a few lines of code here and there, then realize a couple functions could use some refactoring, and then one things leading to another you find yourself a few days later in the process of setting up a brand new stack complete with a database and GraphQL API?</p> <p>This is what happened to us this year. And while it resulted in quite a few stressful evenings as we tried to wrap this up and release the State of JavaScript 2019 results in, well, 2019; it also means we now have a much more powerful and flexible stack to collect and analyze data going forward.</p> </blockquote> <p>“你有时候会在这里那里调整几行代码,然后发现有几个函数可以重构,然后一个变更引发另一个变更,几天后你发现重构的过程中,用上了数据库和GraphQL API,建立了一个全新的技术栈...”</p> <p>这是今年发生在他们身上的故事,使用数据库和GraphQL重构,使得整个stateofjs项目的开发、数据收集、数据分析等工作,更加灵活、更加强大。 他们的重构将有助于分析所有那些掀起波澜的新工具的发展历程,例如 Svelte,Stencil,Nest 或 Flutter...</p> <p>无论前端社区不断向你扔出多少奇怪名字的库,跟紧stateofjs的调查,及时自检,总归不会掉队😘😆</p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/2019_javascript_report/#post-comment/</comments>
</item>
<item>
<title>信息源聚合 | 2019年度Javascript社区</title>
<link>https://www.scarsu.com/2019_javascript_sources/</link>
<guid isPermaLink="true">https://www.scarsu.com/2019_javascript_sources/</guid>
<description>根据stateOfJs2019调查中,20000余名JS开发者的数据整理而来</description>
<pubDate>Mon, 30 Dec 2019 00:00:00 GMT</pubDate>
<content:encoded><h1>2019年度Javascript社区-信息源聚合</h1> <ul> <li><strong>排名有先后,依据是<a>StateOfJs调查</a></strong></li> <li>整理了一份可以在浏览器直接导入的👉&lt;a href="/assets/js_sources_bookmark.html" download="js_sources_bookmark.html"&gt;书签文件&lt;/a&gt;</li> </ul> <h2>Blogs &amp; Magazines</h2> <ul> <li><a>CSS Tricks</a></li> <li><a>Dev.to</a></li> <li><a>JavaScript Weekly</a></li> <li><a>Smashing Magazine</a></li> <li><a>David Walsh Blog</a></li> <li><a>SitePoint</a></li> <li><a>CoDrops</a></li> <li><a>Daily JS</a></li> <li><a>Best Of JS</a></li> <li><a>Echo JS</a></li> <li><a>Medium</a></li> <li><a>Kent C. Dodds</a></li> <li><a>Twitter</a></li> <li><a>Overreacted</a></li> <li><a>Reddit</a></li> <li><a>Hacker News</a></li> <li><a>Alligator.io</a></li> <li><a>Habr</a></li> <li><a>freeCodeCamp</a></li> <li><a>2ality</a></li> <li><a>Scotch</a></li> <li><a>Node Weekly</a></li> <li><a>Hackernoon</a></li> <li><a>The Ember Times</a></li> <li><a>React Status</a></li> <li><a>Frontend Focus</a></li> <li><a>Angular In Depth</a></li> <li><a>Web.dev</a></li> <li><a>Web Development Reading List</a></li> <li><a>ESNext News</a></li> <li><a>The Changelog</a></li> <li><a>Pony Foo</a></li> <li><a>Robin Wieruch</a></li> <li><a>Wes Bos</a></li> </ul> <h2>Sites &amp; Courses</h2> <ul> <li><a>Stack Overflow</a></li> <li><a>MDN</a></li> <li><a>W3Schools</a></li> <li><a>freeCodeCamp</a></li> <li><a>Wes Bos</a></li> <li><a>Codecademy</a></li> <li><a>Level Up Tutorials</a></li> <li><a>Design+Code</a></li> <li><a>Udemy</a></li> <li><a>Egghead.io</a></li> <li><a>Frontend Masters</a></li> <li><a>YouTube</a></li> <li><a>Vue Mastery</a></li> <li><a>Platzi</a></li> <li><a>Vue School</a></li> <li><a>Laracasts</a></li> <li><a>Traversy Media</a></li> <li><a>Medium</a></li> <li><a>Udacity</a></li> <li><a>Kent C. Dodds</a></li> <li><a>Testing JavaScript</a></li> <li><a>Lynda</a></li> <li><a>Academind</a></li> <li><a>LinkedIn Learning</a></li> <li><a>Treehouse</a></li> <li><a>Scrimba</a></li> <li><a>JavaScript.info</a></li> <li><a>Tyle McGinnis</a></li> <li><a>Reddit</a></li> <li><a>Ultimate Courses</a></li> <li><a>caniuse</a></li> <li><a>Overreacted</a></li> <li><a>devdocs.io</a></li> </ul> <h2>Podcasts</h2> <ul> <li><a>Syntax</a></li> <li><a>The Changelog</a></li> <li><a>Front End Happy Hour</a></li> <li><a>JavaScript Jabber</a></li> <li><a>Full Stack Radio</a></li> <li><a>Shop Talk Show</a></li> <li><a>JS Party</a></li> <li><a>CodePen Radio</a></li> <li><a>JAMStack Radio</a></li> <li><a>Modern Web</a></li> <li><a>The Web Platform Podcast</a></li> <li><a>CodePen</a></li> <li><a>React Podcast</a></li> <li><a>Software Engineering Daily</a></li> <li><a>Ladybug Podcast</a></li> <li><a>Real Talk JavaScript</a></li> <li><a>The Undefined Podcast</a></li> <li><a>Веб-стандарты</a></li> <li><a>Elm Slack</a></li> <li><a>Soft Skills Engineering Podcast</a></li> <li><a>Frontend Weekend</a></li> <li><a>Elm Town</a></li> <li><a>The Odin Project</a></li> <li><a>Developer Tea</a></li> <li><a>Command Line Heroes</a></li> <li><a>Adventures in Angular</a></li> <li><a>Toolsday</a></li> <li><a>Coding Blocks</a></li> <li><a>Egghead.io</a></li> <li><a>Kent C. Dodds</a></li> <li><a>EmberMap</a></li> <li><a>.NET Rocks</a></li> <li><a>Views on Vue</a></li> <li><a>Reason Town</a></li> <li><a>Hipsters Ponto Tech</a></li> <li><a>DevMode.fm</a></li> <li><a>Fun Fun Function</a></li> </ul> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/2019_javascript_sources/#post-comment/</comments>
</item>
<item>
<title>ML03 | Tensor-张量简介</title>
<link>https://www.scarsu.com/fed_ml_03_tensor/</link>
<guid isPermaLink="true">https://www.scarsu.com/fed_ml_03_tensor/</guid>
<description>Javascript玩转机器学习03</description>
<pubDate>Sun, 29 Dec 2019 00:00:00 GMT</pubDate>
<content:encoded><h2>什么是Tensor</h2> <ul> <li><strong>张量</strong></li> <li>是向量和矩阵向更高维度的推广</li> <li>相当于多维数组</li> </ul> <h3>0维张量</h3> <p><img src="/images/ai/05.png" alt="0维张量" /></p> <p><img src="/images/ai/06.png" alt="rankType描述维度" /></p> <h3>1维张量</h3> <p><img src="/images/ai/07.png" alt="1维张量" /></p> <p><img src="/images/ai/08.png" alt="shape描述每个维度上数组长度" /></p> <h3>2维张量</h3> <p><img src="/images/ai/09.png" alt="每一维度数组长度均为2的2维张量" /></p> <p><img src="/images/ai/10.png" alt="size描述张量的元素数量" /></p> <h3>2 维张量</h3> <p><img src="/images/ai/11.png" alt="2维张量" /></p> <p><img src="/images/ai/12.png" alt="每一维度数组长度均为1的2维张量" /></p> <h3>3维张量</h3> <p><img src="/images/ai/13.png" alt="3维张量" /></p> <p><img src="/images/ai/14.png" alt="shape描述了三个维度的数组长度均为1" /></p> <h2>Tensor和机器学习有什么关系?</h2> <ul> <li>Tensor符合神经网络的数据结构</li> <li>神经网络每一层要存N维数据</li> <li>N层的For循环运算</li> </ul> <h2>Tensor的运算 十分符合 神经网络的运算</h2> <ul> <li>eg.用TensorFlow.js提供的<strong>点乘dotAPI</strong>能够简化复杂的for循环运算:</li> </ul> <p><img src="/images/ai/15.png" alt="传统for循环运算张量 vs dot运算张量" /></p> <p><img src="/images/ai/16.png" alt="点乘结果与for循环结果一致" /></p> <hr /> <p><a>代码仓库</a></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/fed_ml_03_tensor/#post-comment/</comments>
</item>
<item>
<title>ML02 | TensorFlow.js简介</title>
<link>https://www.scarsu.com/fed_ml_02_tensorflow/</link>
<guid isPermaLink="true">https://www.scarsu.com/fed_ml_02_tensorflow/</guid>
<description>Javascript玩转机器学习02</description>
<pubDate>Thu, 26 Dec 2019 00:00:00 GMT</pubDate>
<content:encoded><h2>TensorFlow.js是什么</h2> <ul> <li>js实现的机器学库</li> <li>可以在node.js/浏览器环境中使用机器学习技术,这意味着有更好的实时性和交互性</li> <li>著名的TensorFlow是用Python实现的</li> </ul> <h2>TensorFlow.js能干什么</h2> <ul> <li>运行现有的模型(算法工程师已经训练好的模型)</li> <li>重新训练现有模型</li> <li>使用javascript开发机器学习模型</li> </ul> <h2>demo</h2> <ul> <li><a>tfjs的各种例子</a></li> </ul> <h2>在浏览器安装tfjs</h2> <ul> <li>新建一个html,script标签引入</li> </ul> <p><code>&lt;script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.0.0/dist/tf.min.js"&gt;&lt;/script&gt;</code></p> <ul> <li>npm包安装,用import引入,用parcel/webpack构建</li> </ul> <p><code>npm i @tensorflow/tfjs</code></p> <h2>在Node.JS安装tfjs</h2> <ul> <li> <p>安装带有原生C++绑定的TensorFlow.js(推荐,底层是C++,速度快,但是安装麻烦)</p> </li> <li> <p>安装纯Javascript版本,性能较差</p> </li> <li> <p>使用require方式引用之前npm安装的<code>@tensorflow/tfjs</code>,直接用node运行当前js,一样可以在node中使用到tfjs,但是会提示:</p> </li> </ul> <pre><code>============================ Hi there. Looks like you are running TensorFlow.js in Node.js. To speed things up dramatically, install our node backend, whi ch binds to TensorFlow C++, by running npm i @tensorflow/tfjs-node, or npm i @tensorflow/tfjs-node-gpu if you have CUDA. Then call require('@tensorflow/tfjs-node'); (-gpu suffix for CUDA) at the start of your program. Visit https://github.com/tensorflow/tfjs-node for more details. ============================ </code></pre> <ul> <li> <p>因此要使用<code>npm i @tensorflow/tfjs-node</code>命令来安装后端版本tfjs,但是直接安装会报错,要先安装以下依赖:<code>npm i node-gyp windows-build-tools@4.0.0 -g</code></p> </li> <li> <p><code>node-gyp</code>是node和计算机底层交互时经常要用到的包,在windows直接安装这个包也需要一些依赖,例如安装visual studio、python,因此<code>windows-build-tools@4.0.0</code>这个包就是用来解决其依赖问题的。</p> </li> <li> <p>安装完后端版本tfjs<code>@tensorflow/tfjs-node</code>后,即可直接通过require引入使用</p> </li> </ul> <hr /> <p><a>代码仓库</a></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/fed_ml_02_tensorflow/#post-comment/</comments>
</item>
<item>
<title>ML01 | 机器学习&神经网络简介</title>
<link>https://www.scarsu.com/fed_ml_01/</link>
<guid isPermaLink="true">https://www.scarsu.com/fed_ml_01/</guid>
<description>Javascript玩转机器学习01</description>
<pubDate>Wed, 25 Dec 2019 00:00:00 GMT</pubDate>
<content:encoded><h2>大纲</h2> <ul> <li>理论知识:机器学习、神经网络、 Tensorflow. js</li> <li>经典案例:线性回归、逻辑回归、XOR、IRS、手写数字识 别、商标识别、语音识别</li> <li>神经网络模型:从单个神经元到深度神经网络</li> <li>神经网络模型算法:MSE/Log/ Cross Entropy Sigmoid/Relu/Softmax, SGD/Adam</li> <li>炼丹最佳实践:归化、欠(过)拟合、可视化、度量</li> <li>模型的迁移学习、保存、加载、转换</li> </ul> <h2>为什么要学机器学习</h2> <p>可以做一些很酷的事情,tensorflow.js官网列出了一些已经训练好的,开箱即用的<a>模型</a></p> <p>例如,<a>BodyPix</a>:实时分割人的身体和身体部位</p> <p><img src="/images/picgo/000.gif" alt="body-pix" /></p> <p><a>图像分类</a>, <a>文本恶意检测</a>, <a>语音指令识别</a>, <a>...</a></p> <h2>机器学习是什么</h2> <pre><code>数据 + 经验 -&gt; 优化算法 </code></pre> <ul> <li>对能<strong>通过经验自动改进算法</strong>的研究</li> <li>用<strong>数据</strong>或者以往的<strong>经验</strong>,来优化计算机程序的性能标准</li> </ul> <h2>机器学习例子:线性回归</h2> <ul> <li>只包括一个自变量和一个因变量,且二者的关系可用一条直线近似表示,这种回归分析称为一元线性回归分析。</li> </ul> <p><img src="/images/ai/01.png" alt="线性回归" /></p> <ul> <li>如果回归分析中包括两个或两个以上的自变量,且因变量和自变量之间是线性关系,则称为多元线性回归分析。</li> </ul> <p><img src="/images/ai/02.png" alt="多元线性回归" /></p> <h2>机器学习例子:逻辑回归</h2> <ul> <li>输入连续的(多个)值,输出0-1之间的概率,可以用于解决分类/是非判断问题</li> </ul> <p><img src="/images/ai/03.png" alt="逻辑回归" /></p> <ul> <li>例子:图片分类、语音助手</li> </ul> <p><img src="/images/ai/04.png" alt="逻辑回归:图片分类" /></p> <h2>为什么要用机器学习</h2> <ul> <li>有些问题无法用编写代码规则的方法来解决,例如图片识别。</li> <li>获取数据比编写规则更容易</li> <li>GPU等计算能力显著提升(上世纪神经网络就已发明,但是受限于计算机计算能力,得不到发展</li> </ul> <h2>机器学习如何运作</h2> <ul> <li>神经网络</li> <li>决策树、支持向量机、贝叶斯分类器、强化学习</li> </ul> <h2>什么是神经网络</h2> <ul> <li>人工神经网络</li> <li>一种运算模型(输入输出的映射)</li> <li>由大量的节点(神经元)之间相互连接构成</li> </ul> <p>&lt;!-- eg. 相亲 <img src="http://note.youdao.com/yws/res/26525/FDAB01287A58444E9C6205F65EE8A164" alt="image" /> --&gt;</p> <ul> <li>神经网路包括:一个输入层,若干隐藏层,一个输出层。</li> <li>每条线的权重可能不同</li> </ul> <h2>神经元、权重、偏置、激活函数</h2> <ul> <li>每个神经元里都存储着若干<strong>权重wight</strong>、<strong>偏置bias</strong>和一个<strong>激活函数activation</strong></li> <li>输入<strong>权重 + 偏置</strong>,经过<strong>激活函数</strong>得到<strong>输出</strong></li> <li><strong>激活函数</strong>:用于添加<strong>非线性</strong>变换</li> </ul> <h2>神经网络的训练是什么?</h2> <ul> <li>给大量输入输出,算出神经网络里所有神经元的<strong>权重、偏置</strong>,然后给定新的输入,可以算出新的输出</li> </ul> <h2>机器学习中的术语</h2> <ul> <li><strong>==特征==</strong>:输入</li> <li><strong>==标签==</strong>:输出</li> <li><strong>训练集</strong>:大量输入输出</li> </ul> <h2>如何训练</h2> <ol> <li>初始化:随便生成一些<strong>weight</strong>,<strong>bias</strong></li> <li>计算<strong>损失</strong>:给定特征,计算出标签,得到其与真实标签的差距</li> <li>优化:微调<strong>weight</strong>和<strong>bias</strong>,使损失变小</li> </ol> <h2>前向传播</h2> <ul> <li>将训练数据的<strong>特征(输入)<strong>送入网络,得到</strong>标签(输出)</strong></li> </ul> <h2>反向传播</h2> <ul> <li>计算<strong>损失</strong>并优化</li> </ul> <h2>如何计算损失</h2> <p><strong>损失函数</strong>:均方误差、对数损失、交叉熵...</p> <p>(了解损失函数原理即可,可以从第三方库调用。eg.TensorFlow.js)</p> <h2>如何优化</h2> <p><strong>优化器</strong>:随即梯度下降<strong>SGD</strong>、<strong>Adam</strong></p> <p>(了解损失函数原理即可,可以从第三方库调用。eg.TensorFlow.js)</p> <hr /> <p><a>代码仓库</a></p> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/fed_ml_01/#post-comment/</comments>
</item>
<item>
<title>被讨厌的勇气:一切的人际烦恼都可以用8个字来释怀</title>
<link>https://www.scarsu.com/life_courage/</link>
<guid isPermaLink="true">https://www.scarsu.com/life_courage/</guid>
<description>“课题分离:与我何关,与你何关”、“自由就是被人讨厌”、“一切烦恼皆来自于人际关系”</description>
<pubDate>Sat, 09 Nov 2019 00:00:00 GMT</pubDate>
<content:encoded><h2>简介</h2> <h2>我们的不幸是谁的错?</h2> <h2>一切烦恼都来自于人际关系</h2> <h2>让干涉你的人见鬼去</h2> <h2>要有被讨厌的勇气</h2> <h2>认真的人生活在“当下”</h2> <hr /> <p>有的人并不是天生的脾气暴躁,而是明白了有时候合适的时机散播怒火,才能有效的达到目的。</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/life_courage/#post-comment/</comments>
</item>
<item>
<title>ES6编程风格&最佳实践</title>
<link>https://www.scarsu.com/es6_code_style/</link>
<guid isPermaLink="true">https://www.scarsu.com/es6_code_style/</guid>
<description>遵守一定的规范和统一的风格写代码,是程序猿的基本素养😺</description>
<pubDate>Wed, 06 Nov 2019 00:00:00 GMT</pubDate>
<content:encoded><h2>块级作用域</h2> <ul> <li><code>let</code>完全取代<code>var</code></li> <li>let和const<strong>优先const</strong>: <ul> <li>函数式编程思想,运算不改变值,只是新建值</li> <li>防止了无意间修改变量值所导致的错误</li> <li>有利于将来的分布式运算</li> <li>JavaScript 编译器会对const进行优化,所以多使用const,有利于提高程序的运行效率</li> </ul> </li> </ul> <h2>字符串</h2> <ul> <li>静态一律用单引号/反引号</li> <li>动态使用反引号</li> <li><strong>不使用双引号</strong></li> </ul> <h2>解构赋值</h2> <ul> <li>从数组取值给变量时,优先用<strong>数组解构</strong></li> <li>函数参数是对象属性,优先用<strong>对象解构</strong></li> <li>函数有多个返回值时,优先用<strong>对象解构</strong></li> </ul> <h2>对象</h2> <ul> <li>单行定义的对象,最后一个成员不以逗号结尾;多行定义的对象,最后一个成员要以逗号结尾</li> <li>对象尽量静态化,一旦定义就不要随意添加属性。非要加,就用 <strong>Object.assign</strong> 方法</li> <li>对象有动态属性名:用属性名表达式 <strong>[表达式]</strong></li> <li>对象的属性和方法,尽量用<strong>简洁表达式</strong>,易于书写和描述</li> </ul> <h2>数组</h2> <ul> <li>拷贝数组:用 <strong>...</strong> 扩展运算符</li> <li>类数组对象转数组:用<strong>Array.from</strong>方法</li> </ul> <h2>函数</h2> <ul> <li>立即执行函数:用箭头函数</li> <li>匿名函数:用箭头函数</li> <li>简单的、单行的、不会复用的函数:用箭头函数</li> <li>用箭头函数取代<strong>Function.prototype.bind</strong></li> <li>不再用 <code>_this/that/self/sf</code>去绑定this</li> <li>不在函数体内用 <strong>arguments</strong>变量,用<strong>rest运算符</strong><code>...</code>代替</li> <li>用<strong>默认值语法</strong>设置函数参数</li> </ul> <h2>Map和Object</h2> <ul> <li>只有模拟现实世界的对象时,采用<code>Object</code></li> <li>只需要<code>key:value</code>数据结构时,就用<code>Map</code></li> </ul> <h2>Class和prototype</h2> <ul> <li>尽量用Class取代需要prototype的操作,更易书写和便于理解</li> <li>用<code>extends</code>实现继承,更简单,不会使instanceof运算有风险</li> </ul> <h2>Module</h2> <ul> <li>Module语法使ES的标准写法</li> <li>用import代替require</li> <li>用export代替module.exports</li> <li>如果模块只有一个输出值,就用default,否则别用</li> <li>export default和export不要混合使用</li> <li>模块输出的函数,函数名首字母应该用小写</li> </ul> <h2>使用ESLint</h2> <ul> <li>安装 ESLint</li> <li>安装 Airbnb 等语法规则,以及 import、a11y、react 等插件</li> <li>在项目的根目录下新建一个<code>.eslintrc</code>文件,配置 ESLint</li> </ul> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/es6_code_style/#post-comment/</comments>
</item>
<item>
<title>自控力:即时反馈&延迟折扣</title>
<link>https://www.scarsu.com/self_control/</link>
<guid isPermaLink="true">https://www.scarsu.com/self_control/</guid>
<description>了解意志力/欲望的生理心理精神学原理,从而更好的掌控自己</description>
<pubDate>Thu, 19 Sep 2019 00:00:00 GMT</pubDate>
<content:encoded><h2>《自控力》介绍</h2> <ul> <li>“斯坦福大学广受欢迎的心理学课程”</li> <li>总结 意志力/欲望的现象</li> <li>分析 意志力/欲望的 生理 心理 精神学原理</li> <li>找出 提升自控力/控制欲望 的对策</li> </ul> <h4>思维导图</h4> <p><img src="/images/self_control.png" alt="《自控力思维导图》" /></p> <h2>意志力的本质</h2> <ol> <li><code>我要</code>的力量:行动</li> <li><code>我不要</code>的力量:抵制</li> <li><code>我想要</code>的力量:目标</li> </ol> <h2>意志力的生理特征</h2> <ul> <li>意志力像<code>肌肉</code>一样有限制。</li> <li>意志力被消耗,会导致失控。</li> <li>意志力从早到晚,逐渐减弱——把需要意志力的事情放在<code>早上</code>(意志力最强的时候)做。</li> <li>饥饿/疲惫/紧张会影响意志力。</li> <li>意志力可以训练:在一些小事上持续自控会提升整体的意志力</li> </ul> <h2>增强意志力的生理方法</h2> <ul> <li><code>运动</code>:坚持运动,能提升意志力</li> <li><code>睡眠</code>:睡眠是对能量的恢复,早上的意志力最强</li> <li><code>放松</code>:压力会消耗意志力</li> <li><code>呼吸等待</code>:做失控决定前深呼吸,告诉自己等待几分钟再去做</li> <li><code>训练</code>:通过持续性的小事自控来训练意志力</li> <li><code>动力</code>:找出“我想要”的动力,让它环绕在你的生活的角角落落</li> </ul> <h2>引起“失控”的几种心理</h2> <ul> <li><code>自我感觉良好</code>会让自己更易纵容。</li> <li><code>把进步当作放纵的接口</code>:前进一小步,后退两大步</li> <li><code>透支成就感</code>:向未来赊账</li> </ul> <h2>多巴胺 &amp; 欲望vs幸福</h2> <h4>多巴胺:让人产生欲望,而不是快乐</h4> <ul> <li>人脑的多巴胺系统,与快感中心不是同一个部分。</li> <li>多巴胺系统刺激人原始动力系统的一部分。</li> <li>使人产生欲望,预见快感,追逐欲望,而不是真正使人快乐。</li> <li>过量的多巴胺:上瘾</li> </ul> <h4>欲望 != 幸福</h4> <ul> <li>没有欲望不幸福,欲望过多使人失控。</li> <li>好欲望-》产生动力-》促进意志力</li> <li>坏欲望-》屈服于诱惑-》失控</li> <li>所以要合理利用欲望,分清“欲望”和“幸福”</li> </ul> <h4>多巴胺系统的特点</h4> <ul> <li>对新鲜事物/未知奖励敏感</li> <li>对多样性敏感</li> </ul> <h4>多巴胺对策</h4> <ul> <li>“多巴胺化”:把不喜欢的东西 和 能促进多巴胺的事联系起来。</li> <li>“鱼缸奖励法”:完成目标时,抽取未知的不同的奖励,而不是小儿稳定的奖励。</li> </ul> <h2>压力带来的“失控负循环”</h2> <p><img src="/images/stress_circle.png" alt="压力带来的“失控负循环”" /></p> <h4>打破循环的方法</h4> <ul> <li>及时止损,不要破罐子破摔</li> <li>“自我谅解”,而不是加深自责加深压力促进循环</li> <li>“行动”而不是“发誓改变”,不要满足于指定计划,这种满足感来源于“对想象中未来成就感的透支”</li> <li>用有效的方式解压↓</li> </ul> <h4>有效的解压方式</h4> <ul> <li>运动</li> <li>培养爱好</li> <li>社交</li> <li>音乐</li> <li>阅读</li> <li>牢牢记住以上方式解压后愉悦的心情</li> </ul> <h2>现代 vs 未来</h2> <h4><code>即时反馈</code>&amp;<code>延迟折扣</code></h4> <ul> <li><code>多巴胺系统</code>使人乐于追求即时反馈</li> <li>眼前的“小奖励” 比 “未来的大奖励” 更有诱惑力</li> <li>延迟折扣:需要等待时间越久的奖励,诱惑力越低</li> </ul> <h4>抵制即时反馈</h4> <ul> <li>拉开与诱惑的距离:时间 &amp; 空间</li> <li>“10分钟法则”:决定放纵前,先等待10分钟(利用延迟折扣,诱惑力会降低</li> <li>放大未来的奖励,降低折扣率,让想要的未来离自己更近,例如把偶像/目标贴在经常能看到的地方</li> </ul> <h4>缩小“现在的自己” 与“未来的自己”的差距</h4> <ul> <li>不要高看未来的自己</li> <li>不要一切都拖到未来去做</li> </ul> <h2>意志力会传染</h2> <ul> <li>人生来就具有社会性:不可能脱离社会生存,要与他人产生联系</li> </ul> <h4><code>社会认同感</code></h4> <ul> <li>“自豪”,“惭愧”等社会性情绪,会促进人的自控</li> <li>让自己相信“大多数人都自控”,“自控是个社会规范”,更有利于自控</li> </ul> <h4><code>镜像神经元</code>的行为:</h4> <ul> <li>无意识的模仿他人</li> <li>情绪传染</li> <li>自控力传染</li> </ul> <h4>对策</h4> <ul> <li>增强免疫力</li> <li>坚定自我</li> <li>远离不自控人群</li> </ul> <h2>讽刺性反弹</h2> <h4>“我不要”的神经学原理</h4> <ol> <li>大脑的“操作系统”:消耗能力去自控(耗能高)</li> <li>大脑的“监控系统”:充满了“不要xxx”的警告 (自动机制,耗能很低)</li> </ol> <ul> <li>当人的精力不足时,1、2失去平衡,不断的执行2,不断的想起不能做的事情,却没有足够的能量去执行1去抵制,就会导致失控</li> </ul> <h4>讽刺性反弹的结果</h4> <ul> <li>“我不要”的力量,有时候会产生相反的效果</li> <li>通过“抑制想法”来抵抗诱惑,可能会适得其反</li> <li>越压抑人的本能,越容易适得其反</li> </ul> <h4>对策</h4> <ul> <li>了解认知偏见:认知偏见:想起xx的次数多,容易让人对xx的真实性产生误判。要知道自己不断想起的事情不一定是真的,不一定是对的</li> <li>放弃控制内心的感受,坦率的面对与接受,关注自己的想法与感受,去理解分析,判断真实性的对错</li> <li><code>直面自身的欲望,但不去行动</code>:对内接受自我,对外控制行为</li> <li>把“我不要”转为“我想要”效果更好。</li> </ul> <p>&lt;small&gt;注:书中列出的观点,大多数都有实验数据支撑,都是很有趣的实验,建议亲自阅读&lt;/small&gt;</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/self_control/#post-comment/</comments>
</item>
<item>
<title>刻意学习:如何更高效的成长</title>
<link>https://www.scarsu.com/continuous_action/</link>
<guid isPermaLink="true">https://www.scarsu.com/continuous_action/</guid>
<description>提升执行力 | 持续精进 | 轻松成为更好的自己</description>
<pubDate>Mon, 19 Aug 2019 00:00:00 GMT</pubDate>
<content:encoded><h2>书的主旨 : 持续行动 + 持续学习</h2> <h2>为什么要持续行动</h2> <h4>为了成长</h4> <ul> <li>生而为成长,在这个变化万千的时代,不进则退。</li> </ul> <h4>跳出困境,重构现在与未来</h4> <ul> <li>现状有多痛苦,过往有多不堪,持续行动就该有多深。</li> <li>“悟已往之不谏,知来者之可追”,我们的原生家庭、出身条件、容貌身体发肤、以及过去的种种,都是不可变的默认参数,只能靠当下的行动,去改变未来的轨迹。</li> </ul> <h2>正确的自我认知</h2> <h4>拒绝自我感动</h4> <ul> <li>正是因为做得少,才容易“感动”,自欺欺人。</li> <li>提前透支快感:为自己定下宏大的目标,并为之沾沾自喜,提前透支着目标达成的快感,真正要开始做事便耐不住寂寞开始放弃</li> </ul> <h4>拒绝“强及时反馈”</h4> <ul> <li>我们与外界互动,通常渴望强及时反馈,得不到变容易焦虑、急躁。</li> <li>强及时反馈对复杂系统是不起作用的:</li> </ul> <table> <thead> <tr> <th>复杂系统</th> <th>行为</th> <th>强及时反馈</th> </tr> </thead> <tbody> <tr> <td>人的身体系统</td> <td>跑一次步</td> <td>变瘦变健康</td> </tr> <tr> <td>大海</td> <td>撒一泡尿</td> <td>变脏</td> </tr> </tbody> </table> <h4>不要过度依赖技巧</h4> <ul> <li>投机取巧是追求强即时反馈的表现</li> <li>过度追逐技巧的人,往往缺乏行动量</li> <li>能用思路解决的问题,尽量不用技巧。从全局的层面看问题,理清逻辑思路,而不是抓住某个细节投机取巧</li> </ul> <h4>不要标榜/贴标签,去行动</h4> <ul> <li>通过标榜自己是谁,给自己贴标签,并且能马上得到本来要经过努力做成事才嗯那个得到的反馈,就不会再踏实的做事了。</li> <li>通过“宣称”自己写作、在GRE、在奋斗,快速透支大量快感,往往时不会他是做事的。</li> </ul> <h4>不要自我迷恋,高估自己</h4> <ul> <li>不要做事无巨细的完美主义者:等到把所有的因素都准备完美再开工。不如先把一部分事情做起来。</li> <li>制定计划时,总是雄心勃勃,透支着未来的成就感,高估自己的能力,往往开始正真做事的时候,更容易放弃。</li> </ul> <h4>放大格局</h4> <ul> <li>人是一种容易短视的动物,因为我们的圈子往往比整个世界小的太多太多微乎其微,这种短视会带来认知偏差,让我们做出错误的判断</li> <li>时不时跳出自己的圈子,主动接触外界信息,不要过度相信自己的认知,是提升格局的关键</li> </ul> <h2>成长系统</h2> <p><img src="/images/continuous_action.png" alt="" /></p> <h2>如何行动</h2> <h4>松散到紧凑</h4> <ul> <li>建立合理的作息</li> <li>坚定的坚持下去</li> </ul> <h4>耐得住寂寞:没有成就感也要行动</h4> <ul> <li>持续行动的要义就在于持续,不要以任何理由打破自己定下的原则</li> <li>不依靠透支未来的成就感,作为坚持下去的动力</li> </ul> <h4>​克服拖延</h4> <ul> <li>五分钟内能做完的事,现在立即做。五分钟做不完的,现在开始做一部分。</li> </ul> <h4>放大对未来的感知</h4> <ul> <li>提前完成任务,而不是到deadline</li> <li>不要高度自己的能力,低估自己完成任务所需的时间</li> <li>时刻警醒自己,让自己感知着未来不完成任务带来的后果</li> </ul> <h4>早起是拓宽增量</h4> <ul> <li>更高效的利用时间,有两个途径。一是“存量优化”,在现有的作息时间中,更高效的利用时间。二是“拓宽增量”,也就是增加可支配的时间。</li> <li>对于大多数人来说,“存量优化”是很难的,也是有瓶颈的,因此“拓宽增量”是更好的选择。</li> <li>“拓宽增量”意味着压缩睡眠时间,起的更早显然比睡的更晚对身体更有利,并且清晨的时光,更以利用。</li> </ul> <h4>投资资源(时间+金钱)</h4> <ul> <li>首先,投资自己是一种收益最高的投入,不能因为惜钱,而去绕弯路,去用时间换钱</li> <li>其次,投资自己不光意味花钱,花钱只是获得了更好的资源,真正的成长,需要你投入时间去持续行动</li> </ul> <h4>信息分级,对海量信息抗压</h4> <ul> <li>面对海量的信息,不因噎废食,直接切断所有的信息源</li> <li>不自我焦虑,培养抗压能力,克服“永远刷不完的小红点”带来的焦虑不安</li> <li>形成对信息分级的系统,主动的对信息分级,知道自己想要什么</li> </ul> <h2>关于n阶行动计划</h2> <table> <thead> <tr> <th>阶数</th> <th>时长</th> <th>特点</th> </tr> </thead> <tbody> <tr> <td>一</td> <td>10^1 = 10天,一个周</td> <td>瓶颈在于执行力,行动系统有问题</td> </tr> <tr> <td>二</td> <td>10^2 = 100天,三个月</td> <td>瓶颈在于学习系统和格局,有一定执行力,但是需要完善学习系统,升华格局</td> </tr> <tr> <td>三</td> <td>10^3 = 1000天,三年</td> <td>时间足够长,能够见到真正的对复杂系统的改变,形成了思维惯性和依赖路径,瓶颈在于创新、重构、与时俱进</td> </tr> <tr> <td>...</td> <td>...</td> <td>...</td> </tr> </tbody> </table> <h2>关于1000天持续行动计划</h2> <h4>开局阶段:0-300天</h4> <ul> <li>认清自我,了解现状,认清现实,找出“我能做的”和“我想做的”之间的差距</li> <li>仅能完成任务,倒逼自己</li> </ul> <h4>中盘持续阶段:200-600天</h4> <ul> <li>补足不全,缩短“我能做的”和“我想做的”之间的差距</li> <li>能每天完成任务,并在其基础上有所进步</li> </ul> <h4>突破创新阶段:600-1000天</h4> <ul> <li>突破现有的固定模式,打破思维惯性</li> <li>根据环境的改变,做出新的规划,升华行动</li> </ul> <p>&lt;small&gt;希望你看完,能做点什么&lt;/small&gt;</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/continuous_action/#post-comment/</comments>
</item>
<item>
<title>断舍离:物品的价值在于使用而不在于拥有</title>
<link>https://www.scarsu.com/danshari/</link>
<guid isPermaLink="true">https://www.scarsu.com/danshari/</guid>
<description>在极简极致的生活中了解自我,认识自我,找到自己真正想做的事情。</description>
<pubDate>Mon, 05 Aug 2019 00:00:00 GMT</pubDate>
<content:encoded><h2>断舍离是什么</h2> <p>断舍离是一种,通过收拾物品来了解自己,整理自己,让人生更舒适的方法</p> <h2>‌如何做到断舍离</h2> <ul> <li>断(行为):断绝要进入自己家里/生活里/脑海里的 不需要的东西</li> <li>舍(行为):舍弃自己的世界里既有的破烂(clutter)</li> <li>离(状态):脱离对物品的执念,使自己处于游刃有余的自在空间</li> </ul> <h2>‌用湖泊比喻生活</h2> <ul> <li>断:对上游留下来的东西进行筛选,对生活入口有把控/筛选能力</li> <li>舍:让不需要的东西流出</li> </ul> <p>这样才能让生活保持新鲜,清静。</p> <h2>‌断舍离的灵魂一问</h2> <p><code>自己</code> <code>当下</code> 是否需要?</p> <ul> <li>断舍离的主角:自己</li> <li>断舍离的时间轴:当下</li> </ul> <h2>‌断舍离vs收纳</h2> <p>断舍离是对进入/留存在自己世界中的物品进行筛选(先)</p> <p>收纳是对已有物品的整理(后)</p> <p>通过先达到断舍离的状态,让自己的生活从加法走向减法,让自己陷于收纳整理的时间更少,让生活更轻松自在</p> <h2>‌为什么我们的生活里满是杂物</h2> <ul> <li>捡便宜,通过消费满足物欲,这也新奇,那也想买,买来新鲜感一过就闲置(物欲泛滥,对物品有执念)</li> <li>执念于过去,念旧,舍不得(时间轴错位)</li> <li>囤积癖,对未来过度忧虑,“万一以后会用到”,但实际概率很小(时间轴错位)</li> <li>不想收拾不想改变(懒)</li> </ul> <h2>‌断舍离是令人愉悦的</h2> <p>通过断舍物品,完成自我发现,自我肯定的过程</p> <h2>物品的真正价值</h2> <p>任何物品都需要被使用,这才是它本身价值的体现。我们需要的东西其实并没有那么多,而留在身边的应该是<code>最少量最好用</code>的。</p> <h2>‌“拥有物品”是个伪命题</h2> <p>人的生命是有限的,一切有形的东西都是虚幻的,人心也是不断变化的。</p> <p>物品只应该是我们追求人生幸福感的工具,而不是一种拥有/维护/收纳/处理的累赘。</p> <p>因此“物品被使用的时候才是发挥价值的时候”,物品当下应该在需要他的地方,而不应该是闲置。</p> <h2>七、五、一总量限制原则</h2> <p><code>七</code>:柜子等<code>看不见的</code>收纳物品装备只能放满七成,空出来的三成空间成为物品出入的通道,这样会让人有收拾整齐的欲望和心情。</p> <p><code>五</code>:<code>看得见的收纳</code>只放五成,主要作用于看得见的位置,比如置物架,茶几等等,比如商场高级的商品,摆放位置较零散。</p> <p><code>一</code>:通常用于装饰墙之类的,例如美术馆的画展,名画都单独挂在一面墙,显示了这幅画的重要性,营造了高端的感觉。</p> <p><code>总量限制替换原则</code>:当收纳超出<code>七五一原则</code>时,就需要考虑限制总量不变,替换现有的物品或者限制新入的物品</p> <h2>‌单一动作原则</h2> <p>收纳,要让(经常使用的)物品依赖尽量少的动作就能拿出来</p> <h2>‌自立原则</h2> <p>收纳尽量避免堆叠,立体放置可以让下面的/里面的物品更便于取出</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/danshari/#post-comment/</comments>
</item>
<item>
<title>如何与情绪相处</title>
<link>https://www.scarsu.com/emotions/</link>
<guid isPermaLink="true">https://www.scarsu.com/emotions/</guid>
<description>接受、正视、了解我们的感觉和情绪</description>
<pubDate>Tue, 09 Jul 2019 00:00:00 GMT</pubDate>
<content:encoded><p>从人性上来说,我们倾向于保护自我最脆弱的部分</p> <p>伤痛、需求未被满足、罪恶、耻辱会激发我们痛苦、恐惧、愤怒的情绪,这是人类天生的保护机制</p> <p>我们无法控制自己的本能,但是应该学会接受、正视、了解我们的感觉和情绪,</p> <p>去发现并解决 情绪背后 激发情绪的问题,而不是去任由情绪发泄</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/emotions/#post-comment/</comments>
</item>
<item>
<title>如何追求快乐</title>
<link>https://www.scarsu.com/how_to_be_happy/</link>
<guid isPermaLink="true">https://www.scarsu.com/how_to_be_happy/</guid>
<description>短篇</description>
<pubDate>Tue, 09 Jul 2019 00:00:00 GMT</pubDate>
<content:encoded><blockquote> <p>有很多快乐是放纵的快乐,是降低了人性尊严的快乐,而越能体现人性尊严的快乐,越是一种高级的快乐。</p> <p>追求高级的快乐并不意味着放弃低级的快乐,但是如果你的眼目永远只关注地下,你永远不知道向上看有多么的快乐。</p> </blockquote> <p>——罗翔</p> <p><a>@https://www.bilibili.com/video/BV1AE411T7p7</a></p> <blockquote> <p>I don't need dollar bills to have fun</p> </blockquote> <p>——【Cheap Thrills】 Sia</p> <p>降低欲望、培养兴趣</p> <p>享受平静才是生活的真谛</p> <blockquote> <p>“上次我去一个朋友家玩,看到他们客厅里摆着一张很长的桌子。朋友说,每到周末,两个大人,一个孩子,还有两只猫都会围在这个桌子旁,家里很安静,只有书页翻动和画笔接触纸张的细微声音。”</p> </blockquote> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/how_to_be_happy/#post-comment/</comments>
</item>
<item>
<title>为什么要趁年轻多学习</title>
<link>https://www.scarsu.com/keep_proper_pressure/</link>
<guid isPermaLink="true">https://www.scarsu.com/keep_proper_pressure/</guid>
<description>爆炸性压力才能带来爆炸性进步</description>
<pubDate>Tue, 09 Jul 2019 00:00:00 GMT</pubDate>
<content:encoded><p><a>原文</a></p> <blockquote> <p><strong>爆炸性压力才能带来爆炸性进步</strong></p> <p>每次我状态低迷的时候,我都会看看这个视频,视频18分钟,如果你懒得看,我简述一下:</p> <p>演讲者是许峰源先生,他出身一个非常贫穷的家庭,整个家庭,靠的是父亲踩着三轮车出去卖豆腐微薄的收入支撑着。</p> <p>这不是一个烂仔逆袭的故事,因为从小看到了生活艰苦的一面,许峰源一直很努力想考上台大法律系,因为成为律师才有高收入,才能改变家庭的现状。</p> <p>不幸的是,在他上大学的时候,父亲却查出了舌癌晚期,只剩一年左右的时间,为了让父亲在临终前看到自己的孩子成才,许峰源用了极短的时间通过了司法考试,成为了一名律师,让父亲看到了自己的律师证,才安然去世。</p> <p>祸不单行,很快许峰源的母亲也查出了患有肺腺癌,一种扩散很迅猛的癌症,为了让母亲有一个安享晚年的环境,许峰源在23岁的时候,毅然辞职创业,白天在律师事务所打拼,晚上做培训,最终让母亲住上了好房子,接受更好的治疗,然后平静地送走了母亲。</p> <p>前半生,许峰源先生为之奋斗的两个对象都走了,迷茫了一阵子之后,他依然没有放弃努力,而是选择了实现自我,成为了一名作家。</p> <p>再烂的牌也得打下去,这就是人生</p> </blockquote> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/keep_proper_pressure/#post-comment/</comments>
</item>
<item>
<title>别让任何人打乱你的人生节奏</title>
<link>https://www.scarsu.com/value_yourself/</link>
<guid isPermaLink="true">https://www.scarsu.com/value_yourself/</guid>
<description>短篇</description>
<pubDate>Tue, 09 Jul 2019 00:00:00 GMT</pubDate>
<content:encoded><h2>每个人的人生都不同</h2> <blockquote> <p>"Not everything that counts can be counted,and not everything that's counted truly counts"</p> <p>"并不是每件算出来的事,都有意义;也不是每件有意义的事,都能被算出来" ——爱因斯坦</p> </blockquote> <p><a>@https://www.bilibili.com/video/BV1WW411F7Hx</a></p> <h2>建立自己的价值体系</h2> <p>世人觉得瘦才是美,你就要以健康为代价过度减肥; 世人觉得大眼睛双眼皮才是美,你就要花钱在脸上动刀; 世人觉得肤白才是美,你无法改变就去否定自己; 世人觉得出身决定地位,你就要否定自己和父母;</p> <p>不要再活在别人的价值体系下,</p> <p>不要再被这个世界灌输好与坏,</p> <p>自己亲身去感受、去体验、去思考,</p> <p>什么是真的好与坏</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/value_yourself/#post-comment/</comments>
</item>
<item>
<title>就是不想努力怎么办</title>
<link>https://www.scarsu.com/why_make_efforts/</link>
<guid isPermaLink="true">https://www.scarsu.com/why_make_efforts/</guid>
<description>短篇</description>
<pubDate>Tue, 09 Jul 2019 00:00:00 GMT</pubDate>
<content:encoded><blockquote> <p>我就想做一个安于现状的人</p> <p>就想利用上班赚钱过好自己的小日子</p> <p>就想平凡的过完一生</p> <p>我就是不想拼命奋斗,拼命努力,拼命内卷</p> <p>不可以吗?</p> </blockquote> <p>当然可以,每个人的追求不同,淡泊名利,平静一生,真正能做到的话,是一种很高的人生境界。</p> <p>但是你做出这种决定,就要考虑其带来的结果</p> <blockquote> <p>你能做到真正的“淡泊名利”吗?</p> <p>当别人用光鲜亮丽的服装、车子、房子包装和提升自己的生活品质时,你能做到不羡慕吗</p> <p>当别人在马尔代夫浮潜、在阿尔卑斯滑雪、在土耳其滑翔、在富士山脚泡温泉喝清酒,你能做到不羡慕吗</p> <p>你身边的人生活品质都比你高得时候,你会不会后悔</p> <p>你的普通收入扣除房子首付、房贷、车子、奶粉钱之后你还足够安稳吗</p> <p>如果不买房,你可以做到一生租房,并容忍一生到老不断的搬家吗</p> <p>你的普通收入能让你匹配上你心仪的另一半吗</p> <p>你的现状能维持你一生的稳定平凡吗?你能对抗人生所有的风险吗</p> <p>你可以为自己的一生、父母后半生、孩子前半生的大大小小的健康问题买单吗</p> <p>如果你有了孩子,你作为爸爸/妈妈,能给孩子最好的教育吗</p> </blockquote> <p>如果你深刻的考虑了这些问题,都能得到坚定的答案,那么安于现状,不拼命努力,也没什么不好</p> <p>每个人的人生都不同,人生的路也没有对错之分,只是路上的酸甜苦辣,你需要独自承担</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/why_make_efforts/#post-comment/</comments>
</item>
<item>
<title>JavaScript开发者应懂的33个概念</title>
<link>https://www.scarsu.com/33_js_concepts/</link>
<guid isPermaLink="true">https://www.scarsu.com/33_js_concepts/</guid>
<description>知识点复盘手册</description>
<pubDate>Mon, 01 Jul 2019 00:00:00 GMT</pubDate>
<content:encoded><h2>简介</h2> <p><a>原文链接</a></p> <blockquote> <p>本篇文章是参照 @leonardomso 创立,英文版项目地址在<a>这里</a>。</p> </blockquote> <hr /> <h2>目录</h2> <ol> <li><strong><a>调用堆栈</a></strong></li> <li><strong><a>原始类型</a></strong></li> <li><strong><a>值类型和引用类型</a></strong></li> <li><strong><a>隐式, 显式, 名义和鸭子类型</a></strong></li> <li><strong><a>== 与 ===, typeof 与 instanceof</a></strong></li> <li><strong><a>this, call, apply 和 bind</a></strong></li> <li><strong><a>函数作用域, 块级作用域和词法作用域</a></strong></li> <li><strong><a>闭包</a></strong></li> <li><strong><a>map, reduce, filter 等高阶函数</a></strong></li> <li><strong><a>表达式和语句</a></strong></li> <li><strong><a>变量提升</a></strong></li> <li><strong><a>Promise</a></strong></li> <li><strong><a>立即执行函数, 模块化, 命名空间</a></strong></li> <li><strong><a>递归</a></strong></li> <li><strong><a>算法</a></strong></li> <li><strong><a>数据结构</a></strong></li> <li><strong><a>消息队列和事件循环</a></strong></li> <li><strong><a>setTimeout, setInterval 和 requestAnimationFrame</a></strong></li> <li><strong><a>继承, 多态和代码复用</a></strong></li> <li><strong><a>按位操作符, 类数组对象和类型化数组</a></strong></li> <li><strong><a>DOM 树和渲染过程</a></strong></li> <li><strong><a>new 与构造函数, instanceof 与实例</a></strong></li> <li><strong><a>原型继承与原型链</a></strong></li> <li><strong><a>Object.create 和 Object.assign</a></strong></li> <li><strong><a>工厂函数和类</a></strong></li> <li><strong><a>设计模式</a></strong></li> <li><strong><a>Memoization</a></strong></li> <li><strong><a>纯函数, 函数副作用和状态变化</a></strong></li> <li><strong><a>耗性能操作和时间复杂度</a></strong></li> <li><strong><a>JavaScript 引擎</a></strong></li> <li><strong><a>二进制, 十进制, 十六进制, 科学记数法</a></strong></li> <li><strong><a>偏函数, 柯里化, Compose 和 Pipe</a></strong></li> <li><strong><a>代码整洁之道</a></strong></li> </ol> <hr /> <h2>1. 调用堆栈</h2> <h3>文章</h3> <ul> <li>:book: <a>Call Stack — MDN</a></li> <li>:book: <a>[译] JavaScript 如何工作:对引擎、运行时、调用堆栈的概述 —— 掘金</a></li> <li>:book: <a>[译] 理解 JavaScript 中的执行上下文和执行栈 —— 掘金</a></li> <li>:book: <a>这一次,彻底弄懂 JavaScript 执行机制 —— 掘金</a></li> <li>:book: <a>解读 JavaScript 之引擎、运行时和堆栈调用 —— 开源中国</a></li> <li>:book: <a>Tasks, microtasks, queues and schedules —— Jake Archibald</a></li> <li>:book: <a>Tasks, microtasks, queues and schedules(译) —— 掘金</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>What is the event loop anyway? —— 腾讯视频(英文字幕)</a></li> <li>:tv: <a>Understanding The JavaScript Call Stack, Event Queue, Event Table, &amp; Event Loop —— Bilibili</a></li> <li>:tv: <a>JS 中的变量提升、堆栈内存及闭包详解 —— Acfun</a></li> <li>:tv: <a>事件循环模型 —— PHP 中文网</a></li> <li>:tv: <a>Javascript: the Call Stack explained — Coding Blocks India</a></li> <li>:tv: <a>The JS Call Stack Explained In 9 Minutes — Colt Steele</a></li> <li>:tv: <a>JavaScript Execution Stack — Codecademy</a></li> <li>:tv: <a>What is the Call Stack? — Eric Traub</a></li> <li>:tv: <a>The Call Stack — Kevin Drumm</a></li> <li>:tv: <a>Understanding JavaScript Execution — Codesmith</a></li> <li>:tv: <a>Call Stack &amp; Event Loop — movies com</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>2. 原始类型</h2> <h3>文章</h3> <ul> <li>:book: <a>原始数据 —— MDN</a></li> <li>:book: <a>[译]JavaScript 是怎样编码数字的 —— SegmentFault</a></li> <li>:book: <a>每一个 JavaScript 开发者应该了解的浮点知识 —— 颜海镜</a></li> <li>:book: <a>JavaScript 标准参考教程(基本语法之数值) —— 阮一峰</a></li> <li>:book: <a>The Secret Life of JavaScript Primitives —— Angus Croll</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>javascript 六种数据类型 —— 慕课网</a></li> <li>:tv: <a>javascript 视频教程(数据类型) —— PHP 中文网</a></li> <li>:tv: <a>JavaScript Reference vs Primitive Types — Academind</a></li> <li>:tv: <a>JavaScript Primitive Types — Simon Sez IT</a></li> <li>:tv: <a>Javascript Primitive and Reference Types — Baljeet Singh</a></li> <li>:tv: <a>Value Types and Reference Types in JavaScript — Programming with Mosh</a></li> <li>:tv: <a>JavaScript Primitive Data Types — Avelx</a></li> <li>:tv: <a>Everything you never wanted to know about JavaScript numbers — Bartek Szopka</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>3. 值类型和引用类型</h2> <h3>文章</h3> <ul> <li>:book: <a>ECMAScript 引用类型 —— W3school</a></li> <li>:book: <a>js 中的值类型和引用类型的区别 —— 博客园</a></li> <li>:book: <a>JavaScript 的值传递和引用传递 —— FunDebug</a></li> <li>:book: <a>Primitive Types &amp; Reference Types in JavaScript —— Bran van der Meer</a></li> <li>:book: <a>JavaScript: Passing by Value or by Reference —— CSDN</a></li> <li>:book: <a>js 值引用和值复制 —— SegmentFault</a></li> <li>:book: <a>js- 引用和复制(传值和传址) —— CSDN</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>Javascript Pass by Value vs Pass by Reference — techsith</a></li> <li>:tv: <a>JavaScript Value vs Reference Types — Programming with Mosh</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>4. 隐式, 显式, 名义和鸭子类型</h2> <h3>文章</h3> <ul> <li>:book: <a>ECMAScript 类型转换 —— W3school</a></li> <li>:book: <a>JavaScript 的怪癖 1:隐式类型转换 —— justjavac</a></li> <li>:book: <a>JavaScript 运算符规则与隐式类型转换详解 —— 掘金</a></li> <li>:book: <a>聊一聊 JS 中的隐式类型转换 —— SegmentFault</a></li> <li>:book: <a>有趣的 JavaScript 隐式类型转换 —— 博客园</a></li> <li>:book: <a>JavaScript 显式类型转换与隐式类型转换 —— CSDN</a></li> <li>:book: <a>你不知道的 JavaScript(中卷)强制类型转换 —— 简书</a></li> <li>:book: <a>你懂 JavaScript 嗎?#8 強制轉型 —— cythilya</a></li> <li>:book: <a>动态类型语言和鸭子类型 —— 曾探</a></li> <li>:book: <a>Nominal &amp; Structural Typing —— flow</a></li> <li>:book: <a>What exactly is Type Coercion in Javascript? —— stackoverflow</a></li> <li>:book: <a>You Don't Know JS: Types &amp; Grammar —— github</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>javascript 隐式转换 —— 慕课网</a></li> <li>:tv: <a>Javascript 基础加强-类型转换 —— 黑马程序员</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <p>&lt;div id="5--vs--typeof-vs-instanceof"&gt;&lt;/div&gt;</p> <h2>5. == vs ===, typeof vs instanceof</h2> <h3>文章</h3> <ul> <li>:book: <a>JavaScript 中的相等性判断 —— MDN</a></li> <li>:book: <a>js 中 == 和 === 的区别 —— 掘金</a></li> <li>:book: <a>== vs === in Javascript —— CSDN</a></li> <li>:book: <a>深入理解 javascript 之 typeof 和 instanceof —— CSDN</a></li> <li>:book: <a>JavaScript 的 typeof 的用途 —— justjavac</a></li> <li>:book: <a>一张图看懂 Function 和 Object 的关系及简述 instanceof 运算符 —— 掘金</a></li> <li>:book: <a>浅谈 instanceof 和 typeof 的实现原理 —— 掘金</a></li> <li>:book: <a>typeof 和 instanceOf 的区别</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>6. this, call, apply 和 bind</h2> <h3>文章</h3> <ul> <li>:book: <a>Javascript 的 this 用法 —— 阮一峰</a></li> <li>:book: <a>学会 JS 的 this 这一篇就够了,根本不用记 —— 简书</a></li> <li>:book: <a>[译] this(他喵的)到底是什么 — 理解 JavaScript 中的 this、call、apply 和 bind —— 掘金</a></li> <li>:book: <a>this、apply、call、bind —— 掘金</a></li> <li>:book: <a>使用 call、apply 和 bind 解决 js 中烦人的 this,事件绑定时的 this 和传参问题 —— 博客园</a></li> <li>:book: <a>call、apply 和 bind 的原生实现 —— github</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>JavaScript 关于 this 关键字解释 —— 爱奇艺</a></li> <li>:tv: <a>JS 关于作用域闭包和 this 的综合面试题 —— 百度视频</a></li> <li>:tv: <a>js 面向对象闭包数组 12.函数中的 this —— 乐视视频</a></li> <li>:tv: <a>1.3.10-this 指向及 this 应用 —— 乐视视频</a></li> <li>:tv: <a>珠峰培训 JavaScript 开发课程:关于 this 关键字、闭包作用域 —— 网易云课堂</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>7. 函数作用域, 块级作用域和词法作用域</h2> <h3>文章</h3> <ul> <li>:book: <a>变量作用域与解构赋值 —— 廖雪峰</a></li> <li>:book: <a>学习 Javascript 闭包(Closure) —— 阮一峰</a></li> <li>:book: <a>JavaScript 中词法作用域、闭包与跳出闭包 —— SegmentFault</a></li> <li>:book: <a>JavaScript 深入之词法作用域和动态作用域 —— 掘金</a></li> <li>:book: <a>深入理解闭包之前置知识 → 作用域与词法作用域 —— 掘金</a></li> <li>:book: <a>What is lexical scope? —— stackoverflow</a></li> <li>:book: <a>You Don't Know JS: Scope &amp; Closures —— Kyle Simpson</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>8. 闭包</h2> <h3>文章</h3> <ul> <li>:book: <a>闭包 —— MDN</a></li> <li>:book: <a>ECMAScript 闭包(closure)—— w3school</a></li> <li>:book: <a>学习 Javascript 闭包(Closure) —— 阮一峰</a></li> <li>:book: <a>闭包 —— 廖雪峰</a></li> <li>:book: <a>一次性搞懂 JavaScript 闭包 —— 简书</a></li> <li>:book: <a>JavaScript 闭包 —— SegmentFault</a></li> <li>:book: <a>js 匿名自执行函数中闭包的高级使用 —— 掘金</a></li> <li>:book: <a>高效使用 JavaScript 闭包 —— 掘金</a></li> <li>:book: <a>深入理解 JavaScript 原型与闭包 —— 王福朋</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>JavaScript 闭包和闭包面试题 —— 爱奇艺</a></li> <li>:tv: <a>js 面向对象闭包数组 11.闭包 —— 乐视</a></li> <li>:tv: <a>白贺翔_函数(闭包) —— 乐视</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>9. map, reduce, filter 等高阶函数</h2> <h3>文章</h3> <ul> <li>:book: <a>高阶函数 —— 廖雪峰</a></li> <li>:book: <a>ES5 中新增的 Array 方法详细说明 —— 张鑫旭</a></li> <li>:book: <a>一张图看懂 JavaScript 中数组的迭代方法:forEach、map、filter、reduce、every、some —— 掘金</a></li> <li>:book: <a>Transducing(上)-《JavaScript 轻量级函数式编程》 —— SegmentFault</a></li> <li>:book: <a>JavaScript 函数式编程(三) —— @BuptStEve</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>10. 表达式和语句</h2> <h3>文章</h3> <ul> <li>:book: <a>js 表达式与语句 —— 博客园</a></li> <li>:book: <a>JS 表达式和语句的区别 —— SegmentFault</a></li> <li>:book: <a>JavaScript 中的表达式(expression)和语句/声明(statement) —— CSDN</a></li> <li>:book: <a>重讀 Axel 的 Javascript 中的 Expression vs Statement 一文 —— SegmentFault</a></li> <li>:book: <a>Expressions versus statements in JavaScript —— Dr. Axel</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>11. 变量提升</h2> <h3>文章</h3> <ul> <li>:book: <a>JavaScript 变量提升 —— 菜鸟教程</a></li> <li>:book: <a>ES6 变量作用域与提升:变量的生命周期详解 —— 掘金</a></li> <li>:book: <a>[翻译] JavaScript Scoping and Hoisting —— SegmentFault</a></li> <li>:book: <a>JavaScript Scoping and Hoisting —— Ben Cherry</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>12. Promise</h2> <h3>文章</h3> <ul> <li>:book: <a>使用 promises —— MDN</a></li> <li>:book: <a>Promise —— MDN</a></li> <li>:book: <a>Promise — 廖雪峰</a></li> <li>:book: <a>JavaScript Promise:去而复返 —— 司徒正美</a></li> <li>:book: <a>(上面的原文)JavaScript Promise:简介 —— Web Fundamentals</a></li> <li>:book: <a>1 分钟读完《10 分钟学会 JavaScript 的 Async/Await》 —— justjavac</a></li> <li>:book: <a>JavaScript Promise 迷你书(中文版)</a></li> <li>:book: <a>JavaScript 进阶之路——认识和使用 Promise,重构你的 Js 代码 —— 博客园</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>Promise 入门 —— 慕课网</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>13. 立即执行函数, 模块化, 命名空间</h2> <h3>文章</h3> <ul> <li>:book: <a>Javascript 模块化编程(一):模块的写法 —— 阮一峰</a></li> <li>:book: <a>javascript 模块化编程-详解立即执行函数表达式 —— 简书</a></li> <li>:book: <a>Javascript 的匿名函数与自执行 —— 掘金</a></li> <li>:book: <a>前端模块化——技术选型 —— SegmentFault</a></li> <li>:book: <a>谈谈 Js 前端模块化规范 —— SegmentFault</a></li> <li>:book: <a>函数声明与函数表达式的区别 —— 伯乐在线</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>14. 递归</h2> <h3>文章</h3> <ul> <li>:book: <a>求解释 js 递归 —— SegmentFault</a></li> <li>:book: <a>JavaScript 中的递归 —— 掘金</a></li> <li>:book: <a>递归(上)-《JavaScript 轻量级函数式编程》 —— 掘金</a></li> <li>:book: <a>递归(下)-《JavaScript 轻量级函数式编程》 —— 掘金</a></li> <li>:book: <a>尾调用和尾递归 —— 掘金</a></li> <li>:book: <a>几个经典递归问题用 js 实现 —— CSDN</a></li> <li>:book: <a>递归函数的几个例子 —— CSDN</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>15. 算法</h2> <h3>文章</h3> <ul> <li>:book: <a>十大经典排序算法总结(JavaScript 描述) —— 掘金</a></li> <li>:book: <a>在 JavaScript 中学习数据结构与算法 —— 掘金</a></li> <li>:book: <a>JS 中可能用得到的全部的排序算法 —— 掘金</a></li> <li>:book: <a>JS 家的排序算法 —— 简书</a></li> <li>:book: <a>前端常见算法的 JS 实现 —— SegmentFault</a></li> <li>:book: <a>前端面试中的常见的算法问题 ——蒲小花的博客</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>Javascript 实现二叉树算法 —— 慕课网</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>16. 数据结构</h2> <h3>文章</h3> <ul> <li>:book: <a>来我们浅谈一下 js 的数据结构 —— 简书</a></li> <li>:book: <a>JavaScript 中的算法与数据结构 —— 简书</a></li> <li>:book: <a>学 JS 必看-JavaScript 数据结构深度剖析 —— 大道至简的博客</a></li> <li>:book: <a>js 中基础数据结构数组去重问题 —— 掘金</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: :tv: <a>JavaScript 数据结构-运算符 —— 乐视</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>17. 消息队列和事件循环</h2> <h3>文章</h3> <ul> <li>:book: <a>并发模型与事件循环 —— MDN</a></li> <li>:book: <a>JavaScript 运行机制详解:再谈 Event Loop —— 阮一峰</a></li> <li>:book: <a>深入理解 JavaScript 事件循环 —— 博客园</a></li> <li>:book: <a>深入浅出 Javascript 事件循环机制 —— 知乎</a></li> <li>:book: <a>JS 事件循环机制(event loop)之宏任务、微任务 —— SegmentFault</a></li> <li>:book: <a>JavaScript:彻底理解同步、异步和事件循环 —— SegmentFault</a></li> <li>:book: <a>从浏览器多进程到 JS 单线程,JS 运行机制最全面的一次梳理 —— 掘金</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>18. setTimeout, setInterval 和 requestAnimationFrame</h2> <h3>文章</h3> <ul> <li>:book: <a>Window setTimeout() 方法 —— 菜鸟教程</a></li> <li>:book: <a>Window setInterval() 方法 —— 菜鸟教程</a></li> <li>:book: <a>关于 setTimeout —— 掘金</a></li> <li>:book: <a>你不知道的 Javascript:有趣的 setTimeout —— 掘金</a></li> <li>:book: <a>原来你是这样的 setTimeout —— 掘金</a></li> <li>:book: <a>setTimeout() 和 setInterval() 本质区别在哪里? —— SegmentFault</a></li> <li>book: <a>window.requestAnimationFrame —— MDN</a></li> <li>:book: <a>requestAnimationFrame 知多少? —— 博客园</a></li> <li>:book: <a>CSS3 动画那么强,requestAnimationFrame 还有毛线用? —— 张鑫旭</a></li> <li>:book: <a>「JavaScript 定时器」setInterval、setTimeout 和 requestAnimationFrame 浅析 —— SegmentFault</a></li> <li>:book: <a>翻译:setInterval 与 requestAnimationFrame 的时间间隔测试 —— SegmentFault</a></li> <li>:book: <a>阿里前端面试题:requestAnimationFrame 实现类似 setInterval 的计时器 —— SegmentFault</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>setTimeout 和 setInterval —— 优酷</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>19. 继承, 多态和代码复用</h2> <h3>文章</h3> <ul> <li>:book: <a>JS 面向对象编程之:封装、继承、多态 —— 博客园</a></li> <li>:book: <a>Javascript 的继承与多态 —— 简书</a></li> <li>:book: <a>js:面向对象编程,带你认识封装、继承和多态 —— 掘金</a></li> <li>:book: <a>JavaScript 中的“多继承” —— 掘金</a></li> <li>:book: <a>代码复用模式 —— github</a></li> <li>:book: <a>深入理解 JavaScript:代码复用模式(推荐篇) —— 汤姆大叔</a></li> <li>:book: <a>深入理解 JavaScript:代码复用模式(避免篇) —— 汤姆大叔</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>20. 按位操作符, 类数组对象和类型化数组</h2> <h3>文章</h3> <ul> <li>:book: <a>按位操作符 —— MDN</a></li> <li>:book: <a>类数组对象 —— MDN</a></li> <li>:book: <a>类型化数组 —— MDN</a></li> <li>:book: <a>JavaScript ArrayBuffer 浅析 —— 博客园</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>21. DOM 树和渲染过程</h2> <h3>文章</h3> <ul> <li>:book: <a>如何创建一个 DOM 树 —— MDN</a></li> <li>:book: <a>HTML DOM 节点 —— W3school</a></li> <li>:book: <a>DOM 概述 —— 阮一峰</a></li> <li>:book: <a>《JavaScript 闯关记》之 DOM(上)—— 掘金</a></li> <li>:book: <a>《JavaScript 闯关记》之 DOM(下)—— 掘金</a></li> <li>:book: <a>掌握 DOM 操作 —— 掘金</a></li> <li>:book: <a>操作 DOM —— 廖雪峰</a></li> <li>:book: <a>原来 CSS 与 JS 是这样阻塞 DOM 解析和渲染的 —— 掘金</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>DOM 探索之基础详解篇 —— 慕课网</a></li> <li>:tv: <a>DOM 事件探秘 —— 慕课网</a></li> <li>:tv: <a>jQuery 基础(二)DOM 篇 —— 慕课网</a></li> <li>:tv: <a>JS 操作 DOM 对象属性和方法 —— 爱奇艺</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>22. new 与构造函数, instanceof 与实例</h2> <h3>文章</h3> <ul> <li>:book: <a>构造函数与 new 命令 —— 阮一峰</a></li> <li>:book: <a>Javascript 面向对象编程(二):构造函数的继承 —— 阮一峰</a></li> <li>:book: <a>完整原型链详细图解(构造函数、原型、实例化对象) —— CSDN</a></li> <li>:book: <a>JavaScript 中构造函数与 new 操作符的实例详解 —— PHP 中文网</a></li> <li>:book: <a>构造函数、实例、原型、原型链之间的关系 —— CSDN</a></li> <li>:book: <a>深入理解 JS—instanceof 和原型链 —— CSDN</a></li> <li>:book: <a>前端基础进阶(九):详解面向对象、构造函数、原型与原型链 —— 简书</a></li> <li>:book: <a>js 用 new 实例化对象与直接调用的 this 的区别 —— 简书</a></li> <li>:book: <a>JavaScript 并非所有的东西都是对象 —— justjavac</a></li> <li>:book: <a>JavaScript instanceof 运算符深入剖析 —— IBM</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>改良版的构造函数 —— 乐视</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>23. 原型继承与原型链</h2> <h3>文章</h3> <ul> <li>:book: <a>继承与原型链 —— MDN</a></li> <li>:book: <a>构造函数、原型与原型链 —— github</a></li> <li>:book: <a>原型及原型链 —— github(1269 Star)</a></li> <li>:book: <a>理清 javascript 中的面向对象(一) 原型继承 —— SegmentFault</a></li> <li>:book: <a>JavaScript:继承和原型链(译) —— justjavac</a></li> <li>:book: <a>三张图搞懂 JavaScript 的原型对象与原型链 —— 博客园</a></li> <li>:book: <a>一张图让你搞懂 JavaScript 的继承与原型链 —— CSDN</a></li> <li>:book: <a>JS 高级--原型链(一看就懂,但 18 岁以下请绕道) —— CSDN</a></li> <li>:book: <a>原型继承 —— 廖雪峰</a></li> <li>:book: <a>JS 原型链与继承别再被问倒了 —— 掘金</a></li> <li>:book: <a>征服 JavaScript 面试系列:类继承和原型继承的区别 —— 掘金</a></li> <li>:book: <a>JavaScript 深入之从原型到原型链 —— 冴羽</a></li> <li>:book: <a>深入理解 JavaScript 原型与闭包 —— 王福朋</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>JS 高级-07-原型链继承 —— 乐视</a></li> <li>:tv: <a>JS 原型对象和原型链简介 —— 腾讯视频</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>24. Object.create 和 Object.assign</h2> <h3>文章</h3> <ul> <li>:book: <a>Object.create —— MDN</a></li> <li>:book: <a>Object.assign —— MDN</a></li> <li>:book: <a>Object.create vs Object.assign —— 慕课网手记</a></li> <li>:book: <a>JS 中的 Object.assign()、Object.create()、Object.defineProperty() —— CSDN</a></li> <li>:book: <a>es6 中 object.create()和 object.assign() —— 风信子博客</a></li> <li>:book: <a>Object-Assign-Deep —— github</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>25. 工厂函数和类</h2> <h3>文章</h3> <ul> <li>:book: <a>类 —— MDN</a></li> <li>:book: <a>类和实例 —— 廖雪峰</a></li> <li>:book: <a>Javascript 定义类(class)的三种方法 —— 阮一峰</a></li> <li>:book: <a>【译】ES6 的工厂函数 —— 掘金</a></li> <li>:book: <a>JavaScript 创建对象之单例、工厂、构造函数模式 —— 掘金</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>26. 设计模式</h2> <h3>文章</h3> <ul> <li>:book: <a>JavaScript 设计模式 —— 掘金</a></li> <li>:book: <a>学用 JavaScript 设计模式 —— 极客学院</a></li> <li>:book: <a>[面试专题]JS 设计模式 —— SegmentFault</a></li> <li>:book: <a>JavaScript Patterns 中译本 —— github</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>HTML5 课程大纲 2-11JS 设计模式</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>27. Memoization</h2> <h3>文章</h3> <ul> <li>:book: <a>JavaScript Memoization —— 司徒正美</a></li> <li>:book: <a>memoization 提升递归效率 —— 博客园</a></li> <li>:book: <a>如何提升 JavaScript 的递归效率 —— 51CTO</a></li> <li>:book: <a>JavaScript 高级技巧 Memoization —— SegmentFaut</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>28. 纯函数, 函数副作用和状态变化</h2> <h3>文章</h3> <ul> <li>:book: <a>纯函数(Pure Function) —— React.js 小书</a></li> <li>:book: <a>JavaScript Functional Programming:纯函数 —— 宁皓网</a></li> <li>:book: <a>js 函数的副作用分析 —— 脚本之家</a></li> <li>:book: <a>如何使用纯函数式 JavaScript 处理脏副作用 —— 掘金</a></li> <li>:book: <a>原生 JavaScript 实现 state 状态管理系统 —— 博客园</a></li> <li>:book: <a>JavaScript 函数式编程 —— @BuptStEve</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>29. 耗性能操作和时间复杂度</h2> <h3>文章</h3> <ul> <li>:book: <a>时间复杂度 O(log n) 意味着什么? —— 掘金</a></li> <li>:book: <a>算法的时间复杂度和空间复杂度 —— 掘金</a></li> <li>:book: <a>算法(一)时间复杂度 —— 掘金</a></li> <li>:book: <a>Big O Search Algorithms in JavaScript —— Bradley Braithwaite</a></li> <li>:book: <a>Time Complexity Analysis in JavaScript — Jennifer Bland</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>30. JavaScript 引擎</h2> <h3>文章</h3> <ul> <li>:book: <a>javascript 引擎 —— 百度百科</a></li> <li>:book: <a>V8(JavaScript 引擎) —— 百度百科</a></li> <li>:book: <a>图解搞懂 JavaScript 引擎 Event Loop —— 掘金</a>3</li> <li>:book: <a>V8 JavaScript 引擎:高性能的 ES2015+ —— justjavac</a></li> <li>:book: <a>10 分钟理解 JS 引擎的执行机制 —— SegmentFaut</a></li> <li>:book: <a>V8 javascript 引擎 —— 博客园</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>31. 二进制, 十六进制, 十进制, 科学记数法</h2> <h3>文章</h3> <ul> <li>:book: <a>二、八、十、十六进制转换(图解篇) —— 博客园</a></li> <li>:book: <a>JavaScript 读写二进制数据 —— 掘金</a></li> </ul> <h3>视频</h3> <ul> <li>:tv: <a>二进制、十进制、十六进制互相转化很难吗? —— 百度视频</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>32. 偏函数, 柯里化, Compose 和 Pipe</h2> <h3>文章</h3> <ul> <li>:book: <a>Javascript 函数式编程之偏函数 —— CSDN</a></li> <li>:book: <a>JavaScript 专题之偏函数 —— SegmentFault</a></li> <li>:book: <a>柯里化和偏函数有什么区别? —— SegmentFault</a></li> <li>:book: <a>Javascript 偏函数与柯里化 —— CSDN</a></li> <li>:book: <a>柯里化(curry) —— JS 函数式编程指南</a></li> <li>:book: <a>代码组合(compose) —— JS 函数式编程指南</a></li> <li>:book: <a>关于 javascript 函数式编程中 compose 的实现 —— SegmentFault</a></li> <li>:book: <a>实现 compose 的五种思路 —— SegmentFault</a></li> <li>:book: <a>JavaScript 函数式编程之函数组合函数 compose 和 pipe 的实现 —— SegmentFault</a></li> <li>:book: <a>JavaScript 轻量级函数式编程-第 4 章:组合函数 ——掘金</a></li> <li>:book: <a>JavaScript 函数式编程(二) —— @BuptStEve</a></li> </ul> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> <h2>33. 代码整洁之道</h2> <h3>文章</h3> <ul> <li>:book: <a>[译] JavaScript 代码整洁之道 —— 边城</a></li> <li>:book: <a>Javascript 编程风格 —— 阮一峰</a></li> <li>:book: <a>重构 - 代码整洁之道 —— 掘金</a></li> <li>:book: <a>让你的代码更简短,更整洁,更易读的 ES6 小技巧 —— 掘金</a></li> <li>:book: <a>Web 前端:11 个让你代码整洁的原则 —— 伯乐在线</a></li> <li>:book: <a>Clean Code concepts adapted for JavaScript —— ryanmcdermott</a></li> </ul> <p>&lt;br&gt;</p> <p><strong><a>:arrow_up: 返回目录</a></strong></p> <hr /> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/33_js_concepts/#post-comment/</comments>
</item>
<item>
<title>Grunt 学习总结</title>
<link>https://www.scarsu.com/grunt/</link>
<guid isPermaLink="true">https://www.scarsu.com/grunt/</guid>
<description>自动化 压缩(minification)、编译、单元测试、linting等</description>
<pubDate>Sat, 01 Jun 2019 00:00:00 GMT</pubDate>
<content:encoded><h1>是什么 &amp; 用途 &amp; 场景</h1> <p>grunt本身是一种自动化任务处理工具,它是一个工具框架,有很多插件扩展它的功能。</p> <p>通过丰富的grunt插件可以实现以下功能:</p> <ul> <li>jshint代码检查</li> <li>代码合并</li> <li>代码压缩--js/css/html都可以</li> <li>SASS/LESS编译css</li> <li>watch监听---文件发生改变自动执行任务</li> </ul> <h1>相关</h1> <ul> <li><a>官方github</a></li> <li><a>官方网址(文档)</a></li> <li><a>中文文档</a></li> <li><a>插件列表</a></li> </ul> <h1>环境</h1> <p>grunt依赖Nodejs和npm环境</p> <p>使用npm安装全局grunt-cli命令行工具:<code>npm install -g grunt-cli</code></p> <h1>demo</h1> <ol> <li>需求</li> </ol> <p>假设你手上有一个项目,叫gruntlearn,项目文件中你的源码存储在src目录下,包含四个模块的js文件,还没编译的scss文件,html文件,图片文件:</p> <p><img src="/images/grunt/grunt01.png" alt="demo src 目录结构" /></p> <p>现在你想用grunt,自动给你的源代码执行几个任务:</p> <ul> <li>将images/html和复制到 发布文件夹build下</li> <li>用jshint检查js语法</li> <li>合并四个js文件(分别合并,因为a,b用于不同的页面)</li> <li>编译scss文件</li> <li>压缩合并后的js文件,存储到build下</li> <li>调试:新建一个本地服务器监听文件改变自动刷新HTML文件</li> </ul> <ol> <li>搭建环境</li> </ol> <ul> <li>在命令行里打开到gruntlearn的目录下,执行<code>npm init</code></li> <li>安装 grunt 和 grunt-cli</li> </ul> <pre><code>npm install grunt-cli --global npm install grunt --save-dev </code></pre> <ul> <li>在项目中安装grunt和相关插件,根据第1步中的需求,需要用到一下插件: <ul> <li>复制文件:grunt-contrib-copy</li> <li>合并文件:grunt-contrib-concat</li> <li>语法检查:grunt-contrib-jshint</li> <li>Scss 编译:grunt-contrib-sass</li> <li>压缩文件:grunt-contrib-uglify</li> <li>监听文件变动:grunt-contrib-watch</li> <li>建立本地服务器:grunt-contrib-connect</li> </ul> </li> <li>安装插件:</li> </ul> <pre><code>npm install --save-dev grunt-contrib-copy grunt-contrib-concat grunt-contrib-jshint grunt-contrib-sass grunt-contrib-uglify grunt-contrib-watch grunt-contrib-connect </code></pre> <ul> <li> <p>创建gruntfile.js文件,代码结构: <img src="/images/grunt/grunt02.png" alt="gruntfile.js 代码结构" /></p> </li> <li> <p>根据demo需求配置gruntfile:</p> </li> </ul> <pre><code>//wrapper函数 module.exports = function (grunt) { //你可以像普通的js文件一样添加自己的代码 var sassStyle = "expanded"; //1.配置任务 tasks--根据插件的文档来定义任务 grunt.initConfig({ pkg: grunt.file.readJSON("package.json"), //将html和图片从src复制到build copy: { //task html: { //target files: [ { expand: true, cwd: "./src/html", src: "*", dest: "./build/html/" }, ], }, images: { //target files: [ { expand: true, cwd: "./src/images", src: "*", dest: "./build/images/", }, ], }, }, //合并js concat: { /* options: { separator: ';',//合并分隔符 }, */ dist: { files: { //文件路径 "./src/js/a.all.js": ["./src/js/a.1.js", "./src/js/a.2.js"], "./src/js/b.all.js": ["./src/js/b.1.js", "./src/js/b.2.js"], }, }, }, //task:编译sass sass: { output: { //target options: { //target options style: sassStyle, }, files: { "./build/css/style.css": "./src/scss/style.scss", //'目标文件':'源文件' }, }, }, //代码检查 jshint: { all: ["./src/js/a.all.js", "./src/js/b.all.js"], }, //压缩 uglify: { uglifyjs: { files: { "./build/js/a.min.js": ["./src/js/a.all.js"], "./build/js/b.min.js": ["./src/js/b.all.js"], }, }, }, //监听 watch: { scripts: { files: [ "./src/js/a.1.js", "./src/js/a.2.js", "./src/js/b.1.js", "/src/js/b.2.js", ], tasks: ["concat", "jshint", "uglify"], }, sass: { files: ["./src/scss/style.scss"], tasks: ["sass"], }, livereload: { options: { liverelload: "&lt;%= connect.options.livereload %&gt;", }, files: [ "./src/html/index.html", "./src/scss/style.scss", "./src/js/a.1.js", "./src/js/a.2.js", "./src/js/b.1.js", "./src/js/b.2.js", ], }, }, connect: { options: { port: 9000, open: true, livareload: 35729, //change this to '0.0.0.0' to access the server from outside hostname: "localhost", }, server: { options: { port: 9001, base: "./", }, }, }, }); //2.加载插件 grunt.loadNpmTasks("grunt-contrib-copy"); grunt.loadNpmTasks("grunt-contrib-concat"); grunt.loadNpmTasks("grunt-contrib-sass"); grunt.loadNpmTasks("grunt-contrib-jshint"); grunt.loadNpmTasks("grunt-contrib-uglify"); grunt.loadNpmTasks("grunt-contrib-watch"); grunt.loadNpmTasks("grunt-contrib-connect"); //3.注册任务 grunt.registerTask("copyhtml", ["copy:html"]); //可以用task:target的方法分别注册 grunt.registerTask("concatjs", ["concat"]); //也可以只用task名称注册,默认执行task下全部target grunt.registerTask("outputcss", ["sass"]); grunt.registerTask("watchit", [ "concat", "sass", "jshint", "uglify", "connect", "watch", ]); grunt.registerTask("default", ["copy", "concat", "sass", "jshint", "uglify"]); }; </code></pre> <ul> <li> <p>执行定义好的命令<code>grunt default</code>: <img src="/images/grunt/grunt03.png" alt="执行命令" /></p> </li> <li> <p>执行后的项目目录结构: <img src="/images/grunt/grunt04.png" alt="执行后目录结构" /></p> </li> </ul> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/grunt/#post-comment/</comments>
</item>
<item>
<title>英语 | 计算机相关 单词书📖</title>
<link>https://www.scarsu.com/cs_english/</link>
<guid isPermaLink="true">https://www.scarsu.com/cs_english/</guid>
<description>总结一下,我看英文前端文档/视频遇到的一些计算机/前端相关的单词/专业术语</description>
<pubDate>Tue, 01 Jan 2019 00:00:00 GMT</pubDate>
<content:encoded><p>从2014年大一过了六级之后,就把学英语落下了,但是作为一名程序员,英语是很重要的。</p> <p>所以工作之后经常刻意要求自己读英文文档,也看过一些英文前端视频,比如FrontEndMaster、WesBos。</p> <p>利用本文总结一下,我看英文前端文档/视频遇到的一些计算机/前端相关的单词/专业术语/非英语环境难遇到的一些词汇👇。</p> <p>(另外推荐一个相关资源:<a>中国程序员容易发音错误的单词</a>)</p> <table> <thead> <tr> <th>单词</th> <th>释义</th> <th>来源</th> </tr> </thead> <tbody> <tr> <td>under the hood</td> <td>底层</td> <td></td> </tr> <tr> <td>specify</td> <td>指定</td> <td></td> </tr> <tr> <td>get passed in</td> <td>传入</td> <td></td> </tr> <tr> <td>sync/async</td> <td>同步异步</td> <td></td> </tr> <tr> <td>asynchronously</td> <td>异步</td> <td></td> </tr> <tr> <td>whatnot</td> <td>诸如此类的</td> <td></td> </tr> <tr> <td>in good shape</td> <td>(运行代码的时候祈祷的</td> <td></td> </tr> <tr> <td>gotchas</td> <td>陷阱</td> <td></td> </tr> <tr> <td>shortcut</td> <td>捷径</td> <td></td> </tr> <tr> <td>inventory</td> <td>库存/牛</td> <td></td> </tr> <tr> <td>neat</td> <td>整齐利落</td> <td></td> </tr> <tr> <td>scaffold</td> <td>脚手架</td> <td></td> </tr> <tr> <td>handy</td> <td>便利</td> <td></td> </tr> <tr> <td>ultimate</td> <td>最终</td> <td></td> </tr> <tr> <td>rewind</td> <td>倒回/回退</td> <td></td> </tr> <tr> <td>isolation</td> <td>隔离</td> <td></td> </tr> <tr> <td>interfere</td> <td>妨碍 打扰</td> <td></td> </tr> <tr> <td>capture</td> <td>捕获</td> <td></td> </tr> <tr> <td>raw</td> <td>原生的</td> <td></td> </tr> <tr> <td>vanilla js</td> <td>raw js:原生js</td> <td></td> </tr> <tr> <td>nail</td> <td>钉子 固定 (巩固知识)</td> <td></td> </tr> <tr> <td>built-in</td> <td>内置的</td> <td></td> </tr> <tr> <td>newbies</td> <td>新手</td> <td></td> </tr> <tr> <td>tutorial</td> <td>教程</td> <td></td> </tr> <tr> <td>sane</td> <td>合理的明智的</td> <td></td> </tr> <tr> <td>modular</td> <td>模块化的</td> <td></td> </tr> <tr> <td>cardio</td> <td>有氧运动</td> <td></td> </tr> <tr> <td>hard code</td> <td>写死的代码</td> <td></td> </tr> <tr> <td>reinstate</td> <td>恢复</td> <td></td> </tr> <tr> <td>verbose</td> <td>冗余的</td> <td></td> </tr> <tr> <td>upstream</td> <td>(向上返回)</td> <td></td> </tr> <tr> <td>downstream</td> <td>(向下传)</td> <td></td> </tr> <tr> <td>CRUD acronym</td> <td>CRUD</td> <td></td> </tr> <tr> <td>manually</td> <td>手动</td> <td></td> </tr> <tr> <td>DEPRECATED</td> <td>启用</td> <td></td> </tr> <tr> <td>bottleneck</td> <td>瓶颈</td> <td></td> </tr> <tr> <td>audit</td> <td>审计</td> <td></td> </tr> <tr> <td>monitor</td> <td>监控</td> <td></td> </tr> <tr> <td>profile</td> <td>分析</td> <td></td> </tr> <tr> <td>memory leaks</td> <td>内存泄漏</td> <td></td> </tr> <tr> <td>emulate/simulation</td> <td>仿真/模拟</td> <td></td> </tr> <tr> <td>refactor</td> <td>重构</td> <td></td> </tr> <tr> <td>parser</td> <td>解析器</td> <td></td> </tr> <tr> <td>anonymous</td> <td>匿名</td> <td></td> </tr> <tr> <td>deactivated</td> <td>停用</td> <td></td> </tr> <tr> <td>stats</td> <td>统计数据</td> <td></td> </tr> <tr> <td>optimization</td> <td>优化</td> <td></td> </tr> <tr> <td>AST abstract syntax tree</td> <td>抽象语法树</td> <td></td> </tr> <tr> <td>meg</td> <td>兆</td> <td></td> </tr> <tr> <td>thrashing</td> <td>抖动</td> <td></td> </tr> <tr> <td>idle</td> <td>空闲</td> <td></td> </tr> <tr> <td>trigger</td> <td>触发</td> <td></td> </tr> <tr> <td>GC garbage collector</td> <td>垃圾回收器</td> <td></td> </tr> <tr> <td>snapshot</td> <td>快照</td> <td></td> </tr> <tr> <td>shallow size</td> <td>是指用于存储其本身的内存大小</td> <td></td> </tr> <tr> <td>retained size</td> <td>释放该对象后对象所占总内存该类的所有实例可支配的内存大小</td> <td></td> </tr> <tr> <td>heap snapshot</td> <td>堆快照</td> <td></td> </tr> <tr> <td>containment</td> <td>容量</td> <td></td> </tr> <tr> <td>overhead</td> <td>开销</td> <td></td> </tr> <tr> <td>distribution</td> <td>分配</td> <td></td> </tr> <tr> <td>timeline</td> <td>时间轴</td> <td></td> </tr> <tr> <td>delegate</td> <td>转交,委托</td> <td>Event Delegation事件委托</td> </tr> <tr> <td>prefix/postfix</td> <td>前缀后缀</td> <td></td> </tr> <tr> <td>Adaptor</td> <td>适配器</td> <td></td> </tr> <tr> <td>TL;DR</td> <td>too long;don't/didn't read 精华/总结</td> <td></td> </tr> <tr> <td>conjecture</td> <td>猜测猜想,推测</td> <td>https://www.codewars.com/kata/52fefe6cb0091856db00030e/train/javascript</td> </tr> <tr> <td>Threshold</td> <td>阈值</td> <td></td> </tr> <tr> <td>constants</td> <td>常量</td> <td></td> </tr> <tr> <td>assign</td> <td>赋值</td> <td></td> </tr> <tr> <td>dirty</td> <td>一般指代更改了未保存的数据/文件</td> <td></td> </tr> <tr> <td>truthy</td> <td>泛指真值</td> <td></td> </tr> <tr> <td>singly-linked list</td> <td>单链表</td> <td></td> </tr> <tr> <td>legacy</td> <td>遗留问题(legacy code:万恶的遗留代码)</td> <td></td> </tr> <tr> <td>instruction</td> <td>指令</td> <td></td> </tr> <tr> <td>Glossary</td> <td>术语</td> <td></td> </tr> <tr> <td>constrained</td> <td>受约束的</td> <td></td> </tr> <tr> <td>deterministic</td> <td>确定的</td> <td></td> </tr> <tr> <td>decent</td> <td>优雅的、体面的</td> <td></td> </tr> <tr> <td>bulk</td> <td>体积</td> <td></td> </tr> <tr> <td>parallel</td> <td>并行的。平行的</td> <td></td> </tr> <tr> <td>fraction</td> <td>片段</td> <td></td> </tr> <tr> <td>standstill</td> <td>停止停顿</td> <td></td> </tr> <tr> <td>subtle</td> <td>微妙的</td> <td></td> </tr> <tr> <td>augment</td> <td>增强,扩展(vue 拦截数组方法,扩展数组的原型方法时使用 protoAugment</td> <td></td> </tr> <tr> <td>instantiation</td> <td>实例化</td> <td></td> </tr> <tr> <td>Cheat sheet</td> <td>手册 清单</td> <td></td> </tr> <tr> <td>on-the-fly</td> <td>动态</td> <td></td> </tr> <tr> <td>convention</td> <td>公约,惯例</td> <td></td> </tr> <tr> <td>cluster</td> <td>集群</td> <td></td> </tr> <tr> <td>resolve</td> <td>解析</td> <td></td> </tr> <tr> <td>amend</td> <td>修正修订 eg.git commit --amend</td> <td></td> </tr> <tr> <td>abort</td> <td>中止</td> <td></td> </tr> <tr> <td>bias</td> <td>偏差/偏置</td> <td>机器学习术语</td> </tr> <tr> <td>explicit</td> <td>显式的,清楚明确的</td> <td></td> </tr> <tr> <td>Conquer</td> <td>攻破、征服的</td> <td></td> </tr> <tr> <td>carve</td> <td>雕刻</td> <td></td> </tr> <tr> <td>carve out some time</td> <td>挤出一些时间</td> <td></td> </tr> <tr> <td>tackle</td> <td>处理、解决、应付</td> <td></td> </tr> <tr> <td>intentionally</td> <td>刻意地、故意地</td> <td></td> </tr> <tr> <td>corresponding</td> <td>相对应的</td> <td></td> </tr> <tr> <td>nest</td> <td>巢,嵌套</td> <td></td> </tr> <tr> <td>nested array</td> <td>嵌套数组</td> <td></td> </tr> <tr> <td>flat(ten)</td> <td>展开,铺平,扁平化</td> <td>Array.prototype.flat方法</td> </tr> <tr> <td>scenario</td> <td>/səˈnɛrioʊ/方案;场景,情景</td> <td></td> </tr> <tr> <td>operands</td> <td>操作数,运算对象</td> <td></td> </tr> <tr> <td>diagonal</td> <td>对角线,斜线</td> <td>leetcode 52. N皇后问题,棋盘斜线集合变量名</td> </tr> <tr> <td>dimensions</td> <td>尺寸,维度</td> <td>FCC https://www.freecodecamp.org/learn/responsive-web-design/responsive-web-design-principles/make-typography-responsive</td> </tr> <tr> <td>circuit</td> <td>线路,回路</td> <td>https://www.codewars.com/kata/5536a85b6ed4ee5a78000035/train/javascript</td> </tr> <tr> <td>polyfill</td> <td>填充</td> <td>https://github.com/inexorabletash/polyfill</td> </tr> <tr> <td>shim</td> <td>垫片</td> <td>https://github.com/es-shims/es5-shim</td> </tr> <tr> <td>exceed</td> <td>超过,溢出</td> <td></td> </tr> <tr> <td>exponential</td> <td>指数</td> <td>https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number/toExponential</td> </tr> <tr> <td>allowlists</td> <td>白名单</td> <td>https://developers.google.com/web/fundamentals/security/csp</td> </tr> <tr> <td>pitfall</td> <td>陷阱</td> <td>https://css-tricks.com/debouncing-throttling-explained-examples/</td> </tr> <tr> <td>traverse</td> <td>遍历,今天leetcode每日一题又遇到一次,renew</td> <td>https://developer.mozilla.org/en-US/docs/Web/API/Element/closest</td> </tr> <tr> <td>successive</td> <td>连续的</td> <td>https://www.codewars.com/kata/562b384167350ac93b00010c/train/javascript</td> </tr> <tr> <td>immersive</td> <td>沉浸式</td> <td></td> </tr> <tr> <td>trade-off</td> <td>交换,权衡,妥协</td> <td>技术选型场景常用语</td> </tr> <tr> <td>interceptor</td> <td>拦截器</td> <td>axios</td> </tr> <tr> <td>peer</td> <td>对等的</td> <td>npm WARN经常出现:You must install peer dependencies yourself.</td> </tr> <tr> <td>actuator</td> <td>致动器,执行机</td> <td><a>github</a></td> </tr> <tr> <td>Ambiguous</td> <td>模棱两可的,多义的机</td> <td>com.microsoft.sqlserver.jdbc.SQLServerException: Ambiguous column name 'xx'</td> </tr> <tr> <td>discard</td> <td>丢弃 放弃 遗弃</td> <td>常见'确认discard changes?'</td> </tr> <tr> <td>diagonals</td> <td>对角线,斜线</td> <td>算法 N皇后问题遇到</td> </tr> <tr> <td>Semantic</td> <td>语义</td> <td>https://probot.github.io/apps/semantic-pull-requests/</td> </tr> <tr> <td>transmitter</td> <td>发送器,传输器</td> <td>https://github.com/zhantewei2/ztwx-http#readme</td> </tr> <tr> <td>intersection</td> <td>交叉、交集</td> <td>IntersectionObserver from https://developer.mozilla.org/zh-CN/docs/Web/API/IntersectionObserver</td> </tr> <tr> <td>in place</td> <td>就地</td> <td>modify arr in-place就地更改数组 https://leetcode.cn/problems/duplicate-zeros/</td> </tr> <tr> <td>macro</td> <td>宏</td> <td>计算机科学里的宏是一种抽象,它根据一系列预定义的规则替换一定的文本模式。 https://baike.baidu.com/item/MACRO/10429400</td> </tr> <tr> <td>stale</td> <td>陈旧的</td> <td>cache-control:stale-while-revalidate , https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control</td> </tr> <tr> <td>offload</td> <td>卸下、卸载</td> <td></td> </tr> <tr> <td>markup</td> <td>标识、标记</td> <td></td> </tr> <tr> <td>prioritize</td> <td>v. 按优先顺序列出;优先考虑(处理)</td> <td></td> </tr> <tr> <td>hint</td> <td>n. v. 提示、暗示,迹象</td> <td></td> </tr> <tr> <td>rasterization</td> <td>n. 格栅化</td> <td></td> </tr> <tr> <td>phase</td> <td>n. 阶段</td> <td></td> </tr> <tr> <td>dimension</td> <td>n. 尺寸、维度、规模、范围</td> <td></td> </tr> <tr> <td>geometry</td> <td>n. 几何</td> <td></td> </tr> <tr> <td>omit</td> <td>n. 省去,不做;遗漏,未能做</td> <td></td> </tr> <tr> <td>intact</td> <td>保持原样、原封不动</td> <td></td> </tr> <tr> <td>peer</td> <td>对等、同行</td> <td>peer-to-peer 点对点 端对端 对等</td> </tr> <tr> <td>disclaimer</td> <td>免责声明、 不承诺</td> <td>https://raw.githubusercontent.com/GoogleChrome/lighthouse/f943f8948276188a365214e668aee02e9753484d/docs/Network-Timings.svg</td> </tr> <tr> <td>fatigue</td> <td>疲劳</td> <td>frontend fatigue 前端疲劳,表达前端太卷学不到了</td> </tr> </tbody> </table> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/cs_english/#post-comment/</comments>
</item>
<item>
<title>State of JS | 2018年度javascript行业报告</title>
<link>https://www.scarsu.com/2018_javascript_report/</link>
<guid isPermaLink="true">https://www.scarsu.com/2018_javascript_report/</guid>
<description>JavaScript生态圈总是在变化。新的库,新的框架,新的语言..这有时是有乐趣的,但有时也会让人感到压力。</description>
<pubDate>Mon, 31 Dec 2018 00:00:00 GMT</pubDate>
<content:encoded><p><img src="/images/stateofjs/000.png" alt="" /></p> <h1>数据来源</h1> <p>来自 153 个不同的国家</p> <p>共 20,268 名 JavaScript 开发者参与调查</p> <p>中国占总数的 0.37%,共 75 个开发者</p> <p>(因此本调查报告整体上能反映全球范围的 Javascript 发展趋势,但对国内情况不具有代表性)</p> <p><strong>调查参与者 国家分布图:</strong></p> <p><img src="/images/stateofjs/1.png" alt="" /></p> <p><strong>调查参与者 薪资分布图:</strong></p> <p><img src="/images/stateofjs/2.png" alt="" /></p> <p><strong>调查参与者 开发经验分布图:</strong></p> <p><img src="/images/stateofjs/3.png" alt="" /></p> <p><strong>调查参与者 所属公司体量分布图:</strong></p> <p><img src="/images/stateofjs/4.png" alt="" /></p> <p><strong>调查参与者 性别分布图:</strong></p> <p><img src="/images/stateofjs/5.png" alt="" /></p> <h1>调查结果</h1> <h2>1.JavaScript Flavors</h2> <p>可以编译成 javasript 代码 的 各种语言/语法规范/javascript 超集</p> <p><img src="/images/stateofjs/6.png" alt="" /></p> <h2>2.前端框架 Front-end Frameworks</h2> <p><img src="/images/stateofjs/7.png" alt="" /></p> <h2>3.数据层 Data Layer</h2> <p><img src="/images/stateofjs/8.png" alt="" /></p> <h2>4.后端框架 Back-end Frameworks</h2> <p><img src="/images/stateofjs/9.png" alt="" /></p> <h2>5.测试 Testing</h2> <p><img src="/images/stateofjs/10.png" alt="" /></p> <h2>6.移动端/客户端 Mobile &amp; Desktop</h2> <p><img src="/images/stateofjs/11.png" alt="" /></p> <h2>7.js 开发者使用的其他语言 Other Languages</h2> <p><img src="/images/stateofjs/12.png" alt="" /></p> <h2>8.浏览器 API Browser APIs</h2> <p><img src="/images/stateofjs/13.png" alt="" /></p> <h2>9.构建工具 Build Tools</h2> <p><img src="/images/stateofjs/14.png" alt="" /></p> <h2>10.函数库 Utility Libraries</h2> <p><img src="/images/stateofjs/15.png" alt="" /></p> <h2>11.编辑器 Text Editors</h2> <p><img src="/images/stateofjs/16.png" alt="" /></p> <h2>12.js 开发者的使用感受+期望</h2> <p><strong>“Javascript 正在往正确的方向发展”</strong></p> <p><img src="/images/stateofjs/17.png" alt="" /></p> <p><strong>“当下构建 Javascript app 过于复杂惹”</strong></p> <p><img src="/images/stateofjs/18.png" alt="" /></p> <p><strong>“Javascript 被过度使用”</strong></p> <p><img src="/images/stateofjs/19.png" alt="" /></p> <p><strong>“我喜欢构建 JavaScript 应用程序”</strong></p> <p><img src="/images/stateofjs/20.png" alt="" /></p> <p><strong>“我希望 JavaScript 成为我的主要编程语言”</strong></p> <p><img src="/images/stateofjs/21.png" alt="" /></p> <p><strong>“JavaScript 生态系统变化太快”</strong></p> <p><img src="/images/stateofjs/22.png" alt="" /></p> <p><strong>“这项调查太长惹!”</strong></p> <p><img src="/images/stateofjs/23.png" alt="" /></p> <h1>年度之最</h1> <ul> <li><strong>最满意: Jest</strong></li> </ul> <blockquote> <p>96.5%的使用者表示会再次使用</p> </blockquote> <ul> <li><strong>最感兴趣: GraphQL</strong></li> </ul> <blockquote> <p>听说过 GraphQL 的开发者中有 87.7%表示想要学习</p> </blockquote> <ul> <li><strong>最多提及: Vuex</strong></li> </ul> <blockquote> <p>在“other libraries”提问中最多被提及的库</p> </blockquote> <ul> <li><strong>最多使用: React</strong></li> </ul> <blockquote> <p>年度被使用最多的库,参与调查者中有 14417 位使用 React</p> </blockquote> <ul> <li><strong>最黑马: Reason</strong></li> </ul> <blockquote> <p>Facebook 带来的 崭露头角的 新技术,也许会像 React 和 GraphQL 一样受欢迎?</p> </blockquote> <ul> <li><strong>最特别: VSCode</strong></li> </ul> <blockquote> <p>我们今年刚刚爱上并无法自拔的工具</p> </blockquote> <h1>参赛选手信息</h1> <h3>Javascript Flavors</h3> <ul> <li>ES6</li> </ul> <blockquote> <p>ECMA-262 标准的 Edition6(目前已经发布到 ECMA-262 2018/Edition 9),是 javascript 的规范</p> <p>https://github.com/tc39/ecma262#ecmascript</p> </blockquote> <ul> <li>Typescript</li> </ul> <blockquote> <p>由微软开发的 添加了可选的静态类型和基于类的面向对象编程 的 JS 超集</p> <p>https://github.com/Microsoft/TypeScript</p> </blockquote> <ul> <li>Flow</li> </ul> <blockquote> <p>JavaScript 添加静态类型检查器</p> <p>https://github.com/facebook/flow</p> </blockquote> <ul> <li>Reason</li> </ul> <blockquote> <p>简单,快速,类型安全,利用 JavaScript 和 OCaml 生态系统的库</p> <p>http://reasonml.github.io/</p> </blockquote> <ul> <li>Elm</li> </ul> <blockquote> <p>生成具有出色性能且没有运行时异常的 JavaScript 的语言。</p> <p>https://elm-lang.org/</p> </blockquote> <ul> <li>ClojureScript</li> </ul> <blockquote> <p>ClojureScript 是将 Clojure 成 JavaScript 的编译器。</p> <p>https://clojurescript.org/</p> </blockquote> <h3>前端框架</h3> <ul> <li>React</li> </ul> <blockquote> <p>React 是一个用于设计用户界面的开源 JavaScript 库。</p> <p>https://github.com/facebook/react</p> </blockquote> <ul> <li>Vue.js</li> </ul> <blockquote> <p>一套用于构建用户界面的渐进式框架</p> <p>https://cn.vuejs.org/</p> </blockquote> <ul> <li>Angular</li> </ul> <blockquote> <p>基于 TypeScript 的开源前端 Web 应用程序平台。</p> <p>https://angular.io/</p> </blockquote> <ul> <li>Preact</li> </ul> <blockquote> <p>3kB 大小的 使用相同的现代 API 的 React 快速替代方案,拥有组件和虚拟 DOM。</p> <p>https://github.com/developit/preact</p> </blockquote> <ul> <li>Ember</li> </ul> <blockquote> <p>用于创建大型的 Web 应用程序的 JavaScript 框架</p> <p>https://github.com/emberjs/ember.js</p> </blockquote> <ul> <li>Polymer</li> </ul> <blockquote> <p>Web 组件库</p> <p>https://github.com/Polymer/polymer</p> </blockquote> <h3>数据层</h3> <ul> <li>Redux</li> </ul> <blockquote> <p>JavaScript 应用程序的可预测状态容器</p> <p>https://github.com/reduxjs/redux</p> </blockquote> <ul> <li>GraphQL</li> </ul> <blockquote> <p>一种与后端服务相关联的查询语言和执行引擎</p> <p>https://github.com/facebook/graphql</p> </blockquote> <ul> <li>Apollo</li> </ul> <blockquote> <p>适用于每个 UI 框架和 GraphQL 服务器的功能齐全的 可用于生产的 缓存 GraphQL 客户端</p> <p>https://github.com/apollographql/apollo-client</p> </blockquote> <ul> <li>MobX</li> </ul> <blockquote> <p>简单,可扩展的状态管理</p> <p>https://github.com/mobxjs/mobx</p> </blockquote> <ul> <li>Relay/Relay Modern</li> </ul> <blockquote> <p>Relay 是一个用于构建数据驱动的 React 应用程序的 JavaScript 框架</p> <p>https://github.com/facebook/relay</p> </blockquote> <h3>后端框架</h3> <ul> <li>Express</li> </ul> <blockquote> <p>快速简单的 Node 框架</p> <p>https://github.com/expressjs/express</p> </blockquote> <ul> <li>Next.js</li> </ul> <blockquote> <p>一个多功能 React 服务端框架</p> <p>https://nextjs.org</p> </blockquote> <ul> <li>Koa</li> </ul> <blockquote> <p>使用 ES2017 异步函数的 node.js 的中间件</p> <p>https://github.com/koajs/koa</p> </blockquote> <ul> <li>Meteor</li> </ul> <blockquote> <p>JavaScript 应用程序平台</p> <p>https://github.com/meteor/meteor</p> </blockquote> <ul> <li>Sails</li> </ul> <blockquote> <p>Node.js 的实时 MVC 框架</p> <p>https://github.com/balderdashy/sails</p> </blockquote> <ul> <li>FeathersJS</li> </ul> <blockquote> <p>适用于现代应用程序的 REST 和实时 API 层 https://github.com/feathersjs/feathers</p> </blockquote> <h3>Javascript 测试工具</h3> <ul> <li>Jest</li> </ul> <blockquote> <p>令人愉快的 JavaScript 测试工具</p> <p>https://jestjs.io/</p> </blockquote> <ul> <li>Mocha</li> </ul> <blockquote> <p>node.js 和浏览器的简单,灵活,有趣的 javascript 测试框架</p> <p>https://github.com/mochajs/mocha</p> </blockquote> <ul> <li>Jasmine</li> </ul> <blockquote> <p>适用于浏览器和 node.js 的简单 JavaScript 测试框架</p> <p>https://github.com/jasmine/jasmine</p> </blockquote> <ul> <li>Enzyme</li> </ul> <blockquote> <p>用于 React 的 JavaScript 测试实用程序</p> <p>https://github.com/airbnb/enzyme</p> </blockquote> <ul> <li>Karma</li> </ul> <blockquote> <p>健壮的 Javascript 测试工具</p> <p>https://github.com/karma-runner/karma</p> </blockquote> <ul> <li>Storybook</li> </ul> <blockquote> <p>用于交互式 UI 组件:React,React Native,Vue,Angular,Ember 的开发和测试工具</p> <p>https://github.com/storybooks/storybook</p> </blockquote> <ul> <li>Ava</li> </ul> <blockquote> <p>未来的 JavaScript 测试工具</p> <p>https://github.com/avajs/ava</p> </blockquote> <h3>移动端/客户端</h3> <ul> <li>Electron</li> </ul> <blockquote> <p>使用 JavaScript,HTML 和 CSS 构建跨平台桌面应用程序</p> <p>https://github.com/electron/electron</p> </blockquote> <ul> <li>React Native</li> </ul> <blockquote> <p>使用 React 构建应用程序的框架</p> <p>https://github.com/facebook/react-native</p> </blockquote> <ul> <li>Native Apps</li> </ul> <blockquote> <p>原生客户端 App 语言:Java, Kotlin, Objective-C, or Swift 等</p> </blockquote> <ul> <li>Cordova</li> </ul> <blockquote> <p>移动应用程序开发框架</p> <p>https://cordova.apache.org/</p> </blockquote> <ul> <li>Ionic</li> </ul> <blockquote> <p>使用开放式 Web 技术构建的原生和渐进式 Web 应用</p> <p>https://github.com/ionic-team/ionic</p> </blockquote> <ul> <li>NativeScript</li> </ul> <blockquote> <p>用于使用 JavaScript 构建移动端应用程序的开源框架。使用 Web 技能,如 Angular 和 Vue.js,FlexBox 和 CSS,并在 iOS 和 Android 上获得原生 UI 和性能</p> <p>https://github.com/NativeScript/NativeScript</p> </blockquote> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/2018_javascript_report/#post-comment/</comments>
</item>
<item>
<title>Node版本管理工具 nvm for windows</title>
<link>https://www.scarsu.com/nvm_for_windows/</link>
<guid isPermaLink="true">https://www.scarsu.com/nvm_for_windows/</guid>
<description>node版本更新那么快,怎么才能在机子上多装几版node?还能一句命令切换?</description>
<pubDate>Sat, 29 Sep 2018 00:00:00 GMT</pubDate>
<content:encoded><h1>nvm</h1> <p>只支持 linux 和 cent os</p> <h1>nvm for windows</h1> <p><a>https://github.com/coreybutler/nvm-windows/releases</a></p> <h1>安装</h1> <pre><code>0. 安装前卸载干净已经有的node 1. 设置nvm安装路径(不能有空格,否则nvm use 报错) 2. 设置node路径(当前使用的node的存放路径,会被添加到环境变量) </code></pre> <h1>常用命令</h1> <pre><code>nvm list -当前安装的node版本 nvm list available -可获取的版本 nvm install xx.xx.xx -安装某版本node nvm use xx.xx.xx -使用某版本node nvm uninstall xx.xx.xx -卸载某版本node </code></pre> <h1>其他命令</h1> <pre><code>nvm arch -查看当前系统位数 nvm on/off -打开/关闭nvm(好像并没有什么区别 nvm proxy [url] -设置代理下载地址 nvm root [path] -nvm安装路径 nvm node_mirror [url] -node下载库路径 nvm npm_mirror [url] -npm下载库路径 </code></pre> <hr /> <pre><code>“重点是node为什么更新那么快?” </code></pre> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/nvm_for_windows/#post-comment/</comments>
</item>
<item>
<title>360FED课程 - CSS</title>
<link>https://www.scarsu.com/360fe_02_css/</link>
<guid isPermaLink="true">https://www.scarsu.com/360fe_02_css/</guid>
<description>大佬为什么是大佬?</description>
<pubDate>Fri, 07 Sep 2018 00:00:00 GMT</pubDate>
<content:encoded><h1>css</h1> <p>cascading stylesheet 级联样式表</p> <h1>Level 版本</h1> <ul> <li>CSS Level 1(废弃</li> <li>CSS Level 2 (CSS 2.2 完整规范)</li> <li>CSS Level 3(在 2.2 的基础上增加新模块特性 <ul> <li>Color Module Level 3</li> <li>Selectors Level 3</li> <li>Media Queries</li> <li>Fonts Level 3</li> </ul> </li> </ul> <h1>选择器</h1> <h2>简单</h2> <ul> <li>通配 *</li> <li>标签 E</li> <li>类 .class</li> <li>id #id</li> </ul> <h2>属性选择器 [ ]</h2> <pre><code>/* 具有某个属性 */ [disabled] /* 属性为指定的值 */ [type="checkbox"] /* 属性值包含某个字符串 */ [href*="example"] /* 属性值以某个字符串开头 */ [href^="http:"] /* 属性值以某个字符串结束 */ [href$="jpg"] /* 属性值以空格分割后包含某个字符串 */ [lang~="zh-cn"]/* class选择器的实现机制 */ </code></pre> <h2>伪类</h2> <pre><code>/* 动态性伪类,根据状态选择 */ a:link { ... } /* 未访问过的链接 */ a:visited { ... } /* 已访问过的链接 */ a:hover { ... } /* 鼠标移到链接上的样式 */ a:active { ... } /* 鼠标在连接上按下时的样式 */ a:focus { ... } /* 获得焦点时的样式 */ input:disabled { ... } /* 禁用时的样式 */ input:checked { ... } /* 选中时的样式 */ /*利用:checked来做某些toggle组件状态转换*/ /* 结构性伪类 */ :first-child :last-child :nth-child(2n+1) :first-of-type :last-of-type div:nth-of-type(2n+1) /*对nth-child()增加类型限制*/ :empty </code></pre> <h2>组合性选择器</h2> <ul> <li>后代 E F</li> <li>父子 E&gt;F</li> <li>兄弟 E~F</li> <li>相邻兄弟 E+F</li> </ul> <h1>伪元素</h1> <ul> <li>::before</li> <li>::after</li> <li>::first-letter</li> <li>::first-line</li> </ul> <h1>优先级/特异度 Specificity</h1> <ul> <li>!important &gt; 内联 &gt; id &gt; (伪)类 &gt; (伪)元素</li> <li>覆盖:同样优先级:后面写的覆盖前面写的</li> <li>复合选择器:从优先级高的选择器 的 数量 开始比较</li> </ul> <h1>样式来源</h1> <ul> <li>页面开发者</li> <li>用户设置(浏览器可以指定一个本地 CSS 文件,打开所有页面时自动加载</li> <li>浏览器预设 <ul> <li><a>Mozilla Firefox 预设样式</a></li> <li><a>Google Chrome 预设样式</a></li> </ul> </li> <li>优先级: 开发者 &gt; 用户设置 &gt; 浏览器预设</li> <li>加了!important 的优先级:用户 important &gt; 开发者 important &gt; 开发者 &gt; 用户设置 &gt; 浏览器预设</li> </ul> <h1>默认值策略 Defaulting</h1> <h2>继承</h2> <p>某些属性若不指定值,会自动继承父元素的 !!!【计算值】</p> <h2>显示继承</h2> <pre><code>html { box-sizing: border-box; } * { box-sizing: inherit; /* 优点是有某一块都要设置为content-box时,只需要设置其最外层元素,不需要全设置 */ } #xxx { box-sizing: content-box; } </code></pre> <h2>初始值 initial</h2> <ul> <li>CSS 中,每个属性都有一个初始值</li> <li>background-color 的初始值为 transparent</li> <li>margin-left 的初始值为 0,font-size 是 16px,line-height 是 1.2,但根据 font-family 而不同</li> <li>可以显式重置为初始值,比如 background-color: initial</li> <li>可以上 mdn 查初始值</li> </ul> <h1>CSS 求值过程</h1> <h2>一个令人疑惑的很皮的 CSS 求值例子</h2> <pre><code>&lt;article&gt; &lt;h1&gt;卡尔斯巴德洞窟&lt;/h1&gt; &lt;p&gt; 卡尔斯巴德洞窟(Carlsbad Caverns)是美国的一座国家公园, 位于新墨西哥州东南部。游客可以通过天然入口徒步进入,也可以 通过电梯直接到达230米的洞穴深处。 &lt;/p&gt; &lt;/article&gt; &lt;style&gt; body { margin: 0; } article { line-height: 150%; } h1 { font-size: 40px; /*最终实际的line-height值为24px*/ } p { font-size: 14px; /*最终实际的line-height值为24px*/ } &lt;/style&gt; &lt;style&gt; body { margin: 0; } article { line-height: 1.5; } h1 { font-size: 40px; /*最终实际的line-height值为60px*/ } p { font-size: 14px; /*最终实际的line-height值为21px*/ } &lt;/style&gt; &lt;!-- 原因: 设为150%时,子元素继承前,父元素的line-height=150%会先被计算(resolving),得到一个绝对值,被计算为16px(默认的font-size值)*1.5=24px,子元素继承到的值是24px 设为1.5时,子元素继承前,父元素在执行resolving时,1.5是绝对值,不会被转换,所以子元素继承到值1.5,后面再根据自己的font-size*1.5计算line-height 总结:子元素继承到的是父元素的 计算值(一个绝对值) --&gt; </code></pre> <h2>CSS 求值详细过程</h2> <ul> <li>filtering:有效选择器 有效属性值 符合 media ,筛选出所有<strong>声明值 Declared Values</strong></li> <li>cascading:选出优先级最高的一条声明,得到<strong>层叠值 Cascaded Value</strong></li> <li>defaulting:当层叠值为空时,用 继承 | 初始值,得到<strong>指定值 Specified Value</strong></li> <li>resolving:将相对值、关键字转化为绝对值,如 em 转换为 px,%被转换为 px,相对路径转换为绝对路径,得到<strong>计算值 Computed Value</strong></li> <li>formatting:将计算值进一步转换,比如百分比、关键字转换为绝对值,得到<strong>使用值 Used Value</strong></li> <li>constraining:将小数像素转为整数,得到<strong>实际值</strong></li> </ul> <h1>CSS 排版原理</h1> <h2>盒模型</h2> <h3>content-box:</h3> <ul> <li>margin</li> <li>border</li> <li>padding</li> <li>content(width height)</li> </ul> <h3>border-box</h3> <ul> <li>margin</li> <li>border (width = border + padding + content_width)</li> <li>padding</li> <li>content</li> </ul> <h2>height 100%(一般不用</h2> <ul> <li>高度百分数,是相对于父元素的高度</li> <li>若父元素无高度,则百分比高度不生效</li> <li>用 vw vh 设置相对于屏幕的百分比高度,100vh 即 100%屏幕高度</li> </ul> <h2>padding 100%</h2> <ul> <li>padding 百分比值,不论是 padding top、left,都是相对于<strong>父元素宽度</strong></li> <li>应用:做固定宽高比的盒子.</li> </ul> <h2>margin 折叠</h2> <p>上下相邻元素的间距会取其 margin 中较大值。</p> <h2>border:四条边不同颜色</h2> <ul> <li>实际相邻的 border 交界处,是斜切的。</li> <li>当元素的 width height 为 0 时,会得到四个三角形</li> </ul> <h1>background: repeating-conic-gradient(black 0 60deg, yellow 0 120deg);</h1> <h1>视觉格式化模型</h1> <h2>Viewport 视口</h2> <p>浏览器的可视区域,所有元素都在 viewport 内</p> <h2>块级元素(Block-level Elements)</h2> <ul> <li>会被格式化成块状的元素</li> <li>例如 p、div、section 等</li> <li>将 display 设置为 block、list-item、table 会使元素变为块级</li> </ul> <h2>行内元素(Inline-level Elements)</h2> <ul> <li>不会为其内容生成块级框</li> <li>让其内容分布在多行中</li> <li>display 设置为 inline、inline-block、inline-table 会使元素变为行级</li> </ul> <hr /> <pre><code>“因为大佬比你知道的多” </code></pre> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/360fe_02_css/#post-comment/</comments>
</item>
<item>
<title>360FED课程 - HTML</title>
<link>https://www.scarsu.com/360fe_01_html/</link>
<guid isPermaLink="true">https://www.scarsu.com/360fe_01_html/</guid>
<description>这么穷为什么还花钱买HTML学?</description>
<pubDate>Sun, 02 Sep 2018 00:00:00 GMT</pubDate>
<content:encoded><h1>1. 前端做什么</h1> <p>用 web 标准技术 html css js svg http 等</p> <p>做界面与交互</p> <p>功能+美观+无障碍+安全+兼容+性能+体验</p> <h1>2. 知识图谱/技术栈</h1> <h2>2.1. 语言</h2> <ul> <li>js</li> <li>html</li> <li>css</li> <li>php</li> </ul> <h2>2.2. 行业标准</h2> <ul> <li>DOM</li> <li>ES2018</li> <li>HTTP</li> <li>JSON</li> <li>XML</li> </ul> <h2>2.3. 框架</h2> <ul> <li>React.js</li> <li>Angular.js</li> <li>jQuery</li> <li>Vue.js</li> <li>lodash</li> </ul> <h2>2.4. 兼容性</h2> <ul> <li>IE 等浏览器</li> <li>CSS3 新特性</li> <li>HTML5 新特性</li> <li>ES2018</li> <li>移动端</li> </ul> <h2>2.5. 编程思想</h2> <ul> <li>函数式编程</li> <li>面向对象</li> <li>设计模式</li> </ul> <h2>2.6. 调试</h2> <ul> <li>浏览器</li> <li>Fiddler http</li> </ul> <h2>2.7. 工程化</h2> <ul> <li>npm</li> <li>webpack</li> <li>postcss</li> </ul> <h2>2.8. 安全性</h2> <ul> <li>XSS</li> <li>CSRF</li> <li>加密解密</li> <li>编解码</li> </ul> <h2>2.9. 性能</h2> <ul> <li>优化规则</li> <li>开发者工具</li> <li>浏览器原理</li> </ul> <h2>2.10. 团队协作</h2> <ul> <li>git/svn</li> <li>编码规范/eslint</li> <li>文档管理</li> </ul> <h2>2.11. 交互设计</h2> <h1>3. 前端边界</h1> <p>node、electron、react native、webRTC、WebGL、WEBAssembly</p> <h1>4. HTML</h1> <h2>4.1. doctype</h2> <ul> <li>指定文档使用的标准和版本;</li> <li>浏览器根据 doctype 决定使用哪种渲染模式;</li> <li>没写会以怪异模式渲染(盒模型不同等待)</li> <li>渲染模式</li> </ul> <h2>4.2. 语义化</h2> <ul> <li>元素、属性、属性值都有特定含义,应该遵循语义来写 HTML</li> <li>可读性、可维护性、搜索引擎优化、无障碍性</li> </ul> <h2>4.3. 标签</h2> <h3>4.3.1. flow 流式元素:</h3> <ul> <li>heading 标题</li> <li>sectioning 章节</li> <li>phrasing 段落内容 p h</li> <li>Embedded 嵌入式内容 audio canvas</li> <li>interactive 可交互性内容 button a</li> <li>metadata 元数据元素 base link meta noscript script style title</li> </ul> <h3>4.3.2. 看规范</h3> <h2>4.4. HTML 扩展</h2> <h3>4.4.1. meta 标签(增加元数据</h3> <pre><code>&lt;!-- 编码 --&gt; &lt;meta charset="utf-8"&gt; &lt;!-- 指定http header --&gt; &lt;meta http-equiv="Content-Security-Policy" content="script-src 'self'"&gt; &lt;!-- seo优化 --&gt; &lt;meta name="keywords" content="关键词"&gt; &lt;meta name="description" content="页面介绍"&gt; &lt;!-- 移动设备的viewport 初始缩放比例,视口宽度 --&gt; &lt;meta name="viewport" content="initial-scale=1"&gt; &lt;!-- 关闭IOS电话号码识别 --&gt; &lt;meta name="format-detection" content="telphone=no"&gt; &lt;!-- 360等双核浏览器 指定渲染内核 --&gt; &lt;meta name="renderer" content="webkit"&gt; &lt;!-- 指定IE渲染模式 --&gt; &lt;meta name="X-UA-Compatibla" content="IE=Edge"&gt; </code></pre> <h3>4.4.2. data-*属性(规范内-自定义的属性)</h3> <pre><code> datasetAPI &lt;el data-id=""/&gt; el.dataset.id </code></pre> <h3>4.4.3. link</h3> <ul> <li>rel 属性(relation 关系,外部资源与当前页面的关系)</li> </ul> <pre><code>&lt;!-- 引入css --&gt; &lt;link rel="stylesheet" href="" /&gt; &lt;!-- 浏览器性能优化:dns预解析rel=dns-prefetch、资源预加载rel=prefetch、预渲染 rel=prerender --&gt; &lt;link rel="dns-prefetch" href="" /&gt; &lt;link rel="prefetch" href="" /&gt; &lt;link rel="prerender" href="" /&gt; &lt;!-- favicon:rel=icon --&gt; &lt;link rel="icon" type="image/png" href="" /&gt; &lt;!-- RSS:rel=alternate --&gt; &lt;link rel="alternate" type="application/rss+xml" href="" /&gt; </code></pre> <h3>4.4.4. JSON-LD</h3> <p>LD:linkdata 链接的数据 (直接在页面嵌 json 数据)</p> <pre><code>&lt;script type="application/ld+json"&gt; { "@context": "http://schema.org", "@type": "Person", "name": "John Doe", "jobTitle": "Graduate research assistant", "affiliation": "University of Dreams", "additionalName": "Johnny", "url": "http://www.example.com", "address": { "@type": "PostalAddress", "streetAddress": "1234 Peach Drive", "addressLocality": "Wonderland", "addressRegion": "Georgia" } } // 应用例如分享页面时的数据 // 搜索引擎能识别等等 // 分享链接带有一些标题图片等信息 &lt;/script&gt; </code></pre> <h2>4.5. Web 无障碍/Accessibility</h2> <ul> <li>一些 Web 开发者规范: <ul> <li>WCAG2.0</li> <li>ARIA</li> </ul> </li> <li>提升无障碍性 <ul> <li>img alt</li> <li>noscript</li> <li>input 和 label 对应</li> <li>图片验证码与语音验证码</li> <li>文字背景对比度</li> <li>键盘可操作(tab modal focus)</li> </ul> </li> </ul> <h2>4.6. 工具</h2> <ul> <li><a>W3C Validator(检查 html 合法性)</a></li> <li>emmet(插件)</li> <li>markdown(适合写文档)</li> </ul> <h2>4.7. 参考链接</h2> <ul> <li><a>HTML: The Living Standard</a></li> <li><a>Activating Browser Modes with Doctype</a></li> <li><a>Accessibility</a></li> <li>Web Content Accessibility Guidelines 2.0</li> <li><a>HTML5 Doctor: Semantics</a></li> </ul> <h2>全局属性</h2> <h3>class id style</h3> <h3>title</h3> <p>(兼容性最好的 tooltip😂)</p> <h3>tabindex</h3> <p>tab 键控制次序</p> <h3>lang</h3> <p>语言代码(利于语义化机器理解)(语言代码参考手册http://www.runoob.com/tags/html-language-codes.html)</p> <h3>dir</h3> <p>文本方向(rtl ltr auto)</p> <h3>accesskey</h3> <p>元素的键盘访问快捷键(例值为'h'则不同浏览器不同 OS 有不同的操作方式,例 chrome 是 alt + 'h')</p> <h2>(HTML5 全局属性)</h2> <h3>data-*属性</h3> <p>属性名不要包含大写字母,在 data- 后必须至少有一个字符。 该属性可以是任何字符串</p> <pre><code>el.getAttribute("data-xx") </code></pre> <h3>hidden</h3> <p>不需要属性值,隐藏元素,原理是 display:none</p> <h3>contenteditable</h3> <p>元素是否可编辑</p> <h3>contextmenu</h3> <p>(说是目前只有 firefox 支持,亲测没效果</p> <pre><code>&lt;p contextmenu="mymenu"&gt;&lt;/p&gt; &lt;menu id="mymenu"&gt; &lt;command label="xxx" onclick="fn()"/&gt; &lt;command label="xxx" onclick="fn()"/&gt; &lt;/menu&gt; </code></pre> <h3>draggable:(与 HTML5drag 结合用)</h3> <pre><code> &lt;div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"&gt;&lt;/div&gt; &lt;p id="drag1" draggable="true" ondragstart="drag(event)"&gt;这是一段可移动的段落。可把该段落拖入上下的矩形。&lt;/p&gt; &lt;div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)"&gt;&lt;/div&gt; function allowDrop(ev){ ev.preventDefault(); } function drag(ev){ ev.dataTransfer.setData("Text",ev.target.id); } function drop(ev){ var data=ev.dataTransfer.getData("Text"); ev.target.appendChild(document.getElementById(data)); ev.preventDefault(); } </code></pre> <h3>dropzone 属性:</h3> <p>规定当被拖动的数据在拖放到元素上时,是否被复制### 动或链接,无浏览器支持</p> <h3>sppelcheck:</h3> <p>对元素的文本进行拼写检查</p> <h3>translate 属性:</h3> <p>规定元素内容是否要翻译,=yes|no</p> <h1>遗留</h1> <p>表单元素 属性 datalist select 下拉多选 input 的 multiple 属性 button 的 type 属性默认值 video 不能嵌套 img p 不能嵌套 div figure dfn cite 标签</p> <hr /> <pre><code>“因为你永远不知道你不知道的有多少” </code></pre> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/360fe_01_html/#post-comment/</comments>
</item>
<item>
<title>古老神奇的<table></title>
<link>https://www.scarsu.com/ancient_magical_table/</link>
<guid isPermaLink="true">https://www.scarsu.com/ancient_magical_table/</guid>
<description>凭什么table能兼容IE6?</description>
<pubDate>Wed, 29 Aug 2018 00:00:00 GMT</pubDate>
<content:encoded><h1>结构</h1> <pre><code>&lt;table&gt; &lt;caption&gt;表格上方的居中标题&lt;/caption&gt; &lt;colgroup&gt; &lt;col span="2" style=""&gt; &lt;col style=""&gt; &lt;/colgroup&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;ISBN&lt;/th&gt; &lt;th&gt;Title&lt;/th&gt; &lt;th&gt;Price&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tody&gt; &lt;tr&gt; &lt;td&gt;3476896&lt;/td&gt; &lt;td&gt;My first HTML&lt;/td&gt; &lt;td&gt;$53&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;tfoot&gt; &lt;tr&gt; &lt;td&gt;3476896&lt;/td&gt; &lt;td&gt;My first HTML&lt;/td&gt; &lt;td&gt;$53&lt;/td&gt; &lt;/tr&gt; &lt;/tfoot&gt; &lt;/table&gt; </code></pre> <h1>标签</h1> <pre><code>&lt;caption&gt;、&lt;col&gt;、&lt;colgroup&gt;、&lt;thead&gt;、&lt;tfoot&gt; 以及 &lt;tbody&gt; </code></pre> <h1><code>&lt;caption&gt;标题</code></h1> <p>对齐方式:</p> <ul> <li>用 CSS 属性 "text-align" 和 "caption-side"</li> <li>caption-side 只有 top 和 bootom 两个,即位于表格上方或下方</li> <li>用 text-align 来控制左右位置</li> </ul> <p>无其他属性(HTML4.01 的 align 属性被 HTML5 删除)</p> <h1><code>&lt;colgroup&gt;</code> 和 <code>&lt;col&gt;</code> :对列进行组合</h1> <p>对列进行组合</p> <p>span 属性:定义横跨的列数,无 span 属性默认为 1(类似于 td 的 colspan 属性)</p> <p>无其他属性(表示样式的 HTML4.01 属性均被 HTML5 删除)</p> <h1><code>&lt;thead&gt; &lt;tbody&gt; &lt;tfoot&gt;</code></h1> <p>无属性(样式属性被 HTML5 删除)</p> <p>默认不会影响表格的样式布局</p> <p>优点:</p> <ul> <li>使浏览器有能力支持独立于表格表头和表格页脚的表格主体滚动。</li> <li>当包含多个页面的长的表格被打印时,表格的表头和页脚可被打印在包含表格数据的每张页面上。</li> <li>可以方便的定义 三部分 的样式</li> </ul> <h1><code>&lt;table&gt;</code></h1> <p>属性:border=1 或"" 规定是否有边框</p> <p>无其他属性(表示样式的 HTML4.01 属性均被 HTML5 删除)</p> <h1>表格行:<code>&lt;tr&gt;</code></h1> <p>无属性(表示样式的 HTML4.01 属性均被 HTML5 删除)</p> <h1>单元格:<code>&lt;td&gt;</code> 和 <code>&lt;th&gt;</code></h1> <p>差异</p> <ul> <li>th:文本粗体,居中</li> <li>td:文本普通,左对齐</li> </ul> <p>属性</p> <ul> <li>colspan:横跨的列数</li> <li>rowspan:横跨的行数</li> <li>headers:header_id 单元格关联的一个或多个表头单元格</li> <li>无其他属性(表示样式的 HTML4.01 属性均被 HTML5 删除)</li> </ul> <p>自动居中</p> <ul> <li>如果给 td 定义了尺寸,且子元素的尺寸小于 td 尺寸,子元素会自动垂直居中</li> <li>居中后子元素与 td 的边距,不属于 td 的 padding 值,也不属于子元素的 margin 值</li> <li>IE6 居中随便写,写不出来算我输</li> </ul> <h1>CSS 属性:border-collapse</h1> <p>默认情况:单元格之间有间隔隔开,border-collapse:separate</p> <p>一般不需要隔开:</p> <pre><code>table { border-collapse: collapse; } </code></pre> <hr /> <pre><code>"你大爷还是你大爷" </code></pre> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/ancient_magical_table/#post-comment/</comments>
</item>
<item>
<title>用chrome调试node.js服务端代码</title>
<link>https://www.scarsu.com/debug_nodejs_with_chrome/</link>
<guid isPermaLink="true">https://www.scarsu.com/debug_nodejs_with_chrome/</guid>
<description>不然你想用什么调试?</description>
<pubDate>Mon, 30 Jul 2018 00:00:00 GMT</pubDate>
<content:encoded><h3>开启调试命令</h3> <pre><code>node --inspect app.js //在第一行就停下来等待调试,也可以使用 node --inspect-brk app.js </code></pre> <h3>debugger 地址</h3> <pre><code>//运行开启调试命令后,能看到类似如下的输出: Debugger listening on ws://127.0.0.1:9229/4dc825ec-a204-46f8-8edc-4afadc8da61a For help see https://nodejs.org/en/docs/inspector </code></pre> <h3>在 chrome 中打开 debugger</h3> <pre><code>在Chrome中打开chrome://inspect/#devices 点击inspect进入调试界面 </code></pre> <h3>debugger 端口</h3> <p>inspect 调试默认监听 9229 端口,可以通过下面的参数指定端口</p> <pre><code>--inspect=9222 </code></pre> <hr /> <pre><code>用VSC、用webstorm啊 对不起我懒(~﹃~)~zZ </code></pre> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/debug_nodejs_with_chrome/#post-comment/</comments>
</item>
<item>
<title>成熟的一些标志</title>
<link>https://www.scarsu.com/be_mature/</link>
<guid isPermaLink="true">https://www.scarsu.com/be_mature/</guid>
<description>克制欲望、保持一致性、有原则有底线有追求</description>
<pubDate>Mon, 09 Jul 2018 00:00:00 GMT</pubDate>
<content:encoded><blockquote> <p>能克制欲望,不追求即时反馈,延迟享受。</p> <p>保持一致性,无论在人群中还是独处时,知行合一,不卑不亢,不矫揉造作,不哗众取宠。</p> <p>心中始终有底线、有原则、有追求。</p> <p>时刻反省自己:what在做什么、why为什么这样做、how如何做的更好</p> </blockquote> <p>—— 尼古拉斯·鱼</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/be_mature/#post-comment/</comments>
</item>
<item>
<title>No means No</title>
<link>https://www.scarsu.com/no_means_no/</link>
<guid isPermaLink="true">https://www.scarsu.com/no_means_no/</guid>
<description>该表达态度的时候,要明确、干净、利落的表达。</description>
<pubDate>Mon, 09 Jul 2018 00:00:00 GMT</pubDate>
<content:encoded><p>该表达态度的时候,要明确、干净、利落的表达。</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/no_means_no/#post-comment/</comments>
</item>
<item>
<title>不要扮演受害者</title>
<link>https://www.scarsu.com/play_victim/</link>
<guid isPermaLink="true">https://www.scarsu.com/play_victim/</guid>
<description>受害者的防卫机制常常是自我否定,并将自己置于一个道德正确的位置。</description>
<pubDate>Mon, 09 Jul 2018 00:00:00 GMT</pubDate>
<content:encoded><p>责怪、批评与指责是人类防御机制的关键要素。</p> <p>责怪他人、批评他人行为、指责他人不愿改变,其实是一种轻而易举的手段,</p> <p>能够简单地利用道德批判,将自己提升到一个高于他人的位置,也使我们摆脱了自身的不安。</p> <p>然而,责怪、批评与指责的态度最终只会加强自我的受害者意识。</p> <p>受害者常感到无力、无助、无价值且无法自我满足。</p> <p>他们的防卫机制常常是自我否定,并将自己置于一个道德正确的位置。</p> <p><strong>当我们坦然面对内在的受害情绪时,我们将有机会更具有意识地正视这份感觉,并了解这仅是一种感受,而非事实</strong></p> <p>责怪、批评与指责也终将不再发生。</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/play_victim/#post-comment/</comments>
</item>
<item>
<title>学习最原始的驱动力</title>
<link>https://www.scarsu.com/why_learning/</link>
<guid isPermaLink="true">https://www.scarsu.com/why_learning/</guid>
<description>来自于胡适的心得</description>
<pubDate>Mon, 09 Jul 2018 00:00:00 GMT</pubDate>
<content:encoded><p>保持质疑</p> <p>保持好奇心和兴趣</p> <p>保持对努力的自信</p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/why_learning/#post-comment/</comments>
</item>
<item>
<title>认知 | 看电影/阅读的意义是什么?</title>
<link>https://www.scarsu.com/why_reading/</link>
<guid isPermaLink="true">https://www.scarsu.com/why_reading/</guid>
<description>谁看到的维度越多,世界在谁的眼中便越真实。</description>
<pubDate>Mon, 09 Jul 2018 00:00:00 GMT</pubDate>
<content:encoded><blockquote> <p>谁看到的维度越多,世界在谁的眼中便越真实。</p> <p>练习自己感动、愤怒、喜悦、震惊、欢笑、平静的能力 不被苟且的生活捆绑致死。</p> <p>认识这个世界,丰富认知维度。</p> <p>即使生活一平如水、或筋疲力尽、或颠沛流离,仍要感受这个形形色色的世界,满怀希望,拥有细腻的情感。</p> </blockquote> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/why_reading/#post-comment/</comments>
</item>
<item>
<title>关于坚持</title>
<link>https://www.scarsu.com/will_power/</link>
<guid isPermaLink="true">https://www.scarsu.com/will_power/</guid>
<description>短篇</description>
<pubDate>Mon, 09 Jul 2018 00:00:00 GMT</pubDate>
<content:encoded><blockquote> <p>坚持这两个字,远比你想象中的要难的多,但也比你想象中的有效的多。</p> <p>'You do make a difference!'</p> </blockquote> <p><a>@https://www.bilibili.com/video/BV1XJ411d7Xx</a></p> <blockquote> <p>两年,是很容易虚度过去的时长,也是足够改变自己的时长。</p> </blockquote> <p><a>@https://www.bilibili.com/video/BV1NE41197sr</a></p> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/will_power/#post-comment/</comments>
</item>
<item>
<title>FullPage.js</title>
<link>https://www.scarsu.com/fullpagejs/</link>
<guid isPermaLink="true">https://www.scarsu.com/fullpagejs/</guid>
<description>fullPage.js 是一个基于 jQuery 的插件。</description>
<pubDate>Thu, 19 Apr 2018 00:00:00 GMT</pubDate>
<content:encoded><h2>主要功能有:</h2> <ul> <li>支持鼠标滚动</li> <li>支持前进后退和键盘控制</li> <li>多个回调函数</li> <li>支持手机、平板触摸事件</li> <li>支持 CSS3 动画</li> <li>支持窗口缩放</li> <li>窗口缩放时自动调整</li> <li>可设置滚动宽度、背景颜色、滚动速度、 循环选项、回调、文本对齐方式等等</li> </ul> <h2>兼容性</h2> <pre><code>jQuery 兼容: 兼容 jQuery 1.7+。 浏览器兼容: IE8+ ✔ Chrome ✔ Firefox ✔ Opera ✔ Safari ✔ </code></pre> <h2>引入文件</h2> <pre><code>&lt;link rel="stylesheet" href="css/jquery.fullPage.css"&gt; &lt;script src="js/jquery.fullPage.js"&gt;&lt;/script&gt; &lt;script src="js/jquery.min.js"&gt;&lt;/script&gt; &lt;!-- jquery.easings.min.js 用于 easing 参数,也可以使用完整的 jQuery UI 代替,如果不需要设置 easing 参数,可去掉改文件 --&gt; &lt;script src="js/jquery.easings.min.js"&gt;&lt;/script&gt; &lt;!-- 如果 scrollOverflow 设置为 true,则需要引入 jquery.slimscroll.min.js,一般情况下不需要 --&gt; &lt;script src="js/jquery.slimscroll.min.js"&gt;&lt;/script&gt; </code></pre> <h2>HTML</h2> <pre><code> &lt;div id="dowebok"&gt; &lt;div class="section"&gt; &lt;h3&gt;第一屏&lt;/h3&gt; &lt;/div&gt; &lt;div class="section"&gt; &lt;h3&gt;第二屏&lt;/h3&gt; &lt;/div&gt; &lt;div class="section"&gt; &lt;h3&gt;第三屏&lt;/h3&gt; &lt;/div&gt; &lt;div class="section"&gt; &lt;h3&gt;第四屏&lt;/h3&gt; &lt;/div&gt; &lt;/div&gt; 每个 section 代表一屏,默认显示“第一屏”,如果要指定加载页面时显示的“屏幕”,可以在对应的 section 加上 class=”active”,如: &lt;div class="section active"&gt;第三屏&lt;/div&gt; 同时,可以在 section 内加入 slide,如: &lt;div id="dowebok"&gt; &lt;div class="section"&gt;第一屏&lt;/div&gt; &lt;div class="section"&gt;第二屏&lt;/div&gt; &lt;div class="section"&gt; &lt;div class="slide"&gt;第三屏的第一屏&lt;/div&gt; &lt;div class="slide"&gt;第三屏的第二屏&lt;/div&gt; &lt;div class="slide"&gt;第三屏的第三屏&lt;/div&gt; &lt;div class="slide"&gt;第三屏的第四屏&lt;/div&gt; &lt;/div&gt; &lt;div class="section"&gt;第四屏&lt;/div&gt; &lt;/div&gt; ### JavaScript `` $(function(){ $('#dowebok').fullpage(); }); </code></pre> <h2>详细配置见官方文档</h2> <p><a>Fullpage.js-Github</a></p> <hr /> <pre><code>皮不动了... </code></pre> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/fullpagejs/#post-comment/</comments>
</item>
<item>
<title>MongoDB配置</title>
<link>https://www.scarsu.com/mongodb_configuration/</link>
<guid isPermaLink="true">https://www.scarsu.com/mongodb_configuration/</guid>
<description>MongoDB被我选来做毕设的数据库,在此记录配置过程。</description>
<pubDate>Tue, 06 Mar 2018 00:00:00 GMT</pubDate>
<content:encoded><h2>官网下载安装</h2> <pre><code>(我版本3.0.15 [官网下载地址](https://www.mongodb.com/download-center?jmp=nav) </code></pre> <h2>安装路径</h2> <pre><code>将C:\Program Files\MongoDB\Server\3.0\bin(windows下的默认路径)添加到环境变量 即可在任何位置使用 mongo 使用数据库 mongod 开机 mongoimport 导入数据 </code></pre> <h2>新建</h2> <pre><code>C:\data\db路径作为数据库 </code></pre> <h2>开机 cmd 命令:</h2> <pre><code>mongod --dbpath c:\data\db (保持该cmd窗口才能正常运行mongodb) (其他数据操作另外开cmd) --dbpath是选择数据库文档所在文件夹 即,mongodb中数据库有物理文件 </code></pre> <h2>use</h2> <pre><code>use 数据库名字 使用一个数据库 如果想新建数据库,也是use。use一个不存在的,就是新建。 </code></pre> <h2>查看当前所在数据库</h2> <pre><code>db </code></pre> <h2>插入数据</h2> <pre><code>数据库中不能直接插入数据, 只能往集合(collections)中插入数据 db.userid.insert({"id":"zengsuyu","password":"123456789"}); 此处的userid就是集合 </code></pre> <h2>删除当前所在的数据库</h2> <pre><code>db.dropDatabase(); </code></pre> <h2>导入外部 json 数据</h2> <pre><code>用sublime在外部写好json数据库的形式,然后导入数据库: -db 数据库名(选择数据库 --collection 集合名( 选择集合 --drop (把集合清空 --file json文件名(选择要导入的json文件 </code></pre> <h2>查找数据:</h2> <pre><code>db.集合名.find() (列出所有数据 db.集合名.find({"key":"value"}) (精确匹配key为value值的数据 db.集合名.find().sort("") (升降排序 </code></pre> <h2>mongoose</h2> <pre><code>不用直接操作数据库,操作对象,对象自动持久 </code></pre> <ul> <li>连接 Mongo 数据库</li> </ul> <pre><code>var mongoose = require('mongoose'); var db = mongoose.connect('mongodb://localhost/geekChat');//;连接数据库 </code></pre> <ul> <li>监听 open 事件</li> </ul> <pre><code>db.once('open', function (callback) { console.log("数据库成功连接"); }); </code></pre> <ul> <li>创建类</li> </ul> <pre><code>//创建了一个模型。猫的模型。所有的猫,都有名字,是字符串。“类”。 var Cat = mongoose.model('Cat', { name: String }); //实例化一只猫 var kitty = new Cat({ name: 'Zildjian' }); //调用这只猫的save方法,保存这只猫 kitty.save(function (err) { console.log('喵喵喵'); }); </code></pre> <ul> <li>创建模型</li> </ul> <pre><code>var Schema = mongoose.Schema; var userScheMa = new Schema({ name: String, password: String }); // 定义了一个新的模型,但是此模式还未和users集合有关联 exports.user = db.model('user', userScheMa); // 与users集合关联 ref 数据表关联 </code></pre> <hr /> <pre><code>这次不皮了 </code></pre> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/mongodb_configuration/#post-comment/</comments>
</item>
<item>
<title>Animate.css</title>
<link>https://www.scarsu.com/animatecss/</link>
<guid isPermaLink="true">https://www.scarsu.com/animatecss/</guid>
<description>Animate.css是一个来自国外的 CSS3 动画库。</description>
<pubDate>Thu, 01 Feb 2018 00:00:00 GMT</pubDate>
<content:encoded><h2>功能</h2> <ul> <li>它预设了抖动(shake)</li> <li>闪烁(flash)</li> <li>弹跳(bounce)</li> <li>翻转(flip)</li> <li>旋转(rotateIn/rotateOut)</li> <li>淡入淡出(fadeIn/fadeOut)</li> <li>等多达 60 多种动画效果</li> </ul> <h2>浏览器兼容:</h2> <pre><code>只兼容支持 CSS3 animate 属性的浏览器, 分别是:IE10+、Firefox、Chrome、Opera、Safari。 </code></pre> <h2>引入文件</h2> <pre><code>&lt;link rel="stylesheet" href="animate.min.css"&gt; </code></pre> <h2>官网</h2> <pre><code>[Animate.css](https://daneden.github.io/animate.css/) [Github](https://github.com/daneden/animate.css) </code></pre> <h2>使用</h2> <pre><code> &lt;h1 class="animated infinite bounce delay-2s"&gt;Example&lt;/h1&gt; </code></pre> <ul> <li>首先给元素加上 animated 类</li> <li>第二个 infinate 使动画无限播放,可选</li> <li>第三个 bounce 是具体的动画效果名称,<a>全部动效演示</a></li> <li>第四个 delay-2s 是动效延迟播放 2s,可选</li> </ul> <h2>通过 Js,Jq 给元素添加 class:</h2> <pre><code> $(function(){ $('#dowebok').addClass('animated bounce'); }); </code></pre> <h2>更改 animate.css 的默认设置:</h2> <pre><code> #dowebok { animate-duration: 2s; //动画持续时间 animate-delay: 1s; //动画延迟时间 animate-iteration-count: 2; //动画执行次数 } //兼容各种浏览器代码,需要添加各浏览器前缀: #dowebok{ -webkit-animation-duration: 3s; -webkit-animation-delay: 4s; -webkit-animation-iteration-count: 5; -moz-animation-duration: 3s; -moz-animation-delay: 4s; -moz-animation-iteration-count: 5; -o-animation-duration: 3s; -o-animation-delay: 4s; -0-animation-iteration-count: 5; -ms-animation-duration: 3s; -ms-animation-delay: 4s; -ms-animation-iteration-count:5; animation-duration: 3s; animation-delay: 4s; animation-iteration-count: 5; } </code></pre> <h2>动画结束触发函数:</h2> <pre><code> $(".test").click(function(){ $(this).addClass('animated fadeOut'); }); var animateEnd=(function(el){ var animations={ animation:'animationend', OAnimation:'oAnimationEnd', MozAnimation:'mozAnimationEnd' WebktiAnimation:'webkitAnimationEnd' } for(var i in animations){ if(el.style[i]!==undefined){ return animations[i] } } })(document.createElement('div'));//通过任意元素检测浏览器内核类型 $('.test').one(animateEnd, doSomething); //$.one():为元素的特定事件绑定一个一次性的事件处理函数。 </code></pre> <h2>将以上过程整合为 Jq 扩展函数</h2> <pre><code>jq自定义函数 $.fn.extend({ animateCss: function (animationName, callback) { var animationEnd = (function (el) { var animations = { animation: 'animationend', OAnimation: 'oAnimationEnd', MozAnimation: 'mozAnimationEnd', WebkitAnimation: 'webkitAnimationEnd', }; for (var t in animations) { if (el.style[t] !== undefined) { return animations[t]; } } })(document.createElement('div')); this.addClass('animated ' + animationName).one(animationEnd, function () { //某些动画效果执行完后元素不可见又需要这个元素(实际遇过这个问题) //eg.淡出、向左滑动等等, //可能需要将 class 删除 $(this).removeClass('animated ' + animationName); if (typeof callback === 'function') callback(); }); return this; }, }); $('#yourElement').animateCss('bounce'); $('#yourElement').animateCss('bounce', function () { // 事件结束触发的函数 }); </code></pre> <hr /> <pre><code>为什么不自己写动画? 别人比你写的好啊小辣鸡。 </code></pre> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/animatecss/#post-comment/</comments>
</item>
<item>
<title>提高效率的前端工具</title>
<link>https://www.scarsu.com/fe_tools/</link>
<guid isPermaLink="true">https://www.scarsu.com/fe_tools/</guid>
<description>分享一些用的顺手的前端效率工具~</description>
<pubDate>Mon, 01 Jan 2018 00:00:00 GMT</pubDate>
<content:encoded><h4>http-server 本地快速静态资源服务器</h4> <ul> <li>npm 全局安装</li> <li>执行<code>hs</code>命令</li> <li>即可在terminal当前路径创建一个本地http静态资源服务器,方便调试</li> </ul> <h4>nrm npm快速切换国内源</h4> <ul> <li>npm全局安装nrm</li> <li><code>nrm ls</code>命令列出当前可使用的国内npm源,eg. taobao</li> <li><code>nrm use xx</code>即可切换到某一源</li> </ul> <h4>nvm 快速切换node版本</h4> <ul> <li>nvm官网安装</li> <li><code>nvm list</code>列出当前机器已经安装的node版本</li> <li><code>nvm install vxx</code>安装某一版本node</li> <li><code>nvm use</code>切换到某一版本node</li> </ul> <h4>parcel 极简配置版<strong>webpack</strong></h4> <ul> <li>npm全局安装parcel<code>npm i parcel-bundler -g</code></li> <li><code>parcel setup/index.html</code>即可创建一个本地服务器,并构建打包当前html的依赖</li> </ul> <h4>nodemon 热更新</h4> <ul> <li>npm全局安装<code>npm i nodemon -g</code></li> <li><code>nodemon xx.js</code></li> </ul> </content:encoded>
<category>前端</category>
<comments>https://www.scarsu.com/fe_tools/#post-comment/</comments>
</item>
<item>
<title>胡言乱语 | 我与这世界的距离</title>
<link>https://www.scarsu.com/escape_from_the_world/</link>
<guid isPermaLink="true">https://www.scarsu.com/escape_from_the_world/</guid>
<description>一些胡言乱语</description>
<pubDate>Thu, 06 Jun 1996 00:00:00 GMT</pubDate>
<content:encoded><h2>如何与情绪相处</h2> <p>从人性上来说,我们倾向于保护自我最脆弱的部分</p> <p>伤痛、需求未被满足、罪恶、耻辱会激发我们痛苦、恐惧、愤怒的情绪,这是人类天生的保护机制</p> <p>我们无法控制自己的本能,但是应该学会接受、正视、了解我们的感觉和情绪,</p> <p>去发现并解决 情绪背后 激发情绪的问题,而不是去任由情绪发泄</p> <h2>不要扮演受害者</h2> <p>责怪、批评与指责是人类防御机制的关键要素。</p> <p>责怪他人、批评他人行为、指责他人不愿改变,其实是一种轻而易举的手段,</p> <p>能够简单地利用道德批判,将自己提升到一个高于他人的位置,也使我们摆脱了自身的不安。</p> <p>然而,责怪、批评与指责的态度最终只会加强自我的受害者意识。</p> <p>受害者常感到无力、无助、无价值且无法自我满足。</p> <p>他们的防卫机制常常是自我否定,并将自己置于一个道德正确的位置。</p> <p><strong>当我们坦然面对内在的受害情绪时,我们将有机会更具有意识地正视这份感觉,并了解这仅是一种感受,而非事实</strong></p> <p>责怪、批评与指责也终将不再发生。</p> <h2>亲密关系</h2> <p>亲密关系是一种完美设计</p> <p>在亲密关系中,所有的一切都是重要的部分,即使是令人不悦的冲突与不适的情境。</p> <p>当你继续在感情中成长时,你也开始<strong>懂得欣赏你跟伴侣之间所发生的任何事情</strong>。</p> <p>你的伴侣不是你的爱与幸福的来源,满足你的期待与使你开心不是他们的职责。</p> <p>你的伴侣在你的生活中扮演了三个重要的角色:</p> <ul> <li>一面镜子,让你看见引发你关注的不舒服感;</li> <li>一名老师,在你探寻真实自我的时候,激励与启发你;</li> <li>一名“玩伴”,开启并陪伴你一段生命的旅程。</li> </ul> <h2>学习最原始的驱动力</h2> <p>保持质疑</p> <p>保持好奇心和兴趣</p> <p>保持对努力的自信</p> <h2>No means No</h2> <p>该表达态度的时候,要明确、干净、利落的表达。</p> <h2>就是不想努力怎么办</h2> <blockquote> <p>我就想做一个安于现状的人</p> <p>就想利用上班赚钱过好自己的小日子</p> <p>就想平凡的过完一生</p> <p>我就是不想拼命奋斗,拼命努力,拼命内卷</p> <p>不可以吗?</p> </blockquote> <p>当然可以,每个人的追求不同,淡泊名利,平静一生,真正能做到的话,是一种很高的人生境界。</p> <p>但是你做出这种决定,就要考虑其带来的结果</p> <blockquote> <p>你能做到真正的“淡泊名利”吗?</p> <p>当别人用光鲜亮丽的服装、车子、房子包装和提升自己的生活品质时,你能做到不羡慕吗</p> <p>当别人在马尔代夫浮潜、在阿尔卑斯滑雪、在土耳其滑翔、在富士山脚泡温泉喝清酒,你能做到不羡慕吗</p> <p>你身边的人生活品质都比你高得时候,你会不会后悔</p> <p>你的普通收入扣除房子首付、房贷、车子、奶粉钱之后你还足够安稳吗</p> <p>如果不买房,你可以做到一生租房,并容忍一生到老不断的搬家吗</p> <p>你的普通收入能让你匹配上你心仪的另一半吗</p> <p>你的现状能维持你一生的稳定平凡吗?你能对抗人生所有的风险吗</p> <p>你可以为自己的一生、父母后半生、孩子前半生的大大小小的健康问题买单吗</p> <p>如果你有了孩子,你作为爸爸/妈妈,能给孩子最好的教育吗</p> </blockquote> <p>如果你深刻的考虑了这些问题,都能得到坚定的答案,那么安于现状,不拼命努力,也没什么不好</p> <p>每个人的人生都不同,人生的路也没有对错之分,只是路上的酸甜苦辣,你需要独自承担</p> <h2>别让任何人打乱你的人生节奏</h2> <blockquote> <p>每个人的人生都不同</p> <p>"Not everything that counts can be counted,and not everything that's counted truly counts"</p> <p>"并不是每件算出来的事,都有意义;也不是每件有意义的事,都能被算出来" ——爱因斯坦</p> </blockquote> <p><a>@https://www.bilibili.com/video/BV1WW411F7Hx</a></p> <h2>关于坚持</h2> <blockquote> <p>坚持这两个字,远比你想象中的要难的多,但也比你想象中的有效的多。</p> <p>'You do make a difference!'</p> </blockquote> <p><a>@https://www.bilibili.com/video/BV1XJ411d7Xx</a></p> <blockquote> <p>两年,是很容易虚度过去的时长,也是足够改变自己的时长。</p> </blockquote> <p><a>@https://www.bilibili.com/video/BV1NE41197sr</a></p> <h2>如何追求快乐</h2> <blockquote> <p>有很多快乐是放纵的快乐,是降低了人性尊严的快乐,而越能体现人性尊严的快乐,越是一种高级的快乐。</p> <p>追求高级的快乐并不意味着放弃低级的快乐,但是如果你的眼目永远只关注地下,你永远不知道向上看有多么的快乐。</p> </blockquote> <p>——罗翔</p> <p><a>@https://www.bilibili.com/video/BV1AE411T7p7</a></p> <blockquote> <p>I don't need dollar bills to have fun</p> </blockquote> <p>——【Cheap Thrills】 Sia</p> <h2>成熟的一些标志</h2> <blockquote> <p>能克制欲望,不追求即时反馈,延迟享受。</p> <p>保持一致性,无论在人群中还是独处时,知行合一,不卑不亢,不矫揉造作,不哗众取宠。</p> <p>心中始终有底线、有原则、有追求。</p> <p>时刻反省自己:what在做什么、why为什么这样做、how如何做的更好</p> </blockquote> <p>—— 尼古拉斯·鱼</p> <h2>享受平静才是生活的真谛</h2> <blockquote> <p>“上次我去一个朋友家玩,看到他们客厅里摆着一张很长的桌子。朋友说,每到周末,两个大人,一个孩子,还有两只猫都会围在这个桌子旁,家里很安静,只有书页翻动和画笔接触纸张的细微声音。”</p> </blockquote> <h2>看电影/阅读的意义是什么?</h2> <blockquote> <p>谁看到的维度越多,世界在谁的眼中便越真实。</p> <p>练习自己感动、愤怒、喜悦、震惊、欢笑、平静的能力 不被苟且的生活捆绑致死。</p> <p>认识这个世界,丰富认知维度。</p> <p>即使生活一平如水、或筋疲力尽、或颠沛流离,仍要感受这个形形色色的世界,满怀希望,拥有细腻的情感。</p> </blockquote> <h2>子 瓜 犭 虫</h2> <blockquote> <p>稚儿擎瓜柳棚下,细犬逐蝶窄巷中,人间繁华多笑语,惟我空余两鬓风。</p> <p>“孤独”</p> <p>这两个字拆开看,有小孩,有水果,有走兽,有蚊蝇</p> <p>足以撑起一个盛夏傍晚的巷子口,人味十足。</p> <p>夏日的傍晚,你看着空中嗡嗡飞舞的飞虫,不远处的狗摇着尾巴穿巷而过,你手中拿着吃剩下的半块西瓜</p> <p>忽然觉得好像过了半辈子</p> <p>又好像只过了半分钟。</p> </blockquote> <h2>为什么要趁年轻多学习&lt;a rel="nofollow" href="https://www.zhihu.com/question/354919014/answer/906152325"&gt;&lt;i class="fa fa-link"&gt;&lt;/i&gt;原文&lt;/a&gt;</h2> <blockquote> <p><strong>爆炸性压力才能带来爆炸性进步</strong></p> <p>每次我状态低迷的时候,我都会看看这个视频,视频18分钟,如果你懒得看,我简述一下:</p> <p>演讲者是许峰源先生,他出身一个非常贫穷的家庭,整个家庭,靠的是父亲踩着三轮车出去卖豆腐微薄的收入支撑着。</p> <p>这不是一个烂仔逆袭的故事,因为从小看到了生活艰苦的一面,许峰源一直很努力想考上台大法律系,因为成为律师才有高收入,才能改变家庭的现状。</p> <p>不幸的是,在他上大学的时候,父亲却查出了舌癌晚期,只剩一年左右的时间,为了让父亲在临终前看到自己的孩子成才,许峰源用了极短的时间通过了司法考试,成为了一名律师,让父亲看到了自己的律师证,才安然去世。</p> <p>祸不单行,很快许峰源的母亲也查出了患有肺腺癌,一种扩散很迅猛的癌症,为了让母亲有一个安享晚年的环境,许峰源在23岁的时候,毅然辞职创业,白天在律师事务所打拼,晚上做培训,最终让母亲住上了好房子,接受更好的治疗,然后平静地送走了母亲。</p> <p>前半生,许峰源先生为之奋斗的两个对象都走了,迷茫了一阵子之后,他依然没有放弃努力,而是选择了实现自我,成为了一名作家。</p> <p>再烂的牌也得打下去,这就是人生</p> </blockquote> <h2>时光</h2> <blockquote> <p>小时候小时候,夏天穿过山间的风,打在树梢的雨,外婆灶台上的饭香,无奈回忆真的变成了回忆。</p> </blockquote> <h2>《stronger》kelly clarkson</h2> <blockquote> <p>Doesn't mean I'm lonely when I'm alone</p> </blockquote> <h2>《Lolita》</h2> <blockquote> <p>洛丽塔,我生命之光,我欲念之火。我的罪恶,我的灵魂。</p> </blockquote> <h2>《阿甘正传》</h2> <blockquote> <p>life's like a feather</p> </blockquote> <h2>《하루하루》</h2> <blockquote> <p>离开时请不要回头</p> <p>以后活着也不要找我</p> <p>因为爱你</p> <p>没有一丝悔意</p> <p>所以请带着美好的回忆离去</p> </blockquote> <h2>《安娜·卡列尼娜》列夫·托尔斯泰</h2> <blockquote> <p>“幸福的家庭总是相似的,不幸的家庭各有各的不幸。”</p> </blockquote> <h2>阿德勒</h2> <blockquote> <p>“幸运的人一生都被童年治愈,不幸的人一生都在治愈童年。”</p> </blockquote> <h2>二十多岁浅薄的人生的唯一信仰:自律 + 坚持</h2> </content:encoded>
<category>个人成长</category>
<comments>https://www.scarsu.com/escape_from_the_world/#post-comment/</comments>
</item>
</channel>
</rss>