Hank's Blog

耕种思考的自留地

0%

vue 中的 computed 属性的值只有当内部依赖的 data 属性变化时才会重新求值,这是怎么做到的呢。假设传入以下 computed :

1
2
3
4
5
computed: {
ab: function(){
return this.a + 1;
}
}

以下是 vue 初始化的操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
export function initState (vm: Component) {
vm._watchers = []
const opts = vm.$options
if (opts.props) initProps(vm, opts.props)
if (opts.methods) initMethods(vm, opts.methods)
if (opts.data) {
initData(vm)
} else {
observe(vm._data = {}, true /* asRootData */)
}
if (opts.computed) initComputed(vm, opts.computed)
if (opts.watch && opts.watch !== nativeWatch) {
initWatch(vm, opts.watch)
}
}
Read more »

全局中的解析和执行过程

预处理:创建一个词法环境(LexicalEnvironment,在后面简写为LE),扫描JS中的用声明的方式声明的函数用var定义的变量,将它们加到预处理阶段的词法环境中去。

一、全局环境中如何理解预处理

1
2
3
4
5
6
7
8
9
var a = 1;//用var定义的变量,以赋值
var b;//用var定义的变量,未赋值
c = 3;//未定义,直接赋值
function d(){//用声明的方式声明的函数
console.log('hello');
}
var e = function(){//函数表达式
console.log('world');
}

在预处理时上面代码创建词法作用域可以这样表示:

1
2
3
4
5
LE { // 此时的LE相当于window
a:undefined
b:undefined
d:对函数的一个引用
}
Read more »

关于 this 指向,部分情况要区分严格模式和非严格模式(正常模式):

  • 作为普通函数调用:严格模式下,this的值是 undefined,非严格模式下,this指向全局对象。
  • 作为方法调用:this指向所属对象。
  • 作为构造函数调用:this指向实例化的对象。
  • 通过call, apply, bind调用:如果指定了第一个参数thisArg,this的值就是thisArg的值(如果是原始值,会包装为对象);如果不传thisArg,要判断严格模式,严格模式下this是undefined,非严格模式下this指向全局对象。
Read more »

你想要什么,事实是什么,如何实现愿望。考察影响你的那些事物的规律,理解背后的因果关系,并利用之。

  • 做到头脑极度开放
  • 你的未来取决于你的视角
  • 没有痛苦就没有收获,痛苦 + 反思 = 进步
  • 五步实现愿望:明确目标、找出并不容忍问题、找到问题的根源、规划方案、坚定地执行
  • 如果你找到了解决方案,弱点是不重要的
  • 只有设身处地,才能合理评估另一种观点的价值
  • 寻找最好的答案,而不是你自己能得出的最好答案
  • 为最坏的情况做准备
  • 影响好决策的最大威胁是有害的情绪
  • 不必过于精确,明白关键性的 20%
  • 提高押对的概率始终有价值
  • 先把“必做之事”做完,在做“想做之事”

命令 作用
git reset [commit] 重置当前分支的指针为指定 commit,同时重置暂存区,但工作区不变
git reset –hard 重置暂存区与工作区,与上一次 commit 保持一致
git add [file1] … (git add [dir]) 添加指定文件(目录)到暂存区
git rm [file1] … 删除工作区文件,并且将这次删除放入暂存区
git commit -m [message] 提交暂存区到仓库区
git branch 列出所有本地分支
git branch -r 列出所有远程分支
git branch -a 列出所有本地分支和远程分支
git branch [branch-name] 新建一个分支,但依然停留在当前分支
git branch -d [branch-name] 删除分支
git checkout -b [branch] 新建一个分支,并切换到该分支
git push origin [local_branch]:[remote_branch] 将本地分支推送到远程
git checkout [branch-name] 切换到指定分支,并更新工作区
git checkout - 切换到上一个分支
git checkout [file] 恢复暂存区的指定文件到工作区
git merge [branch] 合并指定分支到当前分支
git tag [tag] 新建一个 tag 在当前 commit
git log(git reflog) 显示当前分支的(最近)版本历史
git diff HEAD 显示工作区与当前分支最新 commit 之间的差异
git push origin [branch] 上传本地指定分支到远程仓库

git checkout可以缩写为gco

HEAD 指向当前分支,HEAD^n表示当前分支的第 n 个父提交,HEAD~n表示当前分支的第 n 个父提交,用于第一父母存在歧义的情况下

Koa2 的源码 相当的简短,因为抽离了路由、模板引擎等模块,只提供一个架子,而几乎所有的功能都需要由第三方中间件完成。阅读时建议对照源码。

1
2
3
4
5
. lib
├── application.js ---------- 构造 app 对象
├── context.js -------------- 构造 ctx 对象
├── request.js --------------- 构造 req 对象
└── response.js ------------- 构造 res 对象

底层原理同 express,即代理http.createServer(requestHandler)中的requestHandler,使用中间件来处理请求。

Read more »

打开 Express4 的源码,目录结构很清晰,阅读时建议对照源码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
. lib
├── middleware -------------- 中间件
├── init.js ------------ 增强 req 对象和 res 对象
└── query.js ------------ 添加 req.query
├── router ------------------ 路由
├── index.js ------------ Router 构造器
├── layer.js ------------ 中间件和路由的抽象
└── route.js ------------ 实现 router.route
├── application.js ---------- app 对象拓展
├── express.js -------------- 项目入口
├── request.js --------------- req 对象拓展
├── response.js ------------- res 对象拓展
├── utils.js ---------------- 工具集
└── view.js ----------------- 模板引擎

底层原理

Express 框架建立在 node.js 内置的 http 模块上,http 模块生成服务器的原始代码如下。

1
2
3
4
5
6
7
8
var http = require("http");

var app = http.createServer(function(request, response) {
response.writeHead(200, { "Content-Type": "text/plain" });
response.end("Hello world!");
});

app.listen(3000, "localhost");

Express 代理了http.createServer(requestHandler)中的requestHandler,并使用注册后的中间件和路由,匹配响应传来的用户请求。

Read more »

首先实现一个基础结构,每一个 Promise 实现,都有状态标识,以及存放成功与失败回调函数的数组。为什么要使用数组来存放回调函数呢,是考虑到了下面这种情况。

1
2
3
4
5
6
7
8
var p3 = new Promise((resolve, reject) =>
setTimeout(() => {
resolve(new Date());
}, 1000)
);
// 连续调用多次 p3.then ,回调函数需要使用数组来存放
p3.then(v => console.log("a: " + v));
p3.then(v => console.log("b: " + v));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function Promise(executor) {
var self = this;

self.status = "pending"; // promise 的状态
self.onResolvedCallback = []; // 存放成功的回调函数的数组
self.onRejectedCallback = []; // 存放失败的回调函数的数组

function resolve(value) {
// todo
}

function reject(reason) {
// todo
}

try {
executor(resolve, reject);
} catch (reason) {
reject(reason);
}
}

resolve/reject 负责异步修改 promise 的状态并触发 onResolvedCallback/onRejectedCallback 中的回调函数。为什么要异步触发呢,是为了保证在触发回调前,所有的回调函数都已经被 then 注册。

Read more »

vuex 中的 store 本质就是没有 template 的隐藏着的 vue 组件,所有配置的 state、actions、mutations 以及 getters 都是其组件的属性,所有的操作都是对这个组件进行的。

vuex 仅仅是作为 vue 的一个插件而存在,不像 Redux、MobX 等库可以应用于所有框架,vuex 只能使用在 vue 上,很大的程度是因为其高度依赖于 vue 的 computed 依赖检测系统以及其插件系统。

每一个 vue 插件都需要有一个公开的 install 方法,vuex 的 install 方法中调用了 applyMixin 方法,该方法在组件的 beforeCreate 生命周期中混入了一个操作:在实例上挂载了一个$store属性指向store对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// src/store.js
import applyMixin from "./mixin";

export function install(_Vue) {
if (Vue && _Vue === Vue) {
if (process.env.NODE_ENV !== "production") {
console.error(
"[vuex] already installed. Vue.use(Vuex) should be called only once."
);
}
return;
}
Vue = _Vue;
applyMixin(Vue);
}
Read more »

作为新手不熟悉python如何引入本地的模块,经过一番折腾,基本明白了引入方式。
假设有一个项目,目录结构如下:

1
2
3
4
5
6
7
8
. root_dir
├── app.py
└── test
└── subtest
├── __init__.py
└── hi.py
├── __init__.py
└── hello.py
Read more »