compress/obfuscate JavaScript 可以用括号表示吗?

Can bracket notation be used to compress/obfuscate JavaScript?

这主要是出于学术原因,但我很好奇广泛使用括号表示法而不是点表示法是否有任何问题。

一些可能的应用可能包括:

我知道 gzip 压缩可能会使重复数据删除的好处变得无用,并且 JavaScript 的混淆可能是徒劳的,因此我真的只是好奇这种技术用于学术目的的优缺点。

考虑通过以下一系列转换来获取此代码:

(function () {
    var parent, child;
    parent = document.body;

    child = document.createElement('div');
    child.setAttribute('foo', 'bar');
    parent.appendChild(child);
    parent = child;

    child = document.createElement('div');
    child.setAttribute('foo', 'bar');
    parent.appendChild(child);
    parent = child;

    child = document.createElement('div');
    child.setAttribute('foo', 'bar');
    parent.appendChild(child);
    parent = child;

    child = document.createElement('div');
    child.setAttribute('foo', 'bar');
    parent.appendChild(child);
    parent = child;

    child = document.createElement('div');
    child.setAttribute('foo', 'bar');
    parent.appendChild(child);
    parent = child;

    child = document.createElement('div');
    child.setAttribute('foo', 'bar');
    parent.appendChild(child);
    parent = child;

    child = document.createElement('div');
    child.setAttribute('foo', 'bar');
    parent.appendChild(child);
    parent = child;

    child = document.createElement('div');
    child.setAttribute('foo', 'bar');
    parent.appendChild(child);
    parent = child;
})();
  1. 为访问方法生成"constants":

    var createElement = "createElement";
    var setAttribute = "setAttribute";
    var appendChild = "appendChild";
    
  2. 使用这些常量将点符号调用替换为括号符号调用

    child = document[createElement]('div');
    child[setAttribute]('foo', 'bar');
    parent[appendChild](child);
    
  3. 现在 mangler 可以将变量名和方法调用减少为单个字符

    var c = "createElement";
    var s = "setAttribute";
    var a = "appendChild";
    
    child = document[c]('div');
    child[s]('foo', 'bar');
    parent[a](child);
    

缩小后,这个人为设计的示例的大小减少了 44%。

显然这不是手动完成的事情;它可能应该针对更常用的 properties/methods.

的 AST 来完成

全面使用括号符号有什么用吗?

我发现一些 SO 问题说它们是 pretty much the same, while some claim bracket notation involving a variable lookup cannot be JIT optimized and is much slower. And then there are microbenchmarks 两者都显示的那种,所以我不太确定它的真实位置。

我知道 UglifyJS2 compressor options 默认优化 属性 访问,执行相反的操作:将括号表示法转换为点表示法。我只是不知道背后的原因,除非真的只是为了多存3个字符。

它确实会导致某些引擎出现 JIT 问题。一个 much simpler benchmark 不会混淆很多东西就证明了这一点(如下)。所以你 可以 这样做,但你必须接受性能成本,这在某些引擎上很重要(在 Chrome 上将 属性 访问速度降低约 64% ,例如;~86% 在 IE11 上,在我下面的简单测试中)。

准备:

var obj = {};
var i;
for (i = 0; i < 1000; ++i) {
    obj['prop' + i] = 'value ' + i;
}
var name = "prop257";

测试obj.prop257

if (obj.prop257 !== "value 257") throw "Error in test";

测试obj[name]

if (obj[name] !== "value 257") throw "Error in test";

Chrome、Firefox、IE11 上的运行结果:

在 Chrome (V8) 和 IE11 (JScript) 上,性能都大幅降低。 Firefox (SpiderMonkey) 受到影响,但没有那么严重。