Vincent's waking life

他是彭于晏?
那我是谁?


  • Home

  • Footprint

  • Cheat sheet

一周网摘2018-12-w1

Posted on 2018-12-09 | In 杂

见微知著,Google Photos Web UI 完善之旅

Google 工程师撰文《Building the Google Photos Web UI》,里面详细介绍了 Google Photos for Web 是如何在几千上万张用户照片的体量下,做到自适应布局、高性能加载、60fps 流畅滚动,并提升页面速度的,干货不少值得一读!中文翻译:

zhuanlan.zhihu.com


为什么我们活得越来越像一只信息量过载的猪

智谷趋势

这篇文章本身也是信息过载/贩卖焦虑吧,有时候需要反省下自己到底想要什么


Parked cars covered by the season’s first snowfall in Moscow

Parked cars covered by the season’s first snowfall in Moscow

vscode + vetur + eslint + prettier 实现团队代码风格统一

Posted on 2018-12-07 | In 前端 , tool chain

vscode + vetur + eslint + prettier 实现团队代码风格统一

如果你也是 front-end coder,也采用 ES6、vue 单文件、css 预编译,希望实现团队代码格式/风格统一,可参考本文。

值得参考并执行的规范

  • 谷歌 HTML/CSS 规范
  • Airbnb CSS / Sass 指南
    • zh_CN
  • Airbnb JavaScript 风格指南
    • zh_CN
  • Eslint rules(强烈推荐)
  • 使用 ES6 进行开发的思考(via Baidu EFE)
  • Vue.js 风格指南

落地方案

  • IDE: vs code
    • ESLint // ide lint 报错/warning 要靠它
    • Prettier - Code formatter // 格式化 html/css/less/scss etc…
    • Vetur // 这里只用来语法提示,代码格式化交给 eslint(npm)
  • npm:
    • eslint
    • eslint-config-airbnb-base
    • eslint-config-prettier
    • eslint-plugin-import
    • eslint-plugin-vue
    • eslint-plugin-prettier
    • prettier
  • 关键配置文件(in git repo)
    • .vscode/setting.json // ESLint(ide 插件),vetur(ide 插件)配置在这里
    • .editorconfig // 字符集配置,缩进等配置
    • .eslintrc.js // eslint(npm)配置,ide eroor/warning 信息在这里配置
    • .eslintignore // eslint 排除文件,如一些库文件
    • .prettierrc.js // prettier 配置,如逗号分号规则
    • .prettierignore //prettier 排除文件

简单说下思路

  • eslint 优先级最高,装插件eslint-config-airbnb-base,eslint-config-prettier,eslint-plugin-vue,可以覆盖 prettier 的设置
  • eslint 主要负责 vue/js 的格式化
  • prettier 主要负责 html/css/less/scss… 的格式化
  • Vetur 也有格式化功能,直接 disable 掉,我们用更高级的
  • prettier 不支持 stylus,但是 Vetur 的依赖包括了stylusSupremacy,可以解决
  • 所有的配置都可以放在项目 repo 里,且优先级会高于 coder 本地的设置,保证团队所有成员提交的代码一致
  • 如果装了其他 format 插件,请在本项目中 disable 掉,我们不需要

附:配置文件

EditorConfig

1
2
3
4
5
6
7
8
9
10
11
12
13
root = true # 表明是最顶层的配置文件,发现设为true时,才会停止查找.editorconfig文件。

[*]
charset = utf-8 # 编码格式,支持latin1、utf-8、utf-8-bom、utf-16be和utf-16le,不建议使用uft-8-bom。
indent_style = space # tab为hard-tabs,space为soft-tabs。
indent_size = 2 # 设置整数表示规定每级缩进的列数和soft-tabs的宽度(译注:空格数)。如果设定为tab,则会使用tab_width的值(如果已指定)。
end_of_line = lf # 定义换行符,支持lf、cr和crlf。
insert_final_newline = # 设为true表明使文件以一个空白行结尾,false反之。
trim_trailing_whitespace = true # 设为true表示会除去换行行首的任意空白字符,false反之。

[*.md]
insert_final_newline = false # 设为true表明使文件以一个空白行结尾,false反之。
trim_trailing_whitespace = false # 设为true表示会除去换行行首的任意空白字符,false反之。

