Google的Closure Compiler遵循哪些规则来决定enum
是否内联?
当我通过Closure Compiler运行代码时,JSDoc annotation enum
类型未内联。然而,当我创建一个简化的示例时,enum
类型被内联,因为这个无意义的示例将演示:
var my_name_space = (function () {
'use strict';
/** @enum {number} */
var TASK_STATUS = {
REJECT: -1,
UNKNOWN: 0,
APPROVE: 1
};
function init_(a) {
if (a === TASK_STATUS.UNKNOWN) {
alert("Reject");
a = TASK_STATUS.REJECT;
} else if (a === TASK_STATUS.APPROVE) {
alert("Unknown");
a = TASK_STATUS.UNKNOWN;
} else {
alert("Approve");
a = TASK_STATUS.APPROVE;
}
return a;
}
return { init: init_};
}()); // my_name_space
my_name_space.init(-1);
Closure的输出:
var my_name_space=function(){return{init:function(a){0===a?(alert("Reject"),a=-1):1===a?(alert("Unknown"),a=0):(alert("Approve"),a=1);return a}}}();my_name_space.init(-1);
事实上,无论有没有JSDoc标题,都会出现衬里。
请解释衬里在什么条件下不会发生,或者甚至更好,请修改以上内容,以证明衬里不会发生。
我正在使用'简单'优化级别。
答案 0 :(得分:3)
首先,枚举不是用于优化目的的特殊对象,但是,@enum对于类型检查很有用,并且具有用于此目的的特殊规则。
至于内联,有很多东西可以阻止内联,展示所有可能性是不合理的,但我可以告诉你为什么它们可能不是:
这些都归结为编译器无法确定它可以:
也就是说,如果你有一个简单的局部定义,并且你只引用了值而不是对象本身,并且值本身是简单的常量(数字,布尔值),它总是会被内联。
答案 1 :(得分:1)
首先,我相信你必须使用ADVANCED_OPTIMIZATIONS从内联获得任何胜利。您当前的代码目前对ADVANCED OPTIMIZATIONS无效,因此我进行了修改以使其正常工作。
/** @enum {number} @const */
var TASK_STATUS = {
REJECT: -1,
UNKNOWN: 0,
APPROVE: 1
};
/**
* @param {TASK_STATUS} a
*/
function init_(a) {
if (a === TASK_STATUS.UNKNOWN) {
alert("Reject");
} else if (a === TASK_STATUS.APPROVE) {
alert("Unknown");
} else {
alert("Approve");
}
}
init_(TASK_STATUS.REJECT);
输出:
alert("Approve");
闭包编译器无法内联代码的原因有几个原因。 Closure编译器不会一直深入到您的代码中 - 它通常使用您传入的类型信息来做出决策。通过对象表达式传递函数效果不佳。 (即,通过对象文字传递init函数)
其次,你的init函数有副作用(分配a)。由于闭包编译器不知道什么是真正被更改的(没有类型信息),所以它做了安全的事情,并没有内联函数。
高级模式下的Closure编译器是一个野兽。这需要一些时间来适应。