2019 年下半年经历了一家公司从爆发扩张阶段到人员紧缩的阶段,我们团队

2020 年我们可能经历了人类最大的瘟疫,

疫情

在 2019 年,

裸辞

顺丰

来北京之后学到的最重要的一点一定是「输出意识」。在技术论坛里看过的不代表自己理解掌握了,提高这些碎片化知识的转化率需要个人记录和实践,眼睛觉得看到的东西很简单、可是手不这么认为。「输出意识」的具体表现为文档、博客、一段验证性质的代码片段;甚至可以为自己吃过的某道菜和看过的电影和书籍都可以写自己的评价。

感情

恋爱

工作后接触到的业务方向一直是 B 端,基本上写了两年多的 web 页面,主要类型是复杂的 web 中后台系统。实际上业务是千变万化的,自己的学习重点要放在数据流的处理方式、流行框架的工作机制上。一方面要寻求更大的业务挑战,三年是一个槛如果目前的工作环境无法满足自己的需求那么就要考虑跳槽。另一方面探索 low code 这种业务处理模式,类似 uformformRender 的表单处理方案。

合租

08月27日

未来

算法题一般都是有基本的模板和技巧在里面,按照 leetcode 的 tag 功能,从数据结构的角度分为 数组、链表、队列、二叉树、堆;

从基础运用的角度来看分为、排序、查找;从算法思想来看又可以分为分治、贪心、回溯、递归;其中又会有一些代表性的算法、八皇后、最小子串。

链表数组题目:

双指针

快慢指针

例如:leetcode 19 数组类题目遇到针对某点旋转时 还需使用二分法进行排序

例如:leetcode 35

优先队列

例如:leetcode 23

分治算法

例如:leetcode 23、21

最小堆

例如:leetcode 23

分治

分治的要素: 先解决局部 再合成一个整体。

回溯

识别回溯

  1. 有没有解:Find a path to success
  2. 求所有解:Find all paths to success 求所有解的个数 求所有解的具体信息
  3. 求最优解:Find the best path to success

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Backtracking(object):

def backtracking(self, input):

self.res = []

def dfs(input, temp, [index]):
# 边界
if 非法数据:
return

# 终止条件
if len(input) == len(temp):
self.res.append(temp[:])
return

# for循环
for i range(len(input)):
##1. 修改path
temp.append(input[i])
##2. backtracking
dfs(input, temp, [index])
##3. 退回原来状态,恢复path
temp.pop()
# 执行
dfs(input, [], 0)
return self.res

深度搜索与递归的区别

深度搜索经常用递归(recursion)来实现,二者常常同时出现。深度搜索,是逻辑意义上的算法,递归,是一种物理意义上的实现,它和迭代(iteration)是对应的。深度搜索,可以用递归来实现,也可以用栈来实现;而递归,一般总是用来实现深度搜索。可以说,递归一定是深度搜索,深度搜索不一定用递归。

eg:

leetcode 22:给定括号个数,给出所有可能

leetcode 77:给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function generateParenthesis(n) {
const res = [];

function go(l, r, s) { // l: left remaining, r: right remaining
if (l > r) return; // The number of '(' should be always >= ')'

if (l === 0 && r === 0) {
res.push(s);
return;
}

if (l > 0) go(l - 1, r, s + '(');
if (r > 0) go(l, r - 1, s + ')');
}

go(n, n, '');
return res;
}

例如:

全排列

leetcode 21 (merge 2 sorted lists)

leetcode 23 (merge K sorted lists)

leetcode 203

DFS 、动态规划、回溯法、递归之间的关系是什么?

数组排列组合问题——BACKTRACKING

二叉树相关:

求深度

遍历

递归

  • 前序

  • 中序

  • 后序

非递归

深度优先

广度优先

变种

  • 已知中序和后序求前序

翻转

什么是 Click Jacking

本质上是 UI 覆盖攻击的一种,

1
2
3
4
1. Flash 点击劫持
2. 图片覆盖攻击(XSIO)
3. 拖拽劫持,主要用于数据窃取
4. 触屏劫持(TapJacking)

手段

  1. iframe 覆盖,覆盖层 opacity 调为0

  2. 图片覆盖

解决方法

使用一个 Http Header X-Frame-Options。

它有三个可选值。

DENY:浏览器会拒绝当前页面加载任何frame页面;

SAMEORIGIN:frame页面的地址只能为同源域名下的页面;

ALLOW-FROM origin:允许frame加载的页面地址

在传统页面开发中,我们使用 模板引擎 进行页面开发,

类似 lodash.template

1
2
3
4
5
6
import { template } from 'lodash'

const compiler = template('<h1><%= title %></h1>')
const html = compiler({ title: 'My Component' })

document.getElementById('app').innerHTML = html

模板引擎的概念是: 数据 + 模板 => HTML

我们可以看到 compiler ,接受的参数是 html 字符串,渲染出页面,似乎一个函数就是一个组件。

实际上在使用 Vue 或 React 开发时,他们的输出并不是 html 字符串,而是 Virtual Dom

数据 + 模板 => Virtual Dom

以 Vue 为例,一个组件的核心其实是 render 函数,其他内容,像 data、computed、props 都是为 render 函数提供服务的。
render 函数本可以直接生成 html 但却产出了 virtual dom, 借助 snabbdom 的 API 我们可以表达出这个公式。

1
2
3
4
5
6
import { h } from snabbdom

// h 函数用来创建 VNode,组件的产出是 VNode
const MyComponent = props => {
return h('h1', props.title)
}

传统的开发中, 通过将模板引擎直接替换为 html,
可是 virtual dom 毕竟无法直接渲染到浏览器中,把 virtual dom 渲染为 dom 的过程叫做 patch

1
2
3
4
5
6
7
8
9
10
11
12
import { h, init } from 'snabbdom'
// init 方法用来创建 patch 函数
const patch = init([])

const MyComponent = props => {
return h('h1', props.title)
}

// 组件的产出是 VNode
const prevVnode = MyComponent({ title: 'prev' })
// 将 VNode 渲染成真实 DOM
patch(document.getElementById('app'), prevVnode)

数据变更时,组件会产生新的 VNode, 只需要再次调用 patch

1
2
3
4
// 数据变更,产出新的 VNode
const nextVnode = MyComponent({ title: 'next' })
// 通过对比新旧 VNode,高效地渲染真实 DOM
patch(prevVnode, nextVnode)

另外说几点题外话: 为什么需要使用 virtual dom

为什么要通过 virtual dom

曾经一度以为使用 virtual dom 的原因是因为操作 virtual dom 比操作 DOM 的速度快。但其实这是一种错误的认识。

看到 尤雨溪:网上都说操作真实 DOM 慢,但测试结果却比 React 更快,为什么 这个答案的回答可以总结为这几点:

  • 在比较性能的时候,要分清楚初始渲染、小量数据更新、大量数据更新这些不同的场合。
  • 可以渲染到 DOM 以外的 backend,比如 ReactNative。
  • 为函数式的 UI 编程方式打开了大门

本文参考:
hcysun 组件的本质是什么

最近在看一个组件的时候看到了 React.pureComponent,官方文档中对他的描述是

1
由于PureComponent的shouldeComponentUpdate里,实际是对props/state进行了一个浅对比,所以对于嵌套的对象不适用,没办法比较出来。

shallowCopy

在 React 中,shouldComponentUpdate的实现方式为

1
2
3
if (this._compositeType === CompositeTypes.PureClass) {
shouldUpdate = !shallowEqual(prevProps, nextProps) || ! shallowEqual(inst.state, nextState);
}

可以看到 PureComponent 就是对 props 和 state 的前后状态做的一个浅比较。

天赋异禀者通常有机会得到冠军,同时兼具天赋、自律又懂得思考的人则最终会成为传奇。

2012年开夏,肯尼亚国家队的奥运选拨赛,埃鲁德·基普乔格5000米和万米都位列第7。连续第三次参加奥运的愿望落空了。

那年他27岁。

彻底无缘伦敦后,基普乔格很快做了个决定,转项更长距离的路跑。也就是马拉松。

职业运动员的27岁,一小撮人准备好了大张旗鼓的收获,绝大多数人却要逐渐开始面对压力和焦虑的双重危机。这个年纪,潜力渐行渐远,兑现不出亮眼的成绩,留给职业生涯下半场的时间越来越少。

截止那时,基普乔格最能拿出手的荣誉:

03年世锦赛冠军;

04年雅典奥运铜牌;

08年北京奥运会银牌;