.eslintrc.js

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/**
*
* 规则说明见 https://cn.eslint.org/docs/rules/
* eslint-plugin-import 规则见 https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/default.md
* eslint-plugin-vue 规则见 https://github.com/vuejs/eslint-plugin-vue
*
* "off" 或 0 - 关闭规则
* "warn" 或 1 - 开启规则,使用警告级别的错误:warn (不会导致程序退出)
* "error" 或 2 - 开启规则,使用错误级别的错误:error (当被触发的时候,程序会退出)
*
*/

module.exports = {
extends: [
// add more generic rulesets here, such as:
// 'eslint:recommended',
"airbnb-base", // airbnb lint规范
"plugin:vue/essential", // eslint-plugin-vue
"plugin:prettier/recommended" // eslint-config-prettier
],
// settings: {
// 'import/resolver': {
// webpack: {
// config: 'build/webpack.base.conf.js',
// },
// },
// },
// plugins: ['vue'],
rules: {
"prettier/prettier": 1,
"no-undef": 2, // 禁用未声明的变量,除非它们在 /*global */ 注释中被提到. e.g. /* global Stomp SockJS */ in .vue file's <scrpit>
"no-extend-native": 2, // 禁止扩展原生类型
"no-return-assign": 2, // 禁止在 return 语句中使用赋值语句
"import/order": 0, // Enforce a convention in module import order
"import/no-extraneous-dependencies": 0, // 禁止导入未在package.json的依赖项,devDependencies,optionalDependencies或peerDependencies中声明的外部模块。将使用最接近的父package.json。
"import/no-dynamic-require": 1, // CommonJS的require方法用于从不同文件导入模块。与ES6导入语法不同,可以为其提供将在运行时解析的表达式。虽然这有时是必要且有用的,但在大多数情况下并非如此。使用表达式(例如,连接路径和变量)作为参数使得工具更难以进行静态代码分析,或者在代码库中找到使用模块的位置。
"import/extensions": 0, // 某些文件解析算法允许您在导入源路径中省略文件扩展名。例如,节点解析器可以将./foo/bar解析为绝对路径/User/someone/foo/bar.js,因为默认情况下会自动解析.js扩展名。根据解析程序,您可以配置更多扩展程序以自动解决。
"import/no-unresolved": 0, // 确保导入的模块可以解析为本地文件系统上的模块,如标准Node require.resolve行为所定义。
"import/prefer-default-export": 1, // 当模块中只有一个导出时,更喜欢使用默认导出而不是命名导出。
"vue/no-async-in-computed-properties": 1, // 计算属性应该是同步的。其中的异步操作可能无法按预期工作,并可能导致意外行为,这就是您应该避免它们的原因。如果您需要异步计算属性,可能需要考虑使用其他插件[vue-async-computed]
"vue/no-side-effects-in-computed-properties": 1, // 在计算属性中引入副作用被认为是一种非常糟糕的做法。它使代码无法预测且难以理解。
"vue/no-reserved-keys": 1, // 此规则阻止使用保留名称以避免冲突和意外行为。
"vue/require-v-for-key": 2, // 当v-for写在自定义组件上时,它需要同时使用v-bind:key。在其他元素上,v-bind:key也最好写。
"vue/require-valid-default-prop": 1, // 此规则检查每个prop的默认值是否对给定类型有效。当使用函数未返回类型Array或Object的默认值时,它应报告错误。
"no-unused-vars": 1, // 禁止出现未使用过的变量
"generator-star-spacing": 0, // 强制 generator 函数中 * 号周围使用一致的空格
"no-plusplus": 0, // 禁用一元操作符 ++ 和 --
"func-names": 0, // 要求或禁止使用命名的 function 表达式
"no-console": 0, // no-console
radix: 0, // 强制在parseInt()使用基数参数
"no-control-regex": 0, // 禁止在正则表达式中使用控制字符
"no-continue": 0, // 禁用 continue 语句
"no-debugger": process.env.NODE_ENV === "production" ? 2 : 0,
"no-param-reassign": 1, // 禁止对 function 的参数进行重新赋值
"no-underscore-dangle": 1, // 禁止标识符中有悬空下划线"_"
"global-require": 1, // 要求 require() 出现在顶层模块作用域中
"no-var": 1, // 要求使用 let 或 const 而不是 var
"vars-on-top": 1, // 要求所有的 var 声明出现在它们所在的作用域顶部
"prefer-destructuring": 1, // 优先使用数组和对象解构
"no-useless-concat": 1, // 禁止不必要的字符串字面量或模板字面量的连接
"no-shadow": 1, // 禁止变量声明与外层作用域的变量同名
"guard-for-in": 1, // 要求 for-in 循环中有一个 if 语句,旨在防止使用for in循环而不过滤循环中的结果时可能出现的意外行为。
"no-restricted-syntax": 1, // 禁用特定的语法
"global-require": 1, // 要求 require() 出现在顶层模块作用域中
"consistent-return": 1, // 要求 return 语句要么总是指定返回的值,要么不指定
eqeqeq: 1, // 要求使用 === 和 !==
"no-unused-expressions": 1, // 禁止出现未使用过的表达式
camelcase: 1, // 强制使用骆驼拼写法命名约定
"block-scoped-var": 1, // 强制把变量的使用限制在其定义的作用域范围内,旨在减少绑定上下文之外的变量的使用,并从其他语言模拟传统的块范围。这是为了帮助语言新手避免变量提升的难题。
"no-redeclare": 1, // 禁止多次声明同一变量
"prefer-arrow-callback": 1, // 要求回调函数使用箭头函数
"array-callback-return": 1, // 强制数组方法的回调函数中有 return 语句,Array有几种过滤,映射和折叠的方法。如果我们忘记return在这些回调中写入语句,那可能是一个错误。
"default-case": 1, // 要求 switch 语句中有 default 分支
"no-loop-func": 1, // 禁止在循环中出现 function 声明和表达式
"no-fallthrough": 1, // 禁止 case 语句落空
"no-multi-assign": 1, // 禁止连续赋值
"no-lonely-if": 1, // 禁止 if 作为唯一的语句出现在 else 语句中.如果一个if陈述是该else块中唯一的陈述,那么使用一个else if表格通常会更清晰。
"no-irregular-whitespace": 1, // 禁止在字符串和注释之外不规则的空白
"prefer-const": 1, // 要求使用 const 声明那些声明后不再被修改的变量.如果一个变量从不重新分配,使用const声明更好。const 声明告诉读者,“这个变量永远不会被重新分配,”减少认知负荷并提高可维护性。
"no-use-before-define": 1, // 禁止在变量定义之前使用它们
"no-useless-escape": 1, // 禁用不必要的转义字符
"no-array-constructor": 1, // 禁用 Array 构造函数,由于单参数的缺陷以及Array全局可能被重新定义,所以通常不鼓励使用构造函数来构造新Array数组,而是倾向于使用数组文字符号。例外情况是Array构造函数用于通过给构造函数一个数字参数有意创建指定大小的稀疏数组。
"object-shorthand": 1, // 要求或禁止对象字面量中方法和属性使用简写语法
"no-prototype-builtins": 1, // 禁止直接调用 Object.prototypes 的内置属性.当假定对象将具有属性时,这可能导致错误Object.prototype。此规则可防止Object.prototype直接从对象调用方法。
"no-nested-ternary": 1, // 禁用嵌套的三元表达式.嵌套三元表达式会使代码更难理解。
"no-new-wrappers": 1, // 禁止对 String,Number 和 Boolean 使用 new 操作符.没有任何理由将这些基本包装用作构造函数
"prefer-promise-reject-errors": 1, // 要求使用 Error 对象作为 Promise 拒绝的原因
"no-labels": 1 // 禁用标签语句
}
};

