4

我不确定这只是一个错误还是一个预期的功能。

基本上,我有这个小功能(我现在看到end这里是蓝色的,但这工作得很好,如果我将它重命名为其他东西我仍然有问题):

function f(a, b) {
    var start = Math.min(a, b);
    var end = Math.max(a, b);

    tb.selectionStart = start;
    tb.selectionEnd = end;
};

闭包编译时,我得到:

function f(a,b){var c=Math.max(a,b);tb.selectionStart=Math.min(a,b);tb.selectionEnd=c};

但是,为什么直接selectionStart设置为Math.min,whileselecitonEnd设置为变量(c),是先声明的?做起来不短tb.selectionEnd=Math.max(a,b)吗?

任何想法表示赞赏。

4

2 回答 2

4

编辑:此链接中有一个“官方”答案: 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)。在某些系统中,属性分配实际上会触发某些特定于系统的功能(例如硬件接口),而这些功能又可能包含副作用。

这就是为什么有时当你有这样的代码时:

foo.bar = 1;
foo.bar = 2;
foo.bar = 3;

编译器不会消除前两个语句,因为分配给“bar”可能有副作用。

因此,在您的问题中,变量“end”不能被内联,因为该语句tb.selectionStart = start;可能有副作用(也许仅在奇怪的情况下)。

如果你将“tb”设置为局部变量,或者编译器可以完全控制的东西(例如一个简单的对象var tb = {};:),那么你会发现编译器内联所有的赋值都很好。

于 2011-04-06T12:56:11.907 回答
3

如果您粘贴此代码,则可以。

function f(a, b) {
    var start = Math.min(a, b);
    tb.selectionStart = start;

    var end = Math.max(a, b);
    tb.selectionEnd = end;
};

function f(a,b){tb.selectionStart=Math.min(a,b);tb.selectionEnd=Math.max(a,b)};

我这是闭包编译器的错误。

于 2011-04-06T11:28:57.193 回答