他主项5000米,兼跑越野和10000米。放眼东非,特别肯尼亚和埃塞俄比亚,长跑就是“国粹级”运动,如同乒乓球之于中国一样。非长跑强国的职业运动员,丢到肯尼亚未必能稳赢当地高中生。

除了奥运会和世锦赛,在当地,其它低级别赛事的冠军多如牛毛。当地人提到长跑言必称冠军。能阻碍他们的,一个是激烈的内部竞争,另一个对他们来说,出去跑比赛依然不是件容易的事。

27岁时的基普乔格算得上是位好好先生,低调谦逊,不缺努力。他的职业生涯开头很耀眼,17岁打破世界青少年纪录,而后拿下世锦赛冠军,惊为天人。首都内罗毕很快以他名字命名了一条街道,来纪念天才少年的诞生。

此后十年间,基普乔格的表现不能算不出色,但距离曾经的期望值似乎还差点意思。所有年少成名者,身上都有类似的困扰

名义上,别人视你为乔丹的接班人,事实却是,如果无法达到科比的成就,你的职业生涯都很难被认为是成功的。

又好比,论实力,基普乔格已经达到布洛阿特峰、希夏邦马峰之类的高度,但绝大多数人提起世界最高峰,只说得出珠穆朗玛。知道乔戈里峰的都寥寥。

82年的贝克勒和84年的基普乔格,两人在跑道上对抗了生涯的上半场,下半场都转向公路。两位近十年最伟大的长跑者,也完美错开了高光项目

2.

职业的马拉松选手大多分两类,一类早早就确定以马拉松为主项,平时偶尔跑个5000/万米比赛;另一类则出身更短距离的中长跑。生涯末年油箱还是满的,加速却慢慢变的吃力,所以就打个方向,把赛场从跑道转向公路。

基普乔格之前,马拉松的“GOAT(Greatest of all time)”,海尔·格布雷西拉西耶,就是后一类的代表。

「长跑之王」格布雷西拉西耶有着完美的职业生涯。事后看,贝克勒继承了他中长跑的衣钵,基普乔格则无缝衔接马拉松最强者名号。

和绝大多数人一样, 基普乔格首次亮相的是半程马拉松。2012年9月,他延续了自己惊艳亮相的传统,在里尔半马以季军完赛。59分25秒的成绩也是有史以来首次跑半马第二快的。不到一个月后的世界半马锦标赛,基普乔格又以第六名完赛。

3个月后,在巴萨罗那跑完第三个半程,基普乔格的“热身”正式结束,即将迎来自己的首个全程马拉松。

基普乔格的教练是帕特里克·桑,在“选择哪场比赛作为首马”时,两人看法不同。基普乔格收到伦敦马拉松组委会的邀约,更想跑伦敦。桑却倾向去德国汉堡,即便远不如前者的名头响亮。

桑是基普乔格的第一任教练,也是迄今唯一一位。他年轻时也是运动员,92年巴塞罗那奥运会拿到过银牌。相比运动生涯,他最大成就是慧眼识才,当了教练带出过杰弗里·卡姆沃罗、斯蒂芬·基普罗蒂奇(伦敦奥运会冠军)这些顶尖高手。

帕特里克·桑和基普乔格住的不远。桑拿到奥运会银牌给基普乔格很大激励发,他给桑写了封信,询问是否可以为自己做一份训练计划。而后两人几次交流,便成为师徒,一晃二十年。

基普乔格出身单亲家庭,父亲只是照片里的模糊剪影。十几岁跟了桑后,多少也在他身上寄托了类似父亲的情感。两人相差20岁,亦师亦友。

桑并不是那种严苛的管理者,也从不觉得天赋能决定一切。他认为,“心理素质要比身体素质更重要。(肯尼亚)从不缺才华横溢的苗子,只有心理强大的人才会走的很远。”想必当年相中基普乔格,桑在他身上发现了些其它孩子没有的特质。

桑见证过基普乔格年轻时候一飞冲天,也明白长期被其他人压制是什么滋味。基普乔格换项的选择,帕特里克·桑显然也很支持。对于首马,师徒两人关在房间聊了整整两个小时。“马拉松是个新的领域,你得学习更多东西。”这些是桑摆在明面的话。实际上,桑希望基普乔格能以旗开得胜的姿态开始马拉松。

去汉堡成为冠军,和去伦敦拿个名次,两者在心气上完全没法比。用冠军开路,未来就会不一样。

事实证明桑的确眼光独到,基普乔格也不负期望。

在汉堡平坦的公路上,距离终点剩下不到十公里,基普乔格从第一集团突围,越跑越快,2小时05分30秒第一个完赛,并且还打破了赛会纪录。冲线后的基普乔格表现出少有的激动,“我为自己感到骄傲,我喜欢马拉松。”

“没想到我能跑这么快。”

对于首马的成功,基普乔格自己都有些诧异

如果存在另一个平行世界,另一个「基普乔格」会在同一年的伦敦拿到还不错的名次,庆幸换项的抉择并不赖,而后满世界参赛,在职业生涯后期成为一个小有名气的马拉松选手。

好在假设并没有发生。

3.

至此,基普乔格28岁,身上多了「马拉松冠军」这个标签。

“冠军”与“热门选手”的区别,类似“斗战胜佛”与“齐天大圣”。让孙悟空脱胎换骨的并不是去西天路上他又学会多少技能点,而是前后的心境截然不同了。

这听起来有些唯心主义。不过对基普乔格来说,他的生活训练一直规律且认真,很难要求更多一些。他太需要一个冠军证明了。

汉堡过去5个月后,基普乔格第一次跑柏林马拉松。柏林是一个见证奇迹的地方。诞生过11个世界纪录,世界最好的TOP15成绩,有9个在这里。最近16年,马拉松能不能破纪录,都是柏林说了算。

尽管基普桑最终夺冠,也不负众望刷新了世界纪录,人们对亚军基普乔格的期望甚至更高一些。第二场马拉松便实现204,比起新科世界纪录也只慢了42秒。有人开玩笑,难不成基普乔格用了十年时间攒潜力,就是拗劲准备在马拉松大器晚成?

再往后,2014年春季,以速度闻名的鹿特丹马拉松,基普乔格拿到第二个冠军。30岁前夕,又在芝加哥拿下个人第一个WMM(世界马拉松大满贯)的冠军。

跑马拉松的前两年,看得出基普乔格每一步选择堪比教科书,相当的工整。他在比赛频次上非常克制,每年只跑春秋两场比赛,每一次出场背后都意味着完成了一整套的训练计划。赛前采访,别人会说,我期望跑个什么成绩。基普乔格则表示,我的身体状况很好,也没有什么心理压力。

开头两年收获3个冠军,唯一一次没夺冠还是同胞表现逆天破了纪录。成绩另说,光是能沉住气少参赛保训练这点,基普乔格就比很多东非选手难得了。

基普乔格堪称冠军收割机,他也花了几年时间,把冲线时候狰狞的表情变成云淡风轻的微笑

东非盛产长跑好手,尤其高原上的肯尼亚和埃塞俄比亚。贫瘠了数百年加上生活动荡,当地人想改变生活的选择并不多,长跑已经是一个半产业化的途径。这催生出一群到处比赛赢取奖金的“赏金跑者”。

东非的跑步者村落也有不成文的规定,冠军意味着全村人脸上有光,也顺带经济方面得到恩泽改善下生活。

除了金字塔顶端的高手,绝大多数职业长跑运动员都要背负养家糊口的压力。比赛机会对他们而言非常珍贵,签约经纪团队后都会尽可能多的想要参赛。

马拉松吃的毕竟是身体饭,比赛多了,训练难免缺少系统性,名次和成绩向来又很难两全。这也是东非长跑军团过去的一个现象,万神殿里冠军排排坐,却很难选出个公认的带头大哥。

4.

基普乔格和桑能长久合作,训练上的合拍是一方面,在参赛频次方面也几乎没有意见相左过。这点难能可贵。

桑当年在一堆肉眼可见的天赋里相中基普乔格,很重要的原因是,“这孩子表现出很强的求知欲。”基普乔格总喜欢去研究分析跑步更深一层的东西,这种求知也让他变得非常善于思考,同时兼具独立冷静的特质。

即便有过低谷,桑依然认为基普乔格是那种可以达到某些成就的人。

冷静爱思考,训练营的人叫基普乔格“哲学家”;所参加赛事金牌必达,跑步圈内私下叫他“冠军收割机”。2015年,基普乔格终于完成自己第一个伦敦马拉松。这里后来成为他的福地,接下来又两次折桂。同年秋天基普乔格再次选择跑柏林马拉松,并如愿夺冠。