.prettierrc

1
2
3
4
5
6
7
8
9
10
module.exports = {
printWidth: 80, //一行的字符数,如果超过会进行换行,默认为80
tabWidth: 2, //一个tab代表几个空格数,默认为80
useTabs: false, //是否使用tab进行缩进,默认为false,表示用空格进行缩减
singleQuote: true, //字符串是否使用单引号,默认为false,使用双引号
semi: true, //行位是否使用分号,默认为true
trailingComma: "es5", //是否使用尾逗号,有三个可选值"<none|es5|all>"
bracketSpacing: true //对象大括号直接是否有空格,默认为true,效果:{ foo: bar }
// parser: 'babylon', //代码的解析引擎,默认为babylon,与babel相同。
};

.vscode/setting.json

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
28
29
30
31
32
33
34
35
36
37
38
39
40
{
// 使用2个空格作为tab,并将对齐基准线设置为2个字符test
"editor.tabSize": 2,
// 保存文件时自动格式化,主要针对html/css/less/scss等eslint未覆盖的文件格式
// "editor.formatOnSave": true,
// 保存文件时按照eslint配置自动处理vue/js/jsx/ts/json文件格式
// "eslint.autoFixOnSave": true,
// 打开对vue的lint,并自动fix
"eslint.validate": [
"javascript",
"javascriptreact",
{
"language": "vue",
"autoFix": true
}
],
// 对于.vue文件,关闭prettier,交给eslint fix
"vetur.format.defaultFormatter.css": "none",
"vetur.format.defaultFormatter.html": "none",
"vetur.format.defaultFormatter.js": "none",
"vetur.format.defaultFormatter.less": "none",
"vetur.format.defaultFormatter.postcss": "none",
"vetur.format.defaultFormatter.scss": "none",
"vetur.format.defaultFormatter.stylus": "stylus-supremacy",
"vetur.format.defaultFormatter.ts": "none",

/* stylus 配置 start */
// 是否插入冒号
"stylusSupremacy.insertColons": false,
// 是否插入分号
"stylusSupremacy.insertSemicolons": false,
// 是否插入大括号
"stylusSupremacy.insertBraces": false,
// import之后是否换行
"stylusSupremacy.insertNewLineAroundImports": false,
// 两个选择器中是否换行
"stylusSupremacy.insertNewLineAroundBlocks": false
/* stylus 配置 end */
}


