gpt4 book ai didi

javascript - Closure Compiler ADVANCED_OPTIMIZATIONS 和函数封装

转载 作者:行者123 更新时间:2023-11-29 22:32:56 24 4
gpt4 key购买 nike

使用Google Closure Compiler (ADVANCED_OPTIMIZATIONS),似乎当代码封装在一个函数中时,有一些高级优化是做不到的。

(function(){
var db = {};
/** @enum {number} */
db.col = { One: 0, Two: 3, Three: 4, Four: 1, Five: 2, Six: 7, Seven: 8 };
alert(db.col.Two); alert(db.col.Three); alert(db.col.Four);
})();

var db = {};
/** @enum {number} */
db.col = { One: 0, Two: 3, Three: 4, Four: 1, Five: 2, Six: 7, Seven: 8 };
alert(db.col.Two); alert(db.col.Three); alert(db.col.Four);

编译为

var a={a:{f:0,d:3,c:4,b:1,e:2,h:7,g:8}};alert(a.a.d);alert(a.a.c);alert(a.a.b);
alert(3);alert(4);alert(1);

函数封装阻止高级变量替换的原因是什么?有什么方法可以让两个代码片段编译成相同的输出吗?

最佳答案

一种可能的解释:

您所指的 Closure 编译器的功能是“ namespace 扁平化”,这是编译器试图规避与长链 namespace 中的查找相关的成本。

例如,foo.bar.baz.hello.doSomething(); 需要导航四个对象的链才能找到 doSomething 属性。通过命名空间扁平化,属性被扁平化为 a,调用被替换为 a(); —— 一个显着的改进。

因此,在您的第二种情况下,真正有问题的并不是对象 db。我相信会发生以下优化链:

var db = {};
db.col = { One: 0, Two: 3, Three: 4, Four: 1, Five: 2, Six: 7, Seven: 8 };
alert(db.col.Two); alert(db.col.Three); alert(db.col.Four);

命名空间的扁平化:

var a=0, b=3, c=4, d=1, e=2, f=7, g=8;
alert(b); alert(c); alert(d);

那么,由于 b,c,d 都只使用了一次,所以它们是内联的:

var a=0, e=2, f=7, g=8;
alert(3);alert(4);alert(1);

最后,丢弃未使用的变量 a,e,f,g。

然而,尽管这在全局范围内工作得很好,但当对象在闭包内定义时编译器必须格外小心,因为闭包内可能有函数调用捕获在闭包内定义的对象。闭包内的一切都必须是“无副作用”的,以便编译器“扁平化”对象并消除对象;否则,如果内部函数调用引用的捕获对象不再存在,代码将中断。

alert() 不被认为是无副作用的。因此,假设 dbdb.col 可能会因调用 alert 而被修改。之后的任何可能不是无副作用的代码都可以引用修改后的 dbdb.col,因此不得删除这些对象。 注意:如果 alert() 调用是非无副作用的最后一次调用,则这不适用。

要启用 namespace 扁平化,您必须将对象移出闭包并在无法捕获的全局范围内定义它们:

  1. 将对象定义移到函数闭包之外(因此使它们成为命名空间)
  2. 避免使用对象表示法

这会起作用:

var db = {};    // Put the namespace outside, making it global
db.col = {}; // Put sub-namespaces outside also

(function(){
db.col.One = 0; // Avoid using object notation
db.col.Two = 3;
db.col.Three = 4;
db.col.Four = 1;
db.col.Five = 2;
db.col.Siz = 7;
db.col.Seven = 8;

alert(db.col.Two); alert(db.col.Three); alert(db.col.Four);
})();

一个好的实验是:

(function() {
var db = {};
db.col = { One: 0, Two: 3, Three: 4, Four: 1, Five: 2, Six: 7, Seven: 8 };
alert(db.col.Two); // Only one call
var test = db.col.Three + db.col.Four; // This statement is side-effect-free
})();

你瞧!它有效:

alert(3);

但是:

(function() {
var db = {};
db.col = { One: 0, Two: 3, Three: 4, Four: 1, Five: 2, Six: 7, Seven: 8 };
alert(db.col.Two); // First call, anything afterwards is suspect
alert(db.col.Three); // Oops! Cannot eliminate db or db.col!
})();

有效:

var a={a:{f:0,c:3,b:4,e:1,d:2,h:7,g:8}};alert(a.a.c);alert(a.a.b);

关于javascript - Closure Compiler ADVANCED_OPTIMIZATIONS 和函数封装,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6285567/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com