今天有朋友问了 “KeyMirror” 这个库有什么用的问题,其实这个问题并不难,这里扫一下盲区。
会按照下面这个逻辑来展开,彻底理解一下:
KeyMirror 有什么用?
Google Closure Compiler 是什么?
KeyMirror 解决了什么问题,好处是什么?
KeyMirror 的源码是什么样子?
用 Gulp 配置一个压缩任务,测试一下 Google Closure Compiler.
直观的来看一下,测试代码如下:
var kv = { GET_USER: null, SET_USER: null, REMOVE_USER: null }; // keyMirror 是对应的测试方法 var kv_new = keyMirror(kv); console.log(kv); console.log(kv_new);
最后输出的结果如下:
然后就是相当于重新生成了一个 key == value
的结构。但是肯定就会想,为毛要多此一举呢?其实这个跟 Google Closure Compiler 的 Advanced 模式有关。接下来我们来看一下它是什么。
如果有兴趣的朋友可以直接跳到文章后面,使用 Gulp 把环境搭起来测试,因为下面的地址都要翻墙!
有官方文档,需要翻墙: 文档 。
大致的意思就是说,Closure Compiler 是一个工具,这个工具能够编译 JavaScript 代码,编译后的代码能下载更快并且执行也更快。它能够解析你的 JS 代码,并且去分析它,能移除没有使用到的代码,重写、压缩得到最终的生产环境下的 JS 代码。它拥有检测语法、变量声明、类型定义以及对 JS 语言缺陷做一些检查。
总之,这就是做 JS 编译并且做一些常用检测的一款工具。
具体能够在线体验,也需要翻墙, 在线体验地址
这个工具有三种模式:
只去空格( Whitespace only )
简单处理( Simple )
最优处理( Advanced )
用 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
既能保证代码前后的功能一致,也能享受压缩带来的性能提升。
既然知道了上面的背景和原因,我们来看下如何实现一个这玩意,其实特别简单的功能,就是让 K,V 相等。
var keyMirror = function(obj) { var ret = {}; var key; // 对参数的控制,必须是对象 if (!(obj instanceof Object && !Array.isArray(obj))) { throw new Error('keyMirror(...): Argument must be an object.'); } // 简单的遍历,将对应 K 赋值给 Map[K] for (key in obj) { // 只拷贝自己的属性 if (!obj.hasOwnProperty(key)) { continue; } ret[key] = key; } return ret; };
这里需要用到两个东西:gulp、google-closure-compiler-js
直接上代码:
var gulp = require('gulp'); var compiler = require('google-closure-compiler-js').gulp(); gulp.task('go', function () { return gulp.src('./index.js') .pipe(compiler({ // 编译等级,不区分大小写哈 compilation_level: 'advanced', warning_level: 'VERBOSE', output_wrapper: '(function(){/n%output%/n}).call(this)', js_output_file: 'index.advanced.min.js', create_source_map: true })) .pipe(gulp.dest('.')); });
// 测试代码 var kv = { GET_USER: null, SET_USER: null, REMOVE_USER: null }; // 必须要和 keyMirror 代码一起,不然会被提示 error。 // Error: Compilation error, 1 errors var kv_new = keyMirror(kv); console.log(kv); console.log(kv_new);
亲测非常的慢,不知道是不是我姿势不对,advanced 模式都是花费 12s 左右,simple 模式也花费 8s 左右,第一次测试我还卡挂了,所以基本上代码量上去了感觉是不适用的。
参考地址:
[1] https://developers.google.com/closure/compiler/
[2] https://github.com/facebook/react/issues/1639
[3] https://gist.github.com/zpao/d25251b139647a79cddf
[4] https://www.npmjs.com/package/keymirror
原文出自: http://60sky.com/post/why-key-mirror.html