为什么闭包编译器不缩短这个?
我不确定这只是一个错误还是一个预期的功能。
基本上,我有这个小函数(我现在看到 end
这里是蓝色的,但这工作得很好,如果我将其重命名为其他名称,我仍然遇到问题):
function f(a, b) {
var start = Math.min(a, b);
var end = Math.max(a, b);
tb.selectionStart = start;
tb.selectionEnd = end;
};
当闭包编译它时,我get:
function f(a,b){var c=Math.max(a,b);tb.selectionStart=Math.min(a,b);tb.selectionEnd=c};
但是,为什么selectionStart
直接设置为Math.min
,而selecitonEnd
设置为变量(c
>),哪个先声明? tb.selectionEnd=Math.max(a,b)
不是更短吗?
任何想法表示赞赏。
I'm not sure whether this is just a bug or an intended feature.
Basically, I have this tiny function (I now see end
is colored blue here but this works just fine, if I rename it to something else I still have the issue):
function f(a, b) {
var start = Math.min(a, b);
var end = Math.max(a, b);
tb.selectionStart = start;
tb.selectionEnd = end;
};
When closure-compiling it, I get:
function f(a,b){var c=Math.max(a,b);tb.selectionStart=Math.min(a,b);tb.selectionEnd=c};
However, why is selectionStart
set to Math.min
directly, whilst selecitonEnd
is set to a variable (c
), which is declared first? Isn't it shorter to do tb.selectionEnd=Math.max(a,b)
?
Any ideas are appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
编辑:此链接中有一个“官方”答案:
https://web.archive.org/web/20151226143155/http://code.google.com/p/closure-compiler/issues/detail?id=410
我认为作业可以内联一个变量,然后立即使用该变量。但是,如果中间有任何语句无法证明没有副作用,则编译器不会内联它。
在您的情况下,对变量“start”的赋值与“start”的使用仅通过“end”的赋值语句分开。但是,该语句没有副作用,因为 Math.max 是一个内部函数,并且编译器知道它没有副作用。
但是,在您的情况下,对变量“end”的赋值与该变量的使用通过语句分开,该语句是将“start”赋值给属性。现在,我相信编译器并不认为仅仅分配给属性总是没有副作用的;这是因为某些属性在分配时实际上会导致不同的行为,或更改全局状态(例如 RegExp)。在某些系统中,属性分配实际上会触发某些特定于系统的功能(例如硬件接口),而这些功能又可能会产生副作用。
这就是为什么有时当您有这样的代码时:
编译器不会消除前两个语句,因为分配给“bar”可能会产生副作用。
因此,在您的问题中,无法内联变量“end”,因为语句 tb.selectionStart = start; 可能会产生副作用(可能仅在奇怪的情况下)。
如果您将“tb”设置为局部变量,或者编译器可以完全控制的变量(例如一个简单的对象:
var tb = {};
),那么您会发现编译器内联所有的赋值都很好。EDIT: THERE IS AN "OFFICIAL" ANSWER IN THIS LINK:
https://web.archive.org/web/20151226143155/http://code.google.com/p/closure-compiler/issues/detail?id=410
I think an assignment to a variable, followed immediately by usage of that variable, can be inlined. However, if there is any statement in between that cannot be proven to be free of side-effects, then the compiler won't inline it.
In your case, assignment to variable "start" is separated from the usage of "start" only by the assignment statement to "end". However, this statement is free of side-effects since Math.max is an internal function and the compiler knows that it is side-effect-free.
However, in your case, assignment to variable "end" is separated from the usage of that variable by a statement, which is an assignment of "start" to a property. Now, I believe that the compiler does not assume that merely assigning to a property is always side-effect-free; that is because some properties, when assigned, actually cause different behavior, or change global state (such as RegExp). In some systems, property assignments actually trigger certain system-specific features (e.g. hardware interface) that may in-turn contain side-effects.
That is why, sometimes, when you have code like this:
The compiler won't eliminate the first two statements since assignment to "bar" may have side effects.
So, in your question, the variable "end" cannot be inlined because the statement
tb.selectionStart = start;
may have side effects (perhaps only in wierd cases).If you make "tb" a local variable, or something that the compiler has complete control of (e.g. a simple object:
var tb = {};
), then you'll find that the compiler inlines all of the assignments just fine.如果您粘贴此代码,则可以正常工作。
function f(a,b){tb.selectionStart=Math.min(a,b);tb.selectionEnd=Math.max(a,b)};
这是闭包编译器的错误。
if you paste this code, this works.
function f(a,b){tb.selectionStart=Math.min(a,b);tb.selectionEnd=Math.max(a,b)};
i this is a mistake by closure compiler.