20190209 日迹 及 不明就里的自我总结

尝试用Egg.js做博客系统,打算是做个管理端,然后再做个静态的前端用API去请求。目前已经撸出来了管理端,但是感觉本末倒置了……做来做去发现开发需求完全等同于“Typecho+Typecho主题”……

年前年后的这段时间老老实实地学了一些东西,也反思了一下为什么很长一段时间都有一种“对任何事情都有想法、感觉很适合自己、但是一旦开始做了之后就很容易知难而退”的感觉,包括前几天又突发奇想感觉自己能想出很多的东西所以很想系统学习素描——最后看了一些《富兰克林自传》之后打消了这个想法——应该只是一时冲动。

前FIS大牛、UC浏览器技术Leader、现全民直播CTO张云龙的GitHub上有一篇很有技术人反思自己的文章一个程序员的成长之路,里面有几句话摘抄到这里:

我把整个职业生涯分三个阶段:
第一阶段,一技之长。就是深耕你的专业技能,你的专业技术。
第二阶段,独立做事。当你的一技之长达到一定深度的时候,需要开始思考如何独立做事。
第三阶段,拥有事业。选择一份使命,带领团队实现它。

永远不要放弃一技之长,没有所谓的转行或者转型,永远坚持你最初的领域,扩充你的外延,最终达成比较全面的能力,所以一技之长是值得你长期信仰的。

看到这些文字之后我消化了很长一段时间。

同样的话在不同阶段的自己眼中是不同的,或许很长时间以前的自己看到这些话会说:“说得好,我选择学习大佬”(然后就玩去了);17年的自己应该会感觉到一些危机感然后Mark一下继续干活;18年的自己应该会表示怀疑并且内心坚信技术并不适合自己。而现在看到这些话,内心毫无波动,只想默默记下来,隔一段时间看看。

总结总结再总结,真正拿出来所有的总结出来做一个统一的总结的话,就是:我每一个事业、每一个“长期计划”、其实都没有存活太长的时间。经常被外行以想法很多夸奖、也经常被家人以XXX方面还挺有天赋夸奖,产生了一种骨子里的自负、发自潜意识的对规则的不认同、以及对世界复杂度的漠视,这种想法可能有很多小镇子里出来的“别人家的孩子”相同,但是我们走出桎梏看见了灯红酒绿闻到了血味铜臭听说了都市传说,崩塌的自我信仰无法再支撑自己的前进步伐的时候,或许会习惯性接受了某一种非理性的客观存在,将自己安置在一个已经既定存在的角色中,感觉更安稳舒坦、对未来有了信仰,然后等下一次崩塌之后再次依照此法重建,无限轮回到自己和自己的下一代身上,就淡忘了自己的初衷、为什么来到这样的世界、当初的自己如何厌恶现在的自己。

自认为做技术的人在这种轮回中会稍微清醒一些,行业的特性导致自己身处在任何环境都有一定的搜索能力、也有很多有趣的形形色色的云社交圈子,这些其他的力量时不时会将自己从非理性中唤醒,就像耄耋老头不再相信楼下小张卖的床垫能延年益寿一样地顿悟:啊,我在做什么?

记得听谁说过一句很有意思的话,“工程师是这个世界上最公平的职业,因为你仅凭努力就可以走得很高很远,如果你还觉得你天赋不足,可能是你的努力没有到位。”从前认为这句鸡血良言是如此扎心,现在感觉眼界和见识对硬技能影响是这样的严肃恐怖。我2014年知道了前端工程化这个概念,2016年第一次全职工作,但是2019年大年初二才清楚原来大厂在2014年就已经做了非常多非常完善的工程化了、而且在几年内的那么多种解决方案我一无所知;计算机基础薄弱在小公司完全不会体现出有什么问题,因为应用层靠搜索和文档阅读已经能解决大半部分的问题,不过真正的技术大佬们正在每天Review别人的新作、生啃主流框架的源码,且愈加熟练高效。那句很有意思的话,我感觉可以改一点点:

工程师是这个世界上最公平的职业,因为你仅凭努力就可以走得很高很远。如果你还觉得你天赋不足且已经很努力了,不如尝试打开自己的窗子尝试和那些上面的人建立链接。