回顾过程,不夸张的讲,在当时那样的情况下还能淡定完赛的,可能也只有基普乔格了。

比赛开始不久他发现自己的鞋垫松动了。而后每一步奔跑,鞋垫就一点点慢慢滑出。后面的整整16公里,两只鞋垫肆无忌惮的抽打脚踝,双脚在鞋子显然也好受不到哪去。桑也跟着紧张了全程。桑不怕基普乔格退赛,他只担心基普乔格会受伤。

然后就这样穿着不合脚的鞋,基普乔格竟然出人意料的跑出自己的PB(个人最好成绩)2小时04分整!当天各大媒体头条照片里,脚下荧光色飞舞的鞋垫很抢镜,基普乔格则淡定的保持着微笑飞奔。

过程跌宕,结局欢喜。

基普乔格证明了自己的专注和冷静足以应对42公里可能出现的任何问题。桑开始意识到,在马拉松这个距离,基普乔格是他所见过最具精神力量的选手——未来或许不是再多拿几个冠军的事了。

媒体们事后细思极恐——换成别人,半遛着鞋垫早该退赛了,基普乔格却差点跑进204。真是神人。

媒体们夸起来都很没节操。有人说,基普乔格是博尔特的「远程版本」。但有人马上反驳,博尔特有他一半自律?

也是从2015年开始,按照WMM(世界马拉松大满贯)的算法,基普乔格拿到最高积分,成为公认的世界马拉松第一人。再往后连续蝉联至今,前无古人。

2016年伦敦马拉松,基普乔格又拿下冠军还有新的赛会纪录,比当时的世界纪录只慢了8秒。双喜临门,已经31岁的他收到确认,将再次代表肯尼亚参加奥运会。

四年前恐怕没有人会想到故事是这样发展的。

27岁转项马拉松后,基普乔格把自己每一次的训练都记在笔记本上,直到今年柏林破纪录,他记满了整整15本。他的训练计划没有与众不同的地方。每个训练日,他用80-90%的能量把计划完成,然后比赛日,用100%的能量输出。

没有伤病,没有压力,身体状态很好。确认了这三点,冠军就是探囊取物。

里约奥运会马拉松成了基普乔格的个人秀。前半程他还收着跑,后半程眼看夺金没什么压力,于是才放开了发力。赛后数据,后半程比前半程快了整整3分钟。

基普乔格以领先第二名多达70秒的优势收获金牌。这也是自1972年以来奥运会马拉松冠亚军的最大差距。

现代奥运会举办以来的不成文传统,马拉松被安排在奥运会的最后一天举行。比赛最后在体育场结束,意在向奥运精神致敬、向这座城市致敬。

四年又四年,基普乔格被视为夺冠热门,也曾看着贝克勒们绝城而去,而自己的国家队大门徐徐关上。在快32岁的时候王者归来,他只是说,每次训练和比赛我都很高兴,“跑步是我的生命。”

5.

2017年,基普乔格正规的马拉松赛只有下半年的柏林,上半年重头戏是Nike的Breaking 2“破二挑战”。Nike组了基普乔格等三人,在意大利蒙扎赛道尝试人类是否能在2小时内跑完42.195公里。

很少有人知道“破二”前,基普乔格和这个挑战的策划团队面对了很大压力。社交媒体上不看好的声音山呼海啸,绝大多数评论认为,人类并不具备挑战成功的可能。即便你是基普乔格。

甚至于,身为教练的桑在挑战开始前几天表现的都非常紧张,设想过很多可能出现的状况。反倒基普乔格则异常的淡定。他充满信心,又不会多说任何一句大话。

塔德塞和德西萨过早的落后既定配速并未给基普乔格太大影响。最终的最终,他只比2小时超出了25秒。

兴许这是最累的一次42.195公里,基普乔格确实拼劲了全力。仔细看直播画面,最后几公里不经意已然流露出咬牙力撑的表情,但加速冲线时,他依然保持着微笑。这是基普乔格的招牌表情,他习惯用轻描淡写的方式去给力求结果的证明者一个答案。

关于破二的结果,基普乔格至始至终没流露出过任何遗憾。他觉得“遗憾是缺乏自律的表现”。以及,“人类的目标并不存在什么极限。”基普乔格后来自己说了个细节,跑完瞬间他忍不住流泪了。正巧当时开始下雨,泪水就得以顺其自然的藏匿起来。