后记

  • 代码格式化相关的文章已经汗牛充栋,关键点不在于各种圣战,而在于团队风格统一
  • vue 格式文件格式化比较特殊,template/script/style 部分由不同的插件来完成
  • 通过统一 IDE/插件/配置文件实现:
    • 自动格式化前端开发常见文件,实现团队代码风格统一
    • 杜绝因格式问题导致的提交冲突
    • 统一配置,团队共享,实现同步
  • 搞清楚各种 linter/formater/IDE 插件/npm 插件的分工/优先级很重要
  • ts 解决方案/git commit lint/eslint webpack loader 应该是更好也是更严格的方案,目前暂未涉及,将会是以后努力的方向

欢迎拍砖,欢迎交流

本文完

七牛把用户当猴耍呢,一生黑

Posted on 2018-12-06 | In power user of everything

七牛云速度还是可以的,也算厚道,一直免费给你一个二级域名用,10G/月的免费流量对于我也够用。

但是最近估计有人用图层上传了不和谐的东西(这些毒瘤也该死),导致七牛云收回了二级域名使用权,之前上传到图层的文件都报错“no such domain”。

那好吧,我看看怎么挽回,一看就傻眼了:

  • 想继续用七牛云
    • 可以,先绑自己域名
  • OK,我绑还不行吗?
    • 域名要备案
  • 备 NMB 案,老子不用了,批量下载
    • 没有批量下载 GUI
  • 我写脚本下载
    • 原来送的二级域名收回了,所有图片都没办法访问了。但是有 shell 工具可以批量下载
  • 那我试试 shell
    • 原来送的二级域名收回了,没办法获取下载地址

意思是七牛收回二级域名了,不仅外网无法访问你的资源,你自己也没有办法在后台操作了,如果你之前没备份,就瓜起了

不说了,七牛一生黑

  • 有补救办法吗?
    • 备(NMB)案

好在天无绝人之路,曲线救国的方法

  1. 重新创建一个测试 bucket(会分配一个新的测试域名,有限期 30 天)
  2. batchcopy 原 bucket 到新的 bucket
  3. qdownload 新 bucket

要用到的工具:qshell

这个命令行工具 api 据我观察最近已经和两个月前不兼容了(黑点 2)

目前主要关注batchcopy和qdownload

鉴于 api 经常变就不贴命令了,自己看文档吧。

删 bucket,走人

macOs 下设置Capslock切换输入法

Posted on 2018-12-05 | In power user of everything

如果你有以下需求,不妨一试:

  • 使用搜狗输入法(为了词库)
  • 外接键盘,想实现内置/外置键盘的 cmd 和 opt 位置一致
  • 想用 Capslock 一键切换中/英

预防杠精:

