进入一辆在烈日下暴晒了几个小时的大巴几秒后——马上体会到父母把孩子留在封闭的小车中到底有多危险了——差点当场烤熟了。
使用免费产品时,等价交换的筹码就是用户自己。歌手、演员等价交换付出的是自己的作品,而偶像的作品则是自己,这里包含了个人外在形象,表现出来的才艺;前者可以说是卖艺不卖身,后者则是“卖身”。
年少轻狂只想构建理想乡,却发现一文钱难倒英雄,毕竟未经历战争的人会发起战争来实现“理想”,而经历过战争的人则稳定压倒一切。
进入一辆在烈日下暴晒了几个小时的大巴几秒后——马上体会到父母把孩子留在封闭的小车中到底有多危险了——差点当场烤熟了。
使用免费产品时,等价交换的筹码就是用户自己。歌手、演员等价交换付出的是自己的作品,而偶像的作品则是自己,这里包含了个人外在形象,表现出来的才艺;前者可以说是卖艺不卖身,后者则是“卖身”。
年少轻狂只想构建理想乡,却发现一文钱难倒英雄,毕竟未经历战争的人会发起战争来实现“理想”,而经历过战争的人则稳定压倒一切。
EventSource 是浏览器端配合服务端事件(Server-Sent Events)使用的技术。和 WebSocket 相比,服务端事件是单向推送,而 WebSocket 是双向通信。
// 第二个参数是可选的,withCredentials 目前用于跨域 cookie,默认 false
const es = new EventSource(url, { withCredentials: true });
es.addEventListener('error', err => console.error(err));
// 监听 message 事件
es.addEventListener('message', evt => console.log(evt.data));
// 监听 type/custom 事件
es.addEventListener('type/custom', evt => console.log(evt.data));
EventSource 要求的是持续不断的输出,如果请求正常地结束终止了,那么客户端会再次自动发起连接,除非显式地调用 close()
方法来结束连接。
服务端的实现是返回标记为 Content-Type: text/event-stream
的持续内容,其内容的基本格式是:
event: evt-type
data: any message
其中,event
对应 EventSource 监听的事件类型,但该内容是可选的,如果没指定 event,那么则被 message
事件监听(可简化为 es.onmessage
)。
紧邻的 data
字段会把内容合并起来,连接内容是一个空行。
直接以 :
开头的内容则是注释,不被解析使用。
可以代理一个对象,对读取、赋值等操作做拦截,从而可额外地做一些事情,对于没有拦截的操作,则按原对象操作调用。
let p = new Proxy(target, handler);
通过 handler 来提供以下方法(this
指向 代理后的对象,该对象的 [[handler]]
指向 handler):
get(target, prop, receiver)
拦截属性读取操作set(target, prop, val, receiver)
拦截设置属性值操作has(target, prop)
可以看作是对 in
的操作的拦截apply(target, thisArg, args)
拦截函数的调用,包括普通调用和 apply
和 call
等。construct(target, args, newTarget)
拦截 new
操作符defineproperty(target, prop, descriptor)
拦截 Object.defineProperty
的操作deleteProperty(target, prop)
拦截 delete
操作getOwnPropertyDescriptor(target, prop)
拦截 Object.getOwnpropertyDescriptor
getPrototypeOf(target)
拦截原型对象的读取,包括 Object.getPrototypeOf()
、__proto__
以及 instanceof
等isExtensible(target)
拦截 Object.isExtensible()
ownKeys(target)
拦截 Object.getOwnPropertyNames()
以及 Object.keys()
等preventExtensions(target)
拦截 Object.preventExtensions(obj)
setPrototypeOf(target, proto)
拦截 Object.setPrototypeOf
receiver,Proxy 或继承 Proxy 的对象,最初被调用的对象,通常就是 proxy 自身。但如果对象本身无该属性,原型链上有 Proxy 对象,那么这时对象本身就作为 receiver 参数传进来了。1
不仅使用于 Object,也使用于 Reflect,拦截具体对应的操作可能有所区别
Proxy.revocable(target, handler)
创建一个 proxy 并返回撤销该 proxy 的方法。
const { proxy, revoke } = Proxy.revocable(target, handler);
// .. do something with proxy
// 撤销代理
revoke();
人类能走到今天,是心底那渴望活得更好的念头,是利己之心。所以,在大千世界中看到有更好的东西时,总希望自己也能拥有。
但,路要一步步走,饭要一口口吃。大多数人没法 21 天变成编程高手,一个社会没法还在以小康为目标的情况下提供世界一流国家的福利。
以这为目标,订下五年计划、一年计划,一步步走,一步步前进,这才是可行之法。
谁都有能力提出自己的不满、社会的不到位之处,能提出问题很好,倘若能进一步思考甚至得出可行的解决方案,这会功德无量。
中兴事件、华为事件再次提醒我们,即使这是一个全球联通的社会,但自己还是需要分散风险,不要把鸡蛋放在一个笼子里,甚至核心技术自己需要有积累。
大到一个国家,核心技术就是必须要掌握的,从民生、能源、新技术都必须掌握,否则当世界霸主利用其影响力压制时将无法生存下去。同时,掌握了技术也不要断绝交流,否则又会陷入夜郎自大的危境。
对电子竞技基本没有了解,不过偶尔玩玩游戏,经常看看直播。
电子竞技和普通的体育竞技有点不同,体育竞技,在一段时间内——特别是赛季进行中,规则和竞技内容都是比较固定不变的。但电子竞技不同,先不弹游戏的变更,只说同一个游戏。
一个电子游戏的竞技,在赛季中,规则还好,胜负的条件基本不会变更。但内容就不一定了,电子游戏会经常迭代更新,甚至赛季中就更新版本。
电子游戏的竞争,看上去就是一场“战争”,所以需要知己知彼。
需要了解游戏的内容,磨练自己的战术体系,探测对手的战术体系。而游戏的迭代更新,容易造就之前搭建的战术体系随着版本变更而不再适用,如果没能迅速在新版本中重新构建自己的战术,那么就很容易出现一支队伍之前战无不胜突然在新版本中就无所适从的状况出现。
虽然自己技术过硬才是重点,但涉及到对抗,那就必须要了解对手,了解他们的英雄体系以及基于这些因素而展现出来的战术体系。越是风光,越被别的竞争对手认真研究。相反,站在顶峰的人,容易只针对自己认为的对手来下功夫,而别的队伍则忽略了。这就容易看到所谓的“黑马”,如果黑马不仅仅是战术新颖,还用有了过硬的技术,那么就会变为太阳而不再是流星。
现代的战争是全方位的战争,成型的电子竞技也是全方位的竞争。选手需有练英雄练技术跟进版本变更,教练等需要基于选手技术以及版本来构建阵容和战术体系,后勤团队需要做好包括队员生理保养、心理调整等的俱乐部后勤支持,还有其它团队需要做好盈利问题。
一代版本一代神,每支队伍在输之前都是最强的组合。
命令行工具在输出时,如果是简单的进度更新,可以使用 \r
和 \b
来达成刷新行的效果,但如果要更复杂些的如字体颜色、背景颜色、光标位置移动等功能,那就需要使用 ANSI 转移序列了。
已有不少成熟的命令行工具库,如 Readline、JLine 和 Python Prompt Toolkit,基于这些库创造了如 mycli 和 ipython 等好用的工具。
ANSI 转义序列有比较悠久的历史,不同平台支持的功能不完全一致,这里学习到的是比较简单常用的,包括字体颜色、背景色和其它装饰的富文本和光标操作。
\u001b
即 ESC 的 ASCII 码,\u001b[0m
是清除之前的设定。
适用于 *nix 的系统。
\u001b[?m
,其中 ? ∈ [30, 37]
。
\u001b[30m
\u001b[31m
\u001b[32m
\u001b[33m
\u001b[34m
\u001b[35m
\u001b[36m
\u001b[37m
\u001b[0m
在 8 色的基础上对字体加粗,颜色加亮,得到另外 8 种,加起来就是 16 色。
\u001b[?;1m
,其中 ? ∈ [30, 37]
。
\u001b[30;1m
\u001b[31;1m
\u001b[32;1m
\u001b[33;1m
\u001b[34;1m
\u001b[35;1m
\u001b[36;1m
\u001b[37;1m
const out = process.stdout;
function colors8(pre, post, startCode = 30) {
const codePointA = 'A'.codePointAt(0);
let i = 0;
while (i < 8) {
const colorCode = startCode + i;
const char = String.fromCodePoint(codePointA + i);
out.write(`{pre}{colorCode}{post}{char} `);
i++;
}
console.log('\u001b[0m');
}
function fgColors8() {
colors8('\u001b[', 'm');
}
function fgColors8Bright() {
colors8('\u001b[', ';1m');
}
fgColors8();
fgColors8Bright();
macOS Mojave 下,Charles 捕捉不到 http://localhost
下的流量,需要使用 http://localhost.charlesproxy.com
形式的域名,并添加绑定 127.0.0.1 localhost.charlesproxy.com
。这是因为可能有些系统设置了 localhost 不通过代理。