离开蒙扎后,基普乔格回到酒店,独自到旁边公园又慢跑了很久。只属于他一个人的闲暇时刻。

6.

纽约时报已经称基普乔格为“有史以来最伟大的运动员”。他收获很多冠军,还拿到奥运会金牌,也打破了世界纪录。经济状况良好。即便如此,基普乔格依然维持了自己在肯尼亚训练营的生活,条件堪比苦行僧。

营员们住在非常简陋的合住寝室,使用公共的卫生间,自己从井里打水,轮流打扫卫生,手洗每天换洗的训练服装。他们有严格的作息时间表,吃饭睡觉,互相帮助拉伸和按摩。当太阳升起训练营的选手们开始奔跑,野外的泥路尘土飞扬,犹如非洲动物一场小型的迁徙一般。

每个人每天会跑上几十公里,每周跑量则会惊人的超过两百公里。

训练营的生活基普乔格过了整整19年。跑马拉松后,他的生活越发简单。

很长时间,桑和基普乔格的沟通类似于布置/完成作业,“基普乔格是所有人里最认真执行的。他也会请教我很多,告诉我他自己的理解和分析。”室友说他生活的特别有纪录,不管是吃饭还是睡觉,他总非常按时的进行。另外,“总是第一个到训练场。”

马拉松热潮到来后,体育记者们扛着长枪短炮涌入各个“长跑者小镇”,试图挖出些成功的秘籍。最终的结论,基因天赋也好,环境外因也好,都只是已知结果的假设:他们以最适合自己的方式生活训练,最终取得了成功。

分析过基普乔格的人,说他有最适合马拉松的身体素质,但柔韧性却出人意料的差,挺直膝盖,手指居然无法弯腰触碰到脚趾。以及,每天要喝很多加了糖的茶。

他的微笑不是保护色,是分散痛苦的方式。对手们认为基普乔格有种能力,能将马拉松这样一个并不愉悦的过程变得像一场演出一样,很圆满的呈现出来。

在前辈伯纳德·拉加特眼里,基普乔格还是一个很好的演说家,无论赞助商活动或者专访,基普乔格一直都在思考,说出的话,很少有雷同重复的。

33岁,用了5年时间拿到10个马拉松冠军,包括两个月前在柏林马拉松大幅提升的世界纪录;

32岁,尝试了前无古人的破二挑战;

31岁,时隔8年再一次参加奥运,毫无悬念的拿到金牌;

30岁,甩着鞋垫、一脚血泡的夺冠,而立之年成为公认的马拉松第一人;

28岁,拿下人生第一个马拉松冠军;

27岁,站在运动生涯的岔路口,没有浪费太多时间就做出了决定。

可能他觉得,仅仅拽住当下那些是不够的,自己还是得有个不一样的世界?他一直矜矜业业做了所有该做的,不缺天赋,非常的自律,也一直善于思考。属于基普乔格的时代只是没有确定开启日期——但在选择马拉松后,豁然开朗。

于是在职业生涯的下半场,一个个终将发生的故事,也就水银泻地般兑现出来。

文章出处 埃鲁德·基普乔格:成为传奇

当你老了,回顾一生,就会发觉:什么时候出国读书,什么时候决定做第一份职业、何时选定了对象而恋爱、什么时候结婚,其实都是命运的巨变。只是当时站在三岔路口,眼见风云千樯,你作出选择的那一日,在日记上,相当沉闷和平凡,当时还以为是生命中普通的一天。

系统而深入的获取知识

衡量程序员优劣的其中一个维度是基础是否牢固。你想摆脱简单的重复性劳动去负责更重要的模块基础这块是无法避免的。

js 中的 Promise 原理了解 FRP 才能理解的更深入;vue 的 keep-alive 组件使用了 LRU 算法;模板编译 client-server 模型是 web 开发的理论依据, 你对他掌握的如何取决于你自身网络协议的功底;AST (abstract syntax tree) 是编译原理中的理论、对操作系统了解的不够不管你写什么后端语言,也只会是个接口开发人员。

2020 年减少碎片化信息的获取,碎片化信息可以作为一个了解知识的入口但不能直接靠他来提升技能,利用业余时间看书或者线上 MOOC 的方式去系统的获取知识。也是避免 提前工作 ( overworking ) 情况的发生。