工程师最好玩的就是,很有可能我们终自己一生都找不到终极,永远有向上的力量和方向在指引。所以我卸载了炉石放弃了在这个暂时还没有工作的节骨眼上去学素描,2019希望能找到一个能够苟且的环境继续磨炼自己,同时做一些真正能够在自己立命之本上扎根的学习,也要去挽回自己当时退学造成的巨量影响,等何时能够和同龄人站在同一起跑线上的时候,再回头看看离这些文字落下的一瞬已经隔了几年之久,我是否已经能够独立存活、养家糊口,是否真正理解了谦卑和静默的意义,以及我的博客是否已经用上了自己此刻挖了坑的Typecho主题。

20190119 日迹

这段时间在找工作啦。

重新梳理了下自己的生活,发现之所以在2018欠下N多的债务,无非是因为贪婪的意识作祟,一直妄图有一步登天一样的效率来进行第一桶金的积累,结果正是被人顺着这种想法一直牵着走。

欲望是没有终止的,不管自己身处何处、身边何人给予肯定、当下有何种积累等,都无一例外地要把自己放到最客观的位置看待。经常有人说回归初心,我认为回归初心就是尝试用几年前那个自己来看待自己。在2018的困顿期,我一直果断地认为之前的我太过愚蠢、对利益无所算计,反而是在2018年对利益斤斤计较的我失去的更多。

这个2018年,涉足过灰色地带,冒出过大量的空手套白狼的想法,甚至有几次险些彻底违背本心和法律去做一些奇葩勾当,好在自己身边有个靠谱的人拉住了自己,没有一脚踏进深渊无法回头。很多次在想、在讨论怎样通过操作来得到一些政策上的补贴,口头上讲的是拿到了补贴可以用于事业发展,其实本心想的无非是回收成本、行为变现,这种想法本身就是危险的。

如今要做的事情,就是找到工作,老老实实做一些靠谱的事情,回到2017之前那种心态,真心把力量放到硬本领的提升和沉淀里,做长期的规划,认同现在的生活,寻找更健康更透明的前方。

很想对自己说一句,好久不见。

翻译:《5分钟入手React.js》