系统自带拼音输入法/搜狗输入法都可以设置 caps 切换中英,为何折腾?

答:很多场景,例如各种登录的 pwd input 获得焦点时,系统会自动把输入法切换为自带的英语输入法,这时你是不知情的,你不得不用 ctrl + space 切换回中文输入法。这个过程需要确认,有种反复插拔 usb 的感觉。

你把默认的英文输入法删除了不就好了?

答:首先删不掉,10.14 之前有方法可以 hack,但不推荐,有坑,而且不安全。

实现方法

下载Karabiner,安装之,重启系统

Karabiner是一个 mac 下修改键盘映射的工具

关闭搜狗的中英切换快捷键

此步骤在于避免误操作,从此以后只有两种输入法:英文/中文,互相的状态也单一,纯粹

设置切换输入法的快捷键为 command+control+option+shift+p

我知道默认的快捷键是ctrl+space,设成这个几乎不会用到的快捷键,可以省出ctrl+space,设置成更常用的功能

利用 Karabiner 将Capslock映射为command+control+option+shift+p

配置文件地址在 ~/.config/karabiner/karabiner.json,这里只贴出关键配置

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
28
29
30
31
32
33
34
35
"complex_modifications": {
"parameters": {
"basic.simultaneous_threshold_milliseconds": 50,
"basic.to_delayed_action_delay_milliseconds": 500,
"basic.to_if_alone_timeout_milliseconds": 1000,
"basic.to_if_held_down_threshold_milliseconds": 500
},
"rules": [
{
"manipulators": [
{
"description": "Change caps_lock to command+control+option+shift+p.",
"from": {
"key_code": "caps_lock",
"modifiers": {
"optional": ["any"]
}
},
"to": [
{
"key_code": "p",
"modifiers": [
"left_command",
"left_control",
"left_option",
"left_shift"
]
}
],
"type": "basic"
}
]
}
]
}

交换 cmd/opt

保证外接键盘的键位和内置键盘一样,不然会疯掉

后记

按照以上设置,可以实现不用考虑内置/外置键盘,只需要 caps 就能在中/英之间切换,就算 pwd input 自动切换成英文输入法了,只要发现了点一下 caps 就好,不用再反复确认到底是输入法切换了还是中英状态切换了
设置开机启动什么的不赘述了

缺点

大小写指示灯再也不会亮了

本文完。

一周网摘2018-11-w5

Posted on 2018-11-30 | In 杂

每个 JavaScript 工程师都应懂的 33 个概念 @leonardomso

这个项目是为了帮助开发者掌握 JavaScript 概念而创立的。它不是必备,但在未来学习(JavaScript)中,可以作为一篇指南。

本篇文章是参照 @leonardomso 创立,英文版项目地址在这里。 由于原版资源都要翻墙,所以本人创立一个中文版,附上关于这些概念在国内的一些文章和视频。 若有觉得更好的文章或者视频,可以贡献出来,觉得有误的,请联系我删除。


Science Fiction Interfaces(汤不热好像要科学上网)

![](/pic/sinaimg/006tNbRwgy1fxlac0gfjyj30zk0k0gp2.jpg)

一些科幻作品里出现的电脑操作 UI 界面


ScriptOJ

![](/pic/sinaimg/006tNbRwgy1fxlaf9lu74j31350u01kx.jpg)

ScriptOJ 是首个 Web 前端开发评测系统
从大量实战代码、面试题目中总结出精华题库和相应的测试
帮助你提升、锻炼 Web 开发技能,简单直接地获取第一手 Web 前端实战经验。


HTML5 声音引擎 Howler.js

Howler.js 支持很多声音格式以兼容各种浏览器。MP3, MPEG, OPUS, OGG, OGA, WAV, AAC, CAF, M4A, MP4, WEBA, WEBM, DOLBY, FLAC.


macOS Mojave 上的 launchrocket 凉了

“That’s really unfortunate. That probably means this prefpane is effectively dead.”

官宣

不过有替代方案

1
brew services list

and then

1
brew services start xxx(your service)

每月电影2018-10

Posted on 2018-11-19 | In movies

动物世界 (2018)

动物世界

豆瓣评分: 7.3/10
个人评分: 7.5/10

漫画改编,完成度和工业化程度在大陆电影中可称翘楚。如果主演不是李易峰和周冬雨可能还有加分

