今天看到项目里同事引用的一个库‘ keyMirror’,没错,就是react.js里的。
老惯例,翻了源码看了一遍,不是很难看懂,但是完全没有头脑,这个库是干啥的。
又继续Google,看到最多的解释如下:
用 KeyMirror 的原因就是因为第三种(Advanced,最优处理)模式下,会将 Map<K, V> 格式的 K 进行压缩,比如:
// 源代码
var kv = {
GET_USER: null,
SET_USER: null,
REMOVE_USER: null
};
// 编译后( 整理了一下格式,实际情况下会再添加压缩 )
var a = {
a: null,
c: null,
b: null
};
在引用的时候就变成:
// 源代码
var kv_new = keyMirror(kv);
console.log(kv_new.GET_USER);
// 编译后
var a = keyMirror({ a: null, c: null, b: null });
console.log(a.a);
这样如果在没有进行 KeyMirror 处理的时候,引用就会错误了,这种编译模式破坏了我们的代码,要避免这个编译导致的 Key 改变,可以给 Key 添加引号(单、双均可),其实能够分析的就是静态的属性,动态基本上是不好做好的,可以这样理解。
// 源代码
var kv = {
'STOP_USER': null
};
// 编译后
var a = {
STOP_USER: null
};
然而我们这样做了之后,代码就得不到更有效的压缩,这样 Closure Compiler 的功能就被削弱了,所以引入 KeyMirror 既能保证代码前后的功能一致,也能享受压缩带来的性能提升。
恕我愚钝,我感觉他已经解释的很到位,但是我怎么就是不理解呢,上面说‘这样如果在没有进行 KeyMirror 处理的时候,引用就会错误了’ 怎么就错误了呢,源码正常些,CC编译,没有问题啊 ,这个keyMirror理解不上去,感觉晚上都睡不着了,希望路过的帮忙点播一下,谢谢了。
keyMirror 顾名思义,就是为 keys 复制一份。源码也很简单,就是把 keys 遍历一遍得到
{a: 'a', b: 'b'}
这样的形式。为什么要复制一份呢,是为了动态使用 key。
上面也提到 Closure Compiler advanced mode 下,对象的 keys 会压缩掉。但上面的例子并不会出错,因为 Closure 会聪明的把属性引用的地方也换掉,比如
会得到
所以如果你想在运行时动态使用某个 key 就不行了
会得到
所以 keyMirror 在运行时保留了一个对照关系,相当于一个 enum,就可以动态使用 key
就可以得到正确的结果