理解不了keyMirror

 今天看到项目里同事引用的一个库‘ 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理解不上去,感觉晚上都睡不着了,希望路过的帮忙点播一下,谢谢了。

阅读 5.6k
1 个回答

keyMirror 顾名思义,就是为 keys 复制一份。源码也很简单,就是把 keys 遍历一遍得到 {a: 'a', b: 'b'} 这样的形式。

为什么要复制一份呢,是为了动态使用 key。

上面也提到 Closure Compiler advanced mode 下,对象的 keys 会压缩掉。但上面的例子并不会出错,因为 Closure 会聪明的把属性引用的地方也换掉,比如

var obj = {thisIsKey1: 2, thisIsKey2: '2'}
obj.thisIsKey1 += 2
console.log(obj, obj.thisIsKey1)

会得到

var c = {a:2, c:"2"};
c.a += 2;
console.log(c, c.a);

所以如果你想在运行时动态使用某个 key 就不行了

var obj = {thisIsKey1: 2, thisIsKey2: '2'}
obj.thisIsKey1 += 2
function somehowGetKey (i) { return ['thisIsKey1', 'thisIsKey2'][i] }
console.log(obj, obj[somehowGetKey(0)])

会得到

var c = {a:2, c:"2"};
c.a += 2;
console.log(c, c.thisIsKey1);

所以 keyMirror 在运行时保留了一个对照关系,相当于一个 enum,就可以动态使用 key

var keys = keyMirror({thisIsKey1: null, thisIsKey2: null})
var obj = {}
obj[keys.thisIsKey1] = 2
obj[keys.thisIsKey2] = '2'
function somehowGetKey (i) { return [keys.thisIsKey1, keys.thisIsKey2][i] }
console.log(obj, obj[somehowGetKey(1)])

就可以得到正确的结果

var d = c({b:null, a:null}), e = {};
e[d.b] = 2;
e[d.a] = "2";
console.log(e, e[d.a]);
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题