192019.2

这一波操作很溜

今日陆续看到一些消息,全部来自政策层面,例如,放开针对个人信用融资放贷的“银行版QE”,大湾区发展规划出台,而这波操作正逢08年经济危机过去10年后。

资本主义经济危机有10年一个小周期的规律,而作为资本主义经济的美国,它的经济动向决定了整个世界经济的景气。这两年整个世界遇到的经济问题,无非是经济周期大背景下的具体体现。之所以有这样的周期规律,主要的根源在于,在每一次经济危机发生时,政府出台的政策通过透支未来的资源或经济内置潜力来解决眼下的经济危机,最为令人印象深刻的就是“4万亿刺激计划”,从本质上讲,就是通过货币超发,提供更低门槛的贷款,刺激企业生产和民众消费,从而兜住经济下行可能跌穿经济承受能力的可能性。但是,通过超发放贷的方式,本质上还是透支和产生泡沫的行为,因为贷款必须要还,放出去的钱在市面上引起通胀,但企业和个人仍然要为贷款买单,出来混总是要还的。因此,在之后的几年内,整个国家经济都在消化这些泡沫,整个社会经济呈现出两种趋势:1)由于还贷压力带来的逐步紧缩;2)由于经济惯性带来的持续泡沫。

面对这两种趋势,很有可能在下一个周期到来的时候,泡沫还没有消化完。这种情况下,必须出台更猛的政策,透支更底层的信用来稳住经济发展。而当前这一波政策出台,很显然属于这种情况,不过从泡沫本身而言,中国最大的泡沫来自房地产和信贷。中国社会比其他国家社会更能找到泡沫点,普通人会妖魔化经济泡沫,例如“房价永远不可能跌”“P2P暴雷”等现象,已经司空见惯。

让经济泡沫破掉并不一定是坏事,一但该破的泡沫破灭,就可以有更大的空间来调整经济结构。但问题在于,没有一届政府敢于这样做,因为每一届政府有任期,一旦任期内致使经济倒退,人民生活受到影响,必然会在历史上留下骂名。而巧合的是,几乎每一届政府都能找到办法,除了少数,例如胡弗政府。一旦政府没有预估到实际情况,并提前采取行动,即使在危机发生后采取更大规模的措施,也无济于事,因为当经济泡沫破灭之后,人们的情绪会左右某些政策的实际实施效果,例如经济救市,人们不会因为经济宽松而加大消费,相反会首先解决自己的负债问题。

中国在这一点上有一个特点,就是居民的负债表长期为0,这是中国居民消费的一个特点,重储蓄,轻负债。但不可否认的是,08年经济危机之后,不少企业和地方政府的负债攀升,在影子银行等所谓信贷机构的催生下,居民负债也达到了史无前例的程度。可以预见的是,只要中国经济持续下去,这一趋势会越来越明显,整体负债会愈来愈高,直到遇到类似美国20年代或日本90年代的危机。

但就微观而言,这一波政策操作,再次释放了金融能力,会有一波新的民间企业通过信贷扩大规模,从而带动就业和消费。对于居民而言,一种方式是通过创办企业通过信贷的方式达到目标,一种是通过投资将自己的资金转化为实际的社会经济增长而获得回报。但就目前来看,这一波操作是否能够起到带动作用,还很难讲,主要还要看企业是否相信国家政策,是否愿意冒这个险去协助完成这次宏观经济操作。

08:58:56 已有0条回复
162019.2

昨晚改到2点多,对HelloType抛出的错误信息再次进行了整理。之所以要花那么多时间去整理,是因为我发现在平时使用的时候,特别依赖这个抛出的错误来判断真实的错误情况。之前输出的错误在展示具体类型的时候,丢掉了细节,在发现错误,回去看具体的原始数据和类型容器的时候无法完整的看到,而经过改造后,可以看到更具体的内容,又便于调试。

接下来还想做一件事,就是对traces进行升级,可以通过stack找到该trace产生的位置,并将这些trace的stack加入到eorror的独立属于中去,这样可以定位每一个判决在代码中的位置。