不足之处在于导演炫技痕迹明显且无必要


奇迹

奇迹

豆瓣评分: 8.8/10
个人评分: 8.5/10

是枝裕和为新干线拍的命题作文

小朋友的视角与世界已经太久没有体会了,温暖,纯粹


无人知晓

无人知晓

豆瓣评分: 9.1/10
个人评分: 8.8/10

【西巢鸭弃婴事件】改编,人类的不负责任/不作为是一种极端的恶,人性之下是兽性


网络谜踪 Searching (2018)

网络谜踪

豆瓣评分: 8.5/10
个人评分: 8.5/10

据了解应该不是第一部以电脑屏幕为呈现场景的电影,但却是我看的第一部。至少形式上很震撼

教科书般的本格派推理,真相导演其实早就预埋在正品之中

韩国周杰伦跑了一万年龙套终于接了部好电影


需避坑:

  • 七月与安生 (2016),除了狗血还是狗血
  • 蚁人2:黄蜂女现身 Ant-Man and the Wasp (2018),格局小得可怕

一周网摘2018-09-w2

Posted on 2018-09-08 | In 杂

nginxconfig.io

![](/pic/20180910/nginxconfig.io.jpg)

比较懒不想写 Nginx 配置?可以去 nginxconfig.io 在线生成一套,有前端(MVVM)、PHP 后端、Node.js、单页应用、WordPress 等多个预置模板,一般需求稍微改改就够了。