过度工作(overworking):劳动者提前透支自己的技能,被工作拖着走,这种情况下主观能动性会收到很大影响。

输出意识

来北京之后学到的最重要的一点一定是「输出意识」。在技术论坛里看过的不代表自己理解掌握了,提高这些碎片化知识的转化率需要个人记录和实践,眼睛觉得看到的东西很简单、可是手不这么认为。「输出意识」的具体表现为文档、博客、一段验证性质的代码片段;甚至可以为自己吃过的某道菜和看过的电影和书籍都可以写自己的评价。

业务

目前自己负责的

工作后接触到的业务方向一直是 B 端,基本上写了两年多的 web 页面,主要类型是复杂的 web 中后台系统。实际上业务是千变万化的,自己的学习重点要放在数据流的处理方式、流行框架的工作机制上。一方面要寻求更大的业务挑战,三年是一个槛如果目前的工作环境无法满足自己的需求那么就要考虑跳槽。另一方面探索 low code 这种业务处理模式,类似 uformformRender 的表单处理方案。

目前不是自己负责的但接触很多的

自己的第一家公司规模比较大,基础技术设施比较完备,所以可以只专心做一个系统甚至一个模块的开发,专注于开发语言本身。来到 Keep 后情况就大不同,年轻公司的基础技术平台建设几乎为零,自己也直接或间接的参与了公司的基础技术平台建设,从 SSO、BFF 代理服务到CI CD 平台、前端研发体系、全链路压测平台、运维体系、复杂工单的流转平台等等。

虚荣指标

虚荣指标对自己目标的达成有一定促进意义,所以 2020 年也给自己定几个虚荣指标督促自己:

1、 每天看书

  • 计划 《SICP》已完成 3 0 页(JavaScript 语言的开发者是 scheme 的狂热粉丝, SICP 曾是很多高校的基础读物,其中使用lisp 的一种方言 scheme 语言来教学, 可以提升对不同编程语言的系统性认识)

2、 学习一门新的编程语言(主要应用在 server)

  • 把 Java Spring Boot 应用在业务中,有条件就做起来。

3、 坚持每周刷题 leetcode

  • 「拳不留手,曲不离口」养家糊口的技能不能怠慢。

4、 github 每月活跃 >= 28 天

  • 纯粹的虚荣指标

5、 坚持写博客,持续输出

  • 可以当作个人的 OKR。

6、减少焦虑、理性看待各种博文。

性能检查 -> 代码层面优化 -> 弱引用
| ^
| |
| |
| |
——-> javascript 对象可达性

垃圾收集

JavaScript具有自动垃圾收集机制。也就是说开发人员无需关心内存使用问题,执行环境会负责管理代码执行过程中使用的内存,找出不再继续使用的变量,然后释放其占用的内存。

我们创建的原始值、函数、对象等都会占用内存,内存的管理是自动的,无形的。在JavaScript中,内存管理最主要的概念是可达性。

他通常有两种方式:
1、标记清除
2、引用记数

可达性

WeakMap 和 WeakSet

WeakMap

WeakMap.set
WeakMap.get
WeakMap.has
WeakMap.delete

  1. 额外的数据

  2. 缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const cache = new WeakMap()

const process = (obj) => {

if (!cache.has(obj)) {
cache.set(obj, obj)
}

return cache.get(obj)
}

let obj1 = {

}

使用 Map 方法:

1
2
3
4
5
6
7
8
9
10
11
12
let john = {
name: "john"
}

let map = new Map()

map.set(john, "...")

john = null

map.get('john')
// ...

共存亡,使用 WeakMap 方法

1
2
3
4
5
let john = {
name: "john"
}

let weakmap = new WeakMap()

可迭代协议和迭代器协议

例子

一个不是自己维护的数据源:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const message  = [
{
id: 1,
name: 'leejiahao',
age: 25
},
{
id: 2,
name: Bob,
age: 23
},
{
id: 3,
name: Steven,
age: 22
}

]

1. 通过JavaScript垃圾回收机制来理解WeakSet/WeakMap中对象的弱引用

2. WeakMap and WeakSet

3. 使用 chrome-devtools Memory 面板

4. Memory leak patterns in JavaScript

5. Fixing memory leaks in web applications

6.理解 WeakMap 的 weak

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×