12:12:11 已有0条回复
152019.2

慎用import/export嵌套

今天遇到一个极其蛋疼的情况,两个js模块,相互循环引用,造成一个bug。

// a.js
import { SomeB } from './b.js'

export const SomeA = 'aaa:' + SomeB
// b.js
import { SomeA } from './a.js'

export const SomeB = 'bbb:' + SomeA

接下来我在一个文件中使用模块b:

// c.js
import { SomeB } from './b.js'

console.log(SomeB)

你知道会得到什么结果吗?总之是得到错误的结果。在chrome中直接运行会直接报错,说a.js中的SomeB未定义。这……

其实这是真的。因为a.js和b.js相互引用,导致的结果就是,无论是谁,在执行的时候,都需要另外一个模块加载完成才能进行自己的解释。这就很蛋疼:

c.js -> b.js -> a.js -> b.js -> a.js ...

而js解释器一般会灵活处理,即不会死循环的去如此解释,而是在发现循环的时候,就直接结束,即:

c.js -> b.js -> a.js $

但是,当a.js需要b.js所带来的上下文时,实际上b.js还没有被解释,因为b.js依赖a.js的解释结果,因此,在a.js中,SomeB被认为是not defined,这已经不是TypeError,而是ReferenceError,也就是在上下文中,该变量未被声明。

因此,千万不要循环引用啊,切记切记。

17:01:03 已有0条回复
022019.2

现代浏览器已经不需要babel和webpack了

在Robust中,我提到说babel和webpack具有时间节点上的意义,但是现在看来,这个时间节点已经过去,它们可以功成身退了。怎么讲?我们使用babel的主要目的,是将js高版本的语法编译为低版本语法,以在前几年时间里,浏览器还没有跟上节奏,很多新版本特性没支持的情况下,解决临时问题。但是,现在不同了,大部分新特性浏览器都会提前埋好,标准出来时,浏览器已经支持了。而且,很多特性我们之前不敢用,我们担心某些浏览器不支持。但是随着时间的流逝,可以确定的是,两年前的特性浏览器一定已经支持了,只是新发布的标准还是比较难确定的。而比较激进的chrome,则大部分我们需要的特性都是支持的。我觉得,ES2018发布之后,我们就可以不需要babel了,因为99%以上的语法浏览器都支持了,其中最重要也是最慢的,就是object spread/resest这个特性:

var obja = { a: 1 }
var objb = { ...obja, b: 2 }

这个特性已经成为标准的一部分,那么基本上我们需要的特性都有了。我们对ES标准,已经没有太大的要求,只希望它慢慢迭代,更正和修复一些小问题了。

除了特性支持以外,模块引入也已经被支持了。我们不需要通过webpack来打包,支持我们写的import/export语法,浏览器原生支持这些语法。

<sricpt type="module">
import SomeModule from 'http://xxx/somemodule.mjs'
</script>

它的工作方式非常符合我们的理解,这使得我们完全可以放弃AMD那种复杂的模块引入方式,这就让曾经传言浏览器内置require.js这样的传言不攻自破。

另外,还有一个特性,即tagged string tempaltes,这个特性可以直接替代jsx,ES本身就支持类似jsx那样的语法,只是需要一个tag解析函数而已,而这些都是在运行时可以完成的。举个例子:

import { jsx } from 'https://xxx/jsx'

const vdom = props => jsx`<div class="${props.className}">${props.children}</div>`

ES本身就支持通过一个函数去解析字符串,然后返回任意形式的数据。这样一来,字符串模板本身就可以实现和jsx相同的功能。当然,还是有一点不同,jsx是需要编译的,编译后直接生成代操作的程序代码,在运行的时候,不需要经过解析解析模板这个步骤,省了一些性能。而如果运行时去解析字符串模板,可以缓存,因为字符串本身的结构不会变化,但是比较复杂的结构,还是需要每次都去进行解析模板,所以,性能上会有消耗。但无论如何,ES已经给了我们这样的能力,我们完全可以抛开babel,99%的代码都可以运行。

11:21:59 已有0条回复