原文地址:[Learn React.js in 5 minutes](https://medium.freecodecamp.org/learn-react-js-in-5-minutes-526472d292f4)。
因为想撸一撸 React ,寻思着直接伸手应该比较愉快,就顺便翻译一篇国外的入门好啦。

5分钟入手 React.js ———— 超热门JavaScript库的快速指南

在这篇教程中,你会通过构建一个超简单小应用的方式对于 React.js 有一个基本的理解,我会把其中我个人认为不是特别核心的知识点暂且抛去不谈哈。

当你阅读这篇文章的时候,你也可以点击链接看一下发布在Scrimba的免费React课程,在那你可以通过48个互动视频来相对完整地学习这个库。

废话少说,整!

基础配置

刚开始使用React的时候,我们应该尽量使用最简单的配置来上手:比如像这样只是用<script />标签引入了ReactReactDOM的简单HTML文件:

    <html>
    <head>
    <script src="https://cdn.bootcss.com/react/15.5.4/react.min.js"></script>
    <script src="https://cdn.bootcss.com/react/15.5.4/react-dom.min.js"></script>
    <script src="https://cdn.bootcss.com/babel-standalone/6.15.0/babel.min.js"></script>
    </head>
    <body>
        <div id="root"></div>
        <script type="text/babel">
        
        /* 
        在此处写入React相关代码
        */
        
        </script>
    </body>
    </html>

译者:原作者使用的免费CDN加速是https://unpkg.com/,为了符合国情我全部替换成了https://www.bootcdn.cn/的同类文件,代码可以放心复制~

同时我们引入了Babel,因为我们在React相关代码中要使用一些用JSX语法来描述HTML内容的部分,此时我们需要将JSX来转化成普通的JavaScript,这样浏览器才能正常解析这段程序。

这里有两个地方需要注意一下:

  • 一个是我们标记了#root这个id的<div />标签。它是我们整个应用的根节点,我们程序的编译结果将出现在这个标签中;
  • 还有<script type="text/babel"></script>这个标签。这个标签是我们将要编写React.js代码的地方。

如果你想实验这段代码,可以查看Scrimba playground

译者:除了Scrimba网站,可以根据2016年10月的这篇文章了解下其他的在线编辑器以及特点。

组件

在React的世界里,一切都是组件,组件通常继承于一个JavaScript类。你可以通过继承React.Component类来创建组件,如下代码所示,我们来创建一个名为“Hello”的组件。

class Hello extends React.Component {
    render() {
        return <h1>Hello world!</h1>;
    }
}

然后,我们可以定义组件的方法,不过我们的示例中只定义了一个render()方法。

render()方法中我们返回了一串希望React渲染到页面中的HTML代码,我们想让React把<h1>Hello world!</h1>代码渲染到根节点中。

然后我们调用ReactDOM.render()来给我们的小应用进行DOM渲染:

ReactDOM.render(
    <Hello />, 
    document.getElementById("root")
);

这段代码是我们让根节点与Hello组件产生关联的关键,结果请点击链接查看。

译者:点击这个CodePen地址查看这个例子。

刚刚出现的与HTML语法很相似的<Hello />就是我们刚刚提到的JSX。它并不是HTML,但是最终会转换成HTML来渲染。

下一步我们来学习数据绑定。

数据绑定

在React中有两种数据:Props 以及 State。最开始我们或许比较难以理解这两者的区别,不用太担心,在开始使用它们之后你就会更容易理解它们的具体意义。

State也可以称之为状态,它是组件所私有的、可以在组件内部修改的;而Props是外部传入的,不受组件本身控制。Props从可以控制数据的高层组件向低层组件传递。

一个组件可以直接地修改它的State,而不能直接修改它被传入的Props。

我们先看一下Props。

Props

我们的“Hello”组件是一个非常基础的组件,它无论如何渲染都智慧渲染出相同的数据。React中一个很重要的部分就是它的复用性,也就是说你可以只编写一次组件、却在各种不同的时候调用它——比如显示不同的信息。

为了给刚刚的组件增加复用性,我们来为它添加 Props 。下面的message="my friend"就是你使用 Props 将数据传递给组件的方式:

ReactDOM.render(
    <Hello message="老铁" />, 
    document.getElementById("root")
);

这个被命名为“message”的prop我们为他赋值为“老铁”,我们在组件内使用this.props.message的语法来调用它:

class Hello extends React.Component {
    render() {
        return <h1>Hello {this.props.message}!</h1>;
    }
}

结果请点击链接查看。

译者:点击这个CodePen地址查看这个例子。

我们在代码中用一个大括号来包裹了{this.props.message}代码,这个大括号是用来进行转义操作的,它来标识这段大括号中的JSX为JavaScript表达式。

那么我们现在就有一个可以复用的组件了,它可以让我们给任何宾语喊“Hello”!真牛逼!

那我们该怎么让组件能够拥有自己修改数据的能力呢?那就要使用State了!

State

State是React中的另一种数据形式,它可以在组件内部由组件自己来直接修改,不需要外部传入。

所以你如果需要组件内部能够通过用户交互等形式让数据产生变化,你就需要把它存在组件的State里。

初始化状态

为了将状态进行初始化,我们需要在组件的constructor()方法中简单设置一下this.state参数。在我们的例子中,我们依然是只设置一个“message”属性。

class Hello extends React.Component {
    
    constructor(){
        super();
        this.state = {
            message: "State中的Message"
        };
    }
    
    render() {
        return <h1>Hello {this.state.message}!</h1>;
    }
}

在我们设置State的具体属性的时候,我们需要先在constructor(){}中调用super()方法,只有这样才能在继承父类的子类中正确获取到类型的this

更新 State 中的数据

想要修改State里面的值,最简单的做法是调用this.setState(),并把要更新的值放置其中。下面我们在组件中定义一个updateMessage()方法来更新数据。

class Hello extends React.Component {
    
    constructor(){
        super();
        this.state = {
            message: "State中的Message"
        };
        this.updateMessage = this.updateMessage.bind(this);
   }
    updateMessage() {
        this.setState({
            message: "更新过的State中的Message"
        });
    }    
    render() {
        return <h1>Hello {this.state.message}!</h1>;
    }
}

这个时候要注意一下,我们在updateMessage()中胡作非为的时候,必须要确认this已经绑定到了组件方法中,不然我们无法访问到正确的this

下一步我们在render()中创建一个点击后就能触发updateMessage()的按钮:

render() {
  return (
     <div>
       <h1>Hello {this.state.message}!</h1>
       <button onClick={this.updateMessage}>点我更新State!</button>
     </div>   
  )
}

这样我们就在按钮上挂了一个事件监听器,来监听onClick事件。当事件触发时,组件就会调用updateMessage()方法。如下为完整组件代码:

class Hello extends React.Component {
    
    constructor(){
        super();
        this.state = {
            message: "State中的Message"
        };
        this.updateMessage = this.updateMessage.bind(this);
   }
    updateMessage() {
        this.setState({
            message: "更新过的State中的Message"
        });
    }    
    render() {
        return (
         <div>
           <h1>Hello {this.state.message}!</h1>
           <button onClick={this.updateMessage}>点我更新State!</button>
         </div>   
        )
    }
}

点击按钮后,updateMessage()方法就会调用this.setState(),并通过传值来修改其中的this.state.message。点击之后的效果点击链接查看。

译者:点击这个CodePen地址查看这个例子。

恭喜你!你已经对于React中比较重要的概念有了一个基本的认识啦!

译者:后面作者的感叹、广告、自我介绍都不翻译了,在DocsChina也有类似的React快速入门的中文文档,需要的小伙伴可以自取。

Fiftone

前段时间在博客给自己标了一个新的名字,伍时壹,终于满足了自己中二的期冀。
于是在博客也写了一句:闲情择月 不如心散无常。
赶上今天在阿里的语雀上注册账号建库,就想起了这句,就给闲情择月两句配了文,居然感觉回到了八九年前的时候,内心洋溢出一股莫名其妙的青涩。

信笔轻言闲情事,溯誉尝究择月光;
清植溉荟求心散,黄道飞星录无常;
卸甲无人以为伍,却已笑谈止惶张;
任尔来去度几时,壹品黑茶暖未央。

或许男人,多少都会有一点仿佛是个诗人的时候吧。

倒计时功能在JavaScript实现中的毫秒级时间差调试及思考

在一个脑洞里有个倒计时功能,正在想怎么实现,突然想起一个很关键的问题:

之前一些应用场景的倒计时中我使用了 setTimeout 进行递归处理,setTimeout 和 setInterval 一定是有效率区别的,区别有多大?

然后做一个尝试:

先定义提示方法

function timer(id){ console.timeEnd(id); console.time(id); setTimeout('timer("'+id+'")',1000); }

首先定义一下setTimeout的循环计时器。

function timer2(id){ console.timeEnd(id); console.time(id); }

然后定义一下setInterval中循环的方法。

启动!

timer('setTimeout'); setInterval('timer2("interval")',1000)

五年过去了……

如图所示:
运行截图

根据图上打印的日志情况可以粗略猜到了,setInterval计时1000的时候如果因为机器性能等影响到的时候(我在测试的过程中左右切换应用和进行了其他操作),会自己进行一些调节性的操作,很鸡贼;setTimeout就很憨厚了,踏踏实实计时,一次做慢了无所谓下次该咋样还咋样,这种着眼现实的精神很值得我们学习(鼓掌)。

深入一步

刚刚的毕竟是猜测,我们可以继续去研究下它的更向下一些的原理。首先刚刚的demo就不是特别完善,于是我又参考 StackOverflow 的一个回答优化了下撸了另一个可视化程度比较好的 点击查看demo,有兴趣的小伙伴可以点击去看一下。

测试的结果和之前是一样的,都是interval出现了“效率更高一点”的样子。

然后在JavaScriptInfo上查了下资料,资料中显示了如下两张图:

jsinfo-pic1

此图为setInterval(function_name,100)的执行图,

jsinfo-pic2

此图为setTimeout(function() {...}, 100);的递归执行图。

这里给的解释说明了几个事情:

  • 两个计时器时间上的准确是没有问题的,也不存在合理微小延迟的说法
  • setInterval的计时器触发后即刻开始下次计时,setTimeout的计时器触发后到递归到下次计时之间涉及了业务代码的执行周期,所以相对而言会体现出“用时更长”的感觉

看到这里方才明白,并不是setTimeout有延迟,而是在demo中我忽略掉了两个计时器使用后业务代码的执行时间。

应用

如上所述,两种计时器的差别就在于业务代码执行周期产生的延迟了,也就是说并不是setTimeout不准确,只是他们的用途不完全相同。

在应用过程中,使用其中哪个计时器,要取决于我们的业务代码执行周期何如。比如业务代码运算量极其小、或者只是作为本地监听器,用setInterval会更好用一些;如果业务代码执行周期较长,如定期提交用户操作信息,每次执行过程可能会突然出现执行时间超出计时器本身计时周期的情况,用setTimeout显然更稳妥也更合适。

所以说,还是放弃Baidu,健康搜索吧。