口红色号名称 - RGB 颜色值

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
28
29
30
31
32
33
{
"brands": [{
"name": "圣罗兰",
"series": [{
"name": "莹亮纯魅唇膏",
"lipsticks": [{
"color": "#D62352",
"id": "49",
"name": "撩骚"
}, {
"color": "#DC4B41",
"id": "14",
"name": "一见倾心"
}, {
"color": "#B22146",
"id": "05",
"name": "浮生若梦"
}, {
"color": "#A25356",
"id": "08",
"name": "纯真梦幻"
},
...
}, {
"name": "香奈儿可可小姐",
"series": [{
"name": "唇膏水亮",
"lipsticks": [{
"id": "69",
"color": "#F17365",
"name": "传情"
},
...

“老婆你看我还是很疼你的”


精辟

这就好像说寺庙门口阮老师在给穷人施粥,这时候一个(伪)美食家走了过来,拿起勺子在桶里搅来搅去,然后从桶底捞出了一根头发,接着就大声的向大家喊到:
快来看,这个人做的粥有问题,何止是有问题,简直是完全错误的。
阮老师让很多人从饿肚子到吃饱饭,但它可能确实就是清粥白饭,偶尔也有点瑕疵。
但那些高喊着大家要吃燕窝鲍鱼的人,你们倒是能长年累月的拿出来分给大家啊。
结果这些人只是说着风凉话,看着热闹,最后还一哄而上砸了人家的摊子。
你说你们是不是有病

via 如何看待文章《面试官:阮一峰版的快速排序完全是错的》? - 王德福的回答 - 知乎


visualgo.net

![](/pic/20180910/visualgo.jpg)

推荐一个算法可视化项目,常见的算法基本都找的到,并且每一步都会动态演示出来,不过有点美中不足的是连伪代码都顺手翻译了(看到“做…while”这种组合挺懵逼的……不习惯的话可以切英文版),初学算法的话可以看一看。

微信对我来说只是IM+支付工具,仅此而已

Posted on 2018-09-03 | In power user of everything

前言

曾几何时,每次点亮手机屏幕,微信的图标上面必然会有未读提醒,强迫症的你点进去以后却发现是某公众号的日经广告推送。关掉公众号信息提醒吧,又看不到文章;不关吧过了几分钟又弹出来一篇“震惊”。

是时候作出改变了。

微信的平台化

还记得微信刚刚诞生时,“免费发短信”是其唯一卖点。那时的我,支付使用支付宝,阅读主要靠 RSS,微信的出现似乎对于我来说没什么影响。

后来的微信逐渐往平台发展:

  • 摇一摇(陌生人社交)
  • 朋友圈(Facebook of China)
  • 公众号(干掉博客)
  • 小程序(appstore in 微信)

平台化的微信极大的降低了互联网小白用户的使用门槛:记不住网站域名?-没关系,直接找认证过的公众号;不会用浏览器收藏夹?-微信自带“收藏功能”;不会分享链接?二维码在每篇 post 底部都有。

微信让那些曾经对于电脑和智能手机望而却步的大爷大妈每天刷得不亦乐乎,成为收割“国民总时间”的利器。

灾难

平台化的微信对我来说是个灾难。

我从来不喜欢在微信看文章,因为经常在你看文章的过程中,有好友消息来了,你不得不退出去回消息,再重新回到文章。这个“退出文章-回消息-重新寻找文章入口-返回阅读进度”的体验实在是太糟糕了。尽管微信最近的版本加入了文章悬浮球的功能,但也仅是聊胜于无。

自媒体概念的兴起已经从事实上杀死了独立 blogger。现在某个领域的内容创作者如果想发声,不大会注册域名,搭建独立博客。更好的选择是直接开个公众号,不管是运维还是推广成本都比搭建博客低太多。

从最近微信公众号改版加入信息瀑布流的举动来开,微信的公众号有点想接替 rss 的意思。但是且不谈互联网中立,单是公众号信息流无法分类,无法显示未读,仅有一个残废的置顶功能,它还远远不能满足我的需求。

微信阅读:曲线救国?

微信阅读可以直接把公众号作为文集加入书架,并可以整理分类,也可以显示更新,曾经有段时间我尝试使用它来阅读所有的微信公众号文章。但是微信阅读还是无法显示未读条数,且没有信息流。当你想集中阅读的时候,切换文章/切换文集/切换分类的操作还是让你想死。

重回 rss

还好 rss 还没死透。rsshub 等渠道还是可以订阅到所有的微信公号文章,甚至还有全文输出的 feed 可以在微信删帖前缓存文章内容。关于如何使用 rss 订阅公众号有时间再写篇文章。

上帝的归上帝,凯撒的归凯撒。

无论是屏幕尺寸的局限,还是多任务系统的羸弱,都注定了手机成不了生产工具。

现在我的微信仍保留的功能:

  • 朋友圈(熟人社交还是绕不过去)
  • 小程序(即用即搜,用完即走)
  • 支付(说句题外话,支付宝 vs 微信支付这件事上我却比较看好微信,毕竟支付宝能做的事微信都能做,微信能做的事支付宝却未必)

除了一些会员类和银行提醒类的公众号,再没关注任何其他公众号。

(全文完)

每月电影2018-09

Posted on 2018-08-09 | In movies

走到尽头 끝까지 간다 (2014)

豆瓣评分: 7.8/10
个人评分: 8.5/10

“这部电影没有设置正面人物和反面人物的对比。出场的所有警察几乎都是某种意义上的“坏警察”。但是这些坏警察都有自己的道德底线,他们贪钱但也能干,他们从罪犯那里捞钱,但不利用职务之便欺负平民,他们绝不杀人。这是“冷硬派”侦探故事的典型设定。更符合真实的复杂人性,而杜绝了脸谱化的说教味道。这是韩国主流电影的又一个致胜之处。题材的广泛和自由的表达。他们永远把叙述故事放到第一位,而非警世和教育。韩国电影之所以产生好故事,一个重要原因就是从不避讳所谓的“阴暗面”。你不去触及,那些暗面仍然存在,而你真的写了一群坏警察,也不会有人认为所有韩国警察都作恶多端。成年人看电影,尤其对主流故事片,看的就是虚幻的故事,进入情境,投射感情,抽离回现实,这就是全部。”

白话版大O算法复杂度

Posted on 2018-08-03 | In 前端 , js

大O算法

via 如何理解算法时间复杂度的表示法 O(n²)、O(n)、O(1)、O(nlogn)等? - 司马懿的回答 - 知乎 侵删

$O(1)$

先从 $O(1)$来说,理论上哈希表就是 O(1)。因为哈希表是通过哈希函数来映射的,所以拿到一个关键字,用哈希函数转换一下,就可以直接从表中取出对应的值。和现存数据有多少毫无关系,故而每次执行该操作只需要恒定的时间(当然,实际操作中存在冲突和冲突解决的机制,不能保证每次取值的时间是完全一样的)。举个现实的例子,比如我的身后有一排柜子,里面有香蕉(代号 B),苹果(代号 A),葡萄(G),现在你说 A,我迅速的就把苹果递过来了;你说 B,我迅速就把香蕉递过来了。就算你再增加菠萝(P)、火龙果(H),但是你说一个代号,我递给你相应的水果这个速度是几乎不会变的。


$O(n)$

至于 $O(n)$ ,这个就是说随着样本数量的增加,复杂度也随之线性增加。典型的比如数数。如果一个人从 1 数到 100,需要 100 秒,那么从 1 到 200,基本上不会小于 200 秒,所以数数就是一个 $O(n)$ 复杂度的事情。一般来说,需要序贯处理的算法的复杂度,都不会低于 $O(n)$ 。比如说,如果我们要设计一个算法从一堆杂乱的考试的卷子里面找出最高的分数,这就需要我们从头到尾看完每一份试卷,显然试卷越多,需要的时间也越多,这就是一个 $O(n)$ 复杂度的算法。


$O(n^2)$

而$O(n^2)$ 是说,计算的复杂度随着样本个数的平方数增长。这个例子在算法里面,就是那一群比较挫的排序,比如冒泡、选择等等。沿着我们刚才的说的那个试卷的例子,等我们找出最高的分数之后,放在一边另起一堆,然后用同样的方法找第二高的分数,再放到新堆上…… 这样我们做 n 次,试卷就按照分数从低到高都排好了。因为有 n 份试卷,所以这种翻试卷,找最高分的行为,我们要做 n 次,每次的复杂度是 $O(n)$ ,那么 n 个 $O(n)$ 自然就是 $O(n^2)$

在比如说构建一个网络,每个点都和其他的点相连。显然,每当我们增加一个点,其实就需要构建这个点和所有现存的点的连线,而现存的点的个数是 n,所以每增加 1,就需要增加 n 个连接,那么如果我们增加 n 个点呢,那这个连接的个数自然也就是 $n^2$ 量级了。

无论是翻试卷,还是创建网络,每增加一份试卷,每增加一个点,都需要给算法执行人带来 n 量级的工作量,这种算法的复杂度就是 $O(n^2)$。


O(nlogn)

然后是 $O(nlogn)$ ,这恐怕是常见算法复杂度里面相对最难理解的,就是这个 log 怎么来的。前面那个 n,代表执行了 n 次 $log(n)$ 的操作,所以理解了$log(n)$,就理解了$nlog(n)$。

$O(logn)$的算法复杂度,典型的比如二分查找。设想一堆试卷,已经从高到底按照分数排列了,我们现在想找到有没有 59 分的试卷。怎么办呢?先翻到中间,把试卷堆由中间分成上下两堆,看中间这份是大于还是小于 59,如果大于,就留下上面那堆,别的丢掉,如果小于,就留下下面那堆,丢掉上面。然后按照同样的方法,每次丢一半的试卷,直到丢无可丢为止。

假如有 32 份试卷,你丢一次,还剩 16 份 ,丢两次,还剩下 8 份,丢三次,就只剩下 4 份了,可以这么一直丢下去,丢到第五次,就只剩下一份了。而 $log_2(32) = 5$ 。也就是我们一次丢一半,总要丢到只有一份的时候才能出结果,如果有 n 份,那么显然我们就有:

$$\frac{n}{2^k} = 1\Rightarrow k = log_2 n$$

也就是大约需要$log_2 n$次,才能得出“找到”或者“没找到”的结果。当然你说你三分查找,每次丢三分之二可不可以?当然也可以,但是算法复杂度在这里是忽略常数的,所以不管以 2 为底,还是以什么数为底,都统一的写成 $log(n)$的形式。

理解了这一点,就可以理解快速排序为什么是 $O(nlogn)$ 了。比如对一堆带有序号的书进行排序,怎么快呢?就是随便先选一本,然后把号码大于这本书的扔右边,小于这本书的扔左边。因为每本书都要比较一次,所以这么搞一次的复杂度是 $O(n)$,那么快排需要我们搞多少次呢?这个又回到了二分查找的逻辑了,每次都把书堆一分为二,请问分多少次手里才能只剩下一本书呢?答案还是 $logn$ 。而从代码的角度来说,在到达大小为一的数列之前,我们也是需要作 $logn$ 次嵌套的调用。

1…345

50 posts
10 categories
46 tags
GitHub E-Mail Twitter Douban Zhihu
© 2014 — 2025 Vincent He