簡體   English   中英

Closure Compiler並不總是內聯枚舉。 為什么?

[英]Closure Compiler does not always inline enums. Why?

Google的Closure Compiler遵循哪些規則來決定enum是否內聯?

當我通過Closure Compiler運行我的代碼時,JSDoc 注釋 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);

關閉的輸出:

 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標頭。

請解釋襯里在什么條件下不會發生,甚至更好,請對上面的內容進行修改,以證明襯里不會發生。

我正在使用'簡單'優化級別。

首先,枚舉不是用於優化目的的特殊對象,但是,@ enum對於類型檢查很有用,並且具有用於該目的的特殊規則。

至於內聯,有很多東西可以阻止內聯,展示所有可能性是不合理的,但我可以告訴你為什么它們可能不是:

  • 枚舉對象被定義為對象上的屬性,無法將其分解為變量(ADVANCED模式有助於此處)
  • 枚舉是在全局變量上定義的(ADVANCED模式在這里有幫助)
  • 枚舉對象的別名方式是別名本身無法刪除(將枚舉對象傳遞給無法內聯的函數,將枚舉對象賦值為全局值)。
  • 迭代枚舉鍵/值(for-in等)
  • 枚舉對象被覆蓋

這些都歸結為編譯器無法確定它可以:

  • 刪除對象並將其替換為單個值
  • 內聯這些值

也就是說,如果你有一個簡單的局部定義,並且你只引用了值而不是對象本身,並且值本身就是簡單的常量(數字,布爾值),它總是會被內聯。

首先,我相信你必須使用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編譯器是一個野獸。 這需要一些時間來適應。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM