利用番茄工作法和子弹笔记管理时间

番茄工作法

  • 1个番茄时钟共有30分钟 25分钟工作时间+5分钟休息时间
  • 4个番茄时钟后休息15-30分钟
  • 4个番茄时钟内不可以中断,如果其中一个中断了,就要作废

子弹笔记

第一步 做计划

首先计划好1天中要做的事情
计划要做到很细,比如一本书要分成读完哪几章,又或者说,一个PPT要做完几页
根据优先级的顺序把重要并紧急的任务放到今日待办中

重要并紧急 必做
重要不紧急 做完必做的任务后有时间再做
不重要紧急 不做
不重要不紧急 不做

第二步 设定番茄时钟

记录好每一项子任务需要的番茄时钟数量,最后统计处一天总共用了多少个番茄时钟

第三步 做复盘记录

记录好每天的任务完成情况,比如每个任务用的番茄数量

第四步 分析

哪些任务用的番茄多,哪些用的少,是否有提升空间

第五 可视化

使用图标的方式分析以往的数据,更直观

如何阅读

核心概念

  • 阅读的层次
  • 书籍的分类
  • 心智和成长

第一章 阅读的艺术

知道和理解的区别 – 阅读的目标是为了获得咨询还是为了增进理解?

真正的阅读 — 是仅凭一己之力将书中的概念,从模糊到更清楚理解的一个过程。阅读也是一种理解能力的挑战。

学习 — 是指理解更多的东西,而不是记住更多咨询

指导型学习 — 可以理解为一种辅助型的学习,老师帮助和引导学生进行自我学习。就像医生辅助病人自我康复和农民辅助植物自我生长。

思考 — 主动和被动学习都需要思考,不过主动学习的时候思考的要更多一些。

老师可以直接回答你的问题,而书本不会,需要你自己去寻找答案,就像面对这个世界一样,很多事情需要你自己去寻找答案,老师不会一直都在,所以提升自我学习的能力就是本书的目的。

第二章 阅读的层次

为什么叫层次而不是种类?因为层次是渐进式的。

1. 基础阅读 — 理解为技术性阅读,是否认识那些文字及阅读速度。

2. 检视阅读 — 也叫略读,快速了解本书的类型和重点,比如先看一下章节目录。

3. 分析阅读 — 精读。增进理解和咀嚼消化一本书。本书的重点就是如何进行分析阅读,比如通过问题的方式。

4. 主题阅读 — 也叫比较阅读,读很多相关的书,找到本书的相同及不同之处。最终可以提出一个所有书里都没提出的概念。成为这个领域专家有自己的创新。

第三章 第一层:基础阅读

孩子可能在高中之前都是处于基础阅读的阶段,一般都有位老师在旁边辅助回答一些问题。
所以这个阶段算不上真正的阅读者。

第四章 第二层 检视阅读

首先需要了解这本书是否值的去阅读
一小时内翻阅序章,目录,索引,作者简介。看几页感兴趣的章节。

阅读一本难书的时候,可以跳过不理解的部分,现有个整体认识。
阅读速度要根据目标内容而变化。

在每行字句下快速滑动手指,引导目光的焦点来锻炼阅读的能力,同时也能增加集中力。

第五章 如何做一个自我要求的读者

阅读的核心就是提出问题
主题是什么 找到主题和次要问题
细节 每个概念
有道理吗?
跟你有什么关系?

如何学习

通过问题的形式使用赛博学习法

一、赛博学习法的12个问题

  1. 主要目的 — 有目的才能抓重点提升效率
  2. 写下已知内容 — 知道会什么也就知道了不会什么
  3. 主要内容 — 先有个整体了解看简介和目录然后再整体和细节之间来回穿梭
  4. 预测后面的内容 — 与作者互动,预测是否正确不是重点,而是保持清醒
  5. 抓专业知识 —  5个导读问题帮助更好的理解内容
  6. 提问 — 提出开放式问题帮助你更好的思考,最好的两类问题是假设和联想,能让大脑思考的是提问题而不是做答案
  7. 要点 — 必须要知道重点是什么,有主次之分
  8. 简短总结 — 也是抓住重点的一种方式
  9. 组织和关联 — 形成自己的思维理解方式
  10. 用图表分析 — 加深巩固
  11. 记忆点 — 提炼一些点用于帮助记忆
  12. 新旧知识关联 — 通过联想的方式加深印象

二、关于听课的优缺点

听课相对与自己阅读优点是老师已经吧重点组织好了,缺点是速度是老师控制的,容易跟不上。

关于听课的建议

  1. 预习
  2. 表现出认真的态度
  3. 把问题先记下来,如果老师后面没讲再找机会提问
  4. 记2份笔记 – 把自己的阅读笔记和上课笔记合并起来

三、理解是学习的本质

判断是否理解了xx的方法:

  1. 定义
  2. 举例
  3. 联想

四、总结

学校最应该教的应该是让学生获得独立思考的能力,而不是知识的灌输。

Generator函数设计的意思重点是把异步操作放到yeild表达式中,等调用next之后再执行,也是解决回调地狱的一种方案,其实后面es7的async await更好

生成器函数最基本的用法

// 定义个生成器函数,一般会在function后面加上一个星号来表示
let foo = function* () {
    for (let i = 0; i < 3; i++) {
        yield i
    }
}
// 将生成器函数肤质给一个变量,注意此时生成器函数内部的for循环并不会执行,可以在yield i 上面打印个log测试一下
let f = foo()
// 调用f下的next()方法,最后一次因为循环结束,所以没有值被返回
console.log(f.next()) // {value:0, done:false}
console.log(f.next()) // {value:1, done:false}
console.log(f.next()) // {value:2, done:false}
console.log(f.next()) // {value:undefined, done:true}

Generator不能被当做构造函数的方式被使用,换句话说就是不能被new,会报错foo is not a constructor
yield 关键字只能在Generator函数内部使用。例如将上面的for循环改成forEach则会因为作用域的问题报错

一个最典型的应用场景,写一个函数用来生成7得倍数

function* gen(i = 0) {
    while (true) {
        if (i % 7 === 0) {
            yield i
        }
        i++
    }
}
let g = gen()
console.log(g.next()) // 0
console.log(g.next()) // 7
console.log(g.next()) // 14

应用场景2:解决ajax的回调地狱。
例如有三个接口有依赖关系,常规的写法是嵌套的方式把下一个接口写到回调函数中,使用生成器可以用下面这种写法

function request(url,data = 0) {
    // 使用setTimeout来比喻ajax
    setTimeout(function () { 
        reportData.next(data + 1) // 每次都根据上一次的返回结果去请求下一个接口
    }, 1000)
}

function* gen() {
    let res1 = yield request('api/1')
    console.log(res1) // 1
    let res2 = yield request('api/2',res1)
    console.log(res2) // 2
    let res3 = yield request('api/3',res2)
    console.log(res3) // 3
}

let reportData = gen()
reportData.next() // 开始第一次

Proxy 使用

es5中对对象进行拦截使用 Object.defineProperty(),es6增加了new Proxy来增强代理拦截能力

1. 使用Proxy拦截对象,实现私有属性(下划线开头)禁止访问

let user = {
	name:’xxx’,
	age: 18,
	_gender: ‘male’	
}
user = new Proxy(user,{
	get(target, key) {
		if(key.startsWith(‘_’){
			throw new Error(‘不可访问’)
		} else {
			return target[key]
		}
	},
	set(target, key, val) {
		if(key.startsWith(‘_’){
			throw new Error(‘不可访问’)
		} else {
			return target[key] = val
		}
	}
	has (target, key) {
		if(key[0] === "_") { // key.startsWith(‘_’)
			return false;
		}
			return key in target;
	}
	deleteProperty(key){
		if(key.startsWith(‘_’){
			throw new Error(‘不可删除’)
		} else {
			delete target[key]
			return ture	
		}
	}
	ownKeys(target){
		return Object.keys(target).filter(key => !key.startsWith(‘_’))
	}
})

2. 使用Proxy拦截函数调用

let sum = (…args) =>{
	let num = 0
	args.forEach(item => {
		num += item
	})
	return num
}
sum = new Proxy(sum, {
	// 当前函数,上下文this,参数
	apply(target, ctx, agrs) {
		return target(…args) * 2
	}
})

3. 使用Proxy拦截类的构造函数

let User = class {
	constructor (name){
		this.name = name
	}
}
User = new Proxy(User, {
	// 当前类,参数,目标类
	constructor(target, args, newTarget){
		return new target(…args)
	}
})

前端规范,参考于JAVA开发手册第2版

编程规约

1.1 命名风格
  1. 名称不能以下划线和美元符号开头或结尾
  2. 禁止使用拼音和中文命名
  3. 避免使用性别、种族、地域等歧视性语言
  4. 类名使用大驼峰
  5. 方法、参数、变量使用小驼峰
  6. 常量命名全部大写,用下划线隔开,单词要写完整
  7. 抽象类使用Abstract或Base开头
  8. 避免在不同的代码块使用相同的命名
  9. 避免使用单词缩写
  10. 使用变量类型作为单词的结尾,例如startTime、nameList
  11. 如果使用了设计模式要用单词体现,例如:LoginProxy
  12. 如果是形容能力的接口名称,用对应的形容词结尾,例如:Translatable
  13. 枚举类使用Enum后缀
  14. 获取单个对象使用get开头,获取多个对象使用list开头,获取统计使用count,插入使用save/insert,删除使用remove/delete,修改update
1.2 常量定义
  1. 不允许使用魔法值
  2. 不要使用一个常量类维护所有的常量,要按功能归类分开维护
  3. 常量的五层:跨应用、应用内、子工程内、包内、类内
  4. 如果常量仅在一个固定的范围内变化,则用enum类型定义
1.3 代码格式
  1. 打括号前不换行
  2. 4个空格缩进,禁止Tab字符
  3. //注释内容前加一个空格
  4. 单行字符串长度不超过120字符
  5. 单个方法的总行数不超过80
  6. 不同的逻辑、语义、业务之间插入一个空行
1.4 OOP规约
构造方法禁止加入任何业务逻辑,如果有,那么放入init方法中
类内的方法定义顺序依次是:公有方法>getter/setter方法
setter方法中的参数名称和变量名要保持一致,且不要包含业务逻辑
1.5 日期时间
时间单位使用毫秒
不要1年写成365天
1.6 集合
判断对象是否为空使用isEmpty()方法
1.8 控制语句
switch必须包含default,哪怕什么代码都没有
switch括号内的变量如果为字符串时需要先进行null判断
单行的if语句要加打括号
尽量少用if-else,可以改写成
if(condition){
return obj;
}
// 接着写else的逻辑
超过3层的if-esle逻辑判断可以使用卫语句,策略模式、状态模式等实现,例如卫语句的实例:
function findBoyfriend ( man ){
if(man.isUgly()){
console.log(1)
return
}
if(man.isPoor()){
console.log(2)
return
}
if(man.isBad()){
console.log(3)
return
}
}
不要在条件判断中执行复杂的逻辑,可以把这些复杂的逻辑先赋值给一个变量,这样的代码看起来可读性性更高,例如
let existed = Obj.has(x) && obj.xxx ===1 || obj.xxx…
if(existed){ … }
不要在表达式中插入赋值语句,例如:
return (sync = fair)? new FairSync(): new NofairSync()
循环体内减少业务逻辑,移出体外
避免使用反逻辑运算符,例如:
if(!(x >= 1))
如果是对外开发的接口方法要做参数校验
1.9 注释规约
类和方法注释必须使用/**的方式,并且符合jsdoc规范
文件头部添加创建者和创建日期
代码内的注释要在上方另起一行使用// 注释,多行注释使用/ * */ 并对其文字
枚举类型字段必须注释用途
代码更新后注释要更新,保持一致
删除未使用的方法、属性、变量
如果注释掉的代码一定要保留,要说明用途和影响,否则一律删除
注释是给继任者看的,要准确的描述业务含义
TODO要注明标注人和计划处理的时间
1.10 前后端交互
http请求体body中必须控制长度,Nginx默认长度为1mb
1.11 其他
不要在视图层写复杂的业务逻辑

设计规约

如果系统交互的User类超过1类,相关的User Case 类超过5个,则使用用例图来表达结构
如果某个业务对象的状态超过3个,应使用状态图表达且明确状态变化的各个触发条件
如果系统中的调用链路上涉及的对象超过3个,则使用时序图表达各个环节的输入与输出
如果系统中的类超过了5个,则使用类图表达之间的关系
如果系统中的2个对象之间存在协作关系,需要表示复杂的处理流程,则需要使用活动图来表示
系统架构设计时明确以下原则
确定系统边界,确定在技术层面上做与不做
确定系统内模块之间的关系
确定后续演化的原则
确定非功能性需求,如安全性、可用性、扩展性等
在需求分析时要充分考虑异常流程和业务边界
在类的设计与实现时要符合单一原则
谨慎使用继承的方式进行扩展,优先使用聚合和组合
根据依赖倒置原则,尽量依赖抽象类与接口,更有利于扩展
对扩展开放,对修改闭合
共性的业务和行为抽取出来公共模块和配置
设计文档的主要目的是明确需求、理顺逻辑、后期维护、次要目的是知道编码
可扩展性的本质是找到系统的变化点,并隔离变化点
设计的本质就是识别和表达系统的难点
清晰的代码只是文档的某个片段,而不是全部

react脚手架在vscode编辑器中报错Using `babel-preset-react-app` requires that you specify `NODE_ENV` or `BABEL_ENV` environment variables

例如在app.js文件中的第一行import下面提示红色波浪线

错误提示为:Parsing error: [BABEL] …/src/App.js: Using `babel-preset-react-app` requires that you specify `NODE_ENV` or `BABEL_ENV` environment variables. Valid values are “development”, “test”, and “production”. Instead, received: undefined. (While processing: “…/node_modules/babel-preset-react-app/index.js”)eslint

原因:由 vscode 的 eslint 扩展插件启动的服务时,没有为其注入 BABEL_ENV 或 NODE_ENV。 导致 eslint 所使用的 babel-preset-react-app 解析器中 env 为 undefined 导致。

解决办法:
在vscode的配置文件setting.json中添加一行”eslint.nodeEnv”: “development”
重启

善恶的彼岸 经典语录

1、重要的事情说三遍。——尼采《善恶的彼岸》

2、当你凝视深渊时,深渊也在凝视着你。——尼采《善恶的彼岸》

3、所谓高贵的灵魂,即对自己怀有敬畏之心。——尼采《善恶的彼岸》

4、出于爱所做的事情,总是发生在善恶的彼岸。——尼采《善恶的彼岸》

5、常常谈论自己的人,往往只是为了隐藏自己。——尼采《善恶的彼岸》

6、人的自尊心很容易受到伤害,而人的虚荣心却很难受到伤害。——尼采 《善恶的彼岸》

7、伟人对我毫无意义,我只欣赏自己理想中的明星。——尼采《善恶的彼岸》

8、人最终喜爱的是自己的欲望,不是自己想要的东西!——尼采《善恶的彼岸》

9、凡是不愿意看别人长处的人,总是一眼就看到别人不如自己之处。——尼采《善恶的彼岸》

10、与恶龙缠斗过久,自身亦成为恶龙。凝视深渊过久,深渊将回以凝视。——尼采《善恶的彼岸》

11、只爱一个人是一种野蛮的行为,因为其他人就因此而牺牲了。对上帝的爱也是这样。——尼采《善恶的彼岸》

12、有了理想之后必须用自己的方法找到通往理想的道路,否则,理想只能是空想。如果你认为理想与自己无关,只愿静静地仰视,必然会得到悲剧的结果。一不小心,你的生活会比那些没有理想的人更不堪。——尼采 《善恶的彼岸》

13、在大海上渴死非常可怕。过于吹嘘真理的价值,真理就不再——止渴了,有必要这样做吗?——尼采《善恶的彼岸》

14、与恶魔斗争的人要时刻警惕,以免自己也变成恶魔。如果你久久地注视着深渊,那深渊同时也在注视着你。——尼采《善恶的彼岸》

15、“这是我干的。”我的记忆说,“我怎么会干出这种事呢?”我的矜持说,并坚持不退让。最终还是记忆退让了。——尼采《善恶的彼岸》

16、我们醒着的时候和做梦的时候,所做的事情是一样的:我们只是虚构和想象出与之交往的人——然后立即忘掉他。——尼采《善恶的彼岸》

17、藐视一切,但却能把握一切;它颠覆一切,却也占有一切;他不相信一切,但却并没有因此而丧失自我;它孕育出危险的自由精神,但却牢牢的守护着心灵。——尼采《善恶的彼岸》

18、在个体中,疯狂是一种罕见事物,但是在团体、党团、人群、时代中,它是惯例。或许,类似的疯狂,偏执狂的疯狂,唯有放大或凸现的时候,才会如此触目惊心,犹如人类的噩梦。——尼采《善恶的彼岸》

19、受束缚的心灵,自由精神——当一个人紧紧束缚自己的心灵,囚禁自己的心灵时,会听凭自己的思想享有许多自由;我以前曾说过这一点。但我这样说人们不会相信除非人们有亲身的体验。——尼采《善恶的彼岸》

20、人的特点是逆流而上。如果太简单,失败时就没有借口。挑战困难的事情,即使失败了,别人也会称赞你的勇气,至少会安慰你,你真有勇气!——尼采 《善恶的彼岸》

21、给自己一些考验吧。任何人都不知道的,仅仅你自己知道的。举个例子,就像是在任何人都看不见的地方,正直地活着;就算只有自己一个人的时候,也讲究礼仪地行动;就算对自己也不说一丁点儿谎话。在战胜了这些挑战之后,再重新评价自己,当开始觉得自己真正的高尚的存在的时候,人才获得了真正的自尊心。这才能显露出最强烈的自尊心。这是你对自己的报偿。——尼采 《善恶的彼岸》

22、获得真正自由的方法是要学会自我控制。如果情绪总是处于失控状态,就会被感情牵着鼻子走,丧失自由。所以那些精神自由,保持独立思考的人也正是擅长于控制自己情绪的人。——尼采 《善恶的彼岸》

23、凡不能毁灭我的,必使我强大。——尼采 《善恶的彼岸》

复杂度

时间复杂度
一个函数,用大O表示,比如O(1)、O(n)、O(logN)…
定性描述该算法的运行时间 – 不会描述具体的时间

待续。。。

实现输入框@人名功能

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .label {
        display: inline-block;
        border: solid 1px #ccc;
        padding: 10px 20px;
      }
      .output {
        padding: 20px;
        margin: 20px 0;
        width: 400px;
      }

      #myInput {
        width: 400px;
        border: solid 1px #ccc;
        padding: 10px 20px;
      }
    </style>
  </head>
  <body>
    <div class="output" id="myOutput"></div>
    <div contenteditable="plaintext-only" id="myInput"></div>
    <div><button id="myButton">submit</button></div>
    <div class="label" contenteditable="false" data-name="张三">@张三</div>
    <div class="label" contenteditable="false" data-name="李四">@李四</div>
    <div class="label" contenteditable="false" data-name="王五">@王五</div>
    <script>
      let inputEl = document.getElementById("myInput")
      let outputEl = document.getElementById("myOutput")
      let buttonEl = document.getElementById("myButton")
      let labelsEl = document.querySelectorAll(".label")

      buttonEl.addEventListener("click", (e) => {
        let liEl = document.createElement("div")
        liEl.innerText = inputEl.innerText
        outputEl.appendChild(liEl)
      })
      labelsEl.forEach((m) => {
        m.addEventListener("click", function (e) {
          console.log(this.dataset)
          let spanEl = document.createElement("span")
          spanEl.innerHTML = "@" + this.dataset.name + " "
          spanEl.style = "color:blue"
          spanEl.contentEditable = "false"
          inputEl.appendChild(spanEl)
        })
      })
    </script>
  </body>
</html>