2011-09-12 42 views
5

廣泛閱讀JavaScript中的各種斷言框架。有沒有任何一種事實上/最常見的「標準」庫/框架?當選擇一個 - 哪些點最值得注意?JavaScript中的斷言

我能想到的(唯一)需求是在生產模式下接近零的性能開銷。

+0

也許只是一個措辭故障 - 但零生產表現會很糟糕。也許你的意思是接近於零的開銷。 –

+4

斷言?嗯,'console.assert()'? –

+0

@Marc乙:你說得對:)修復它。 – BreakPhreak

回答

6

兩個可能的解決方案:

有你的構建腳本版本刪除斷言線。

讓你的構建腳本覆蓋斷言功能,所以它只是一個空函數。對此的缺點是,如果斷言調用具有邏輯[又名assert(x> 100,「foo」)],那麼該邏輯[x> 100]仍將運行。

+0

同意!所以,沒有辦法使參數計算無效,對嗎? – BreakPhreak

+0

唯一的方法就是將其刪除,或將斷言語言更改爲更像jUnit/JSUnit/QUnit,其中您有不同的檢查assertTrue,assertFalse,assertEquals,assertNotSame。 – epascarello

+0

即將批准答案。只要有可能 - 請你澄清後者?就像,如果我有'assertTrue(a!= b)' - 我可以應用什麼技巧,這樣'a!= b'將不會在生產模式下計算(開銷較小)? – BreakPhreak

4

下面是我用:

當我工作的代碼我有initDevMode();在我正在使用的文件的頂部,當我準備發佈到產品時,我只是刪除該行,並將所有斷言轉到一個空函數。

/** 
* Log a message to console: 
* either use jquery's console.error 
* or a thrown exception. 
* 
* call initDevMode(); before use to activate 
* use with: 
*  assert(<condition>, "message"); 
*  eg: assert(1 != 1, "uh oh!"); 
* 
* Log errors with: 
*  errorLog(message); 
*  eg: errorLog(xhr.status); 
*/ 
assert = function(test, msg) { } 
errorLog =function(msg) { } 

initDevMode = function() { 
    assert = function(test, msg) { 
     msg = msg || "(no error message)"; 
     if(!test) { 
      try { 
        throw Error(); 
       } catch(e) { 
        var foo = e; 
        var lines = e.stack.split('\n'); 
        for(i in lines) { 
         if(i > 2) { 
         errorLog(msg + lines[i]); 
        } 
       } 
      } 
     } 
     throw("Assertion failed with: " + msg); 
    }; 
    errorLog = function(msg) { 
     if(typeof console.error == 'function') { 
      console.error(msg); 
     } else { 
      function errorLog(msg) { 
       console.log("foo"); 
       setTimeout(function() { 
        throw new Error(msg); 
       }, 0); 
      } 
     } 
    }; 
} 
+1

if(!test)'block'不應該拋出(「Assertion failed」)'駐留'內部嗎? –

0

看一看Jascree;基本上它是一個工具,可以從你的代碼中幾乎任意的邏輯中刪除斷言。使用批處理器生成生產代碼或用於需要測試性能/配置文件代碼的fastcgi-backed腳本目錄時非常方便。

2

我使用以下命令替換console.assert,當它因任何原因而不可用時。

這絕對不是事實標準,它遠非理想,但它確實滿足您的要求,斷言不在生產模式中進行評估。此外,它還向您顯示觸發失敗斷言的表達式,這有助於調試。

螺旋調用語法(帶有函數表達式)用於創建閉包,以便斷言函數可以訪問調用方訪問的相同變量。

我懷疑這有很高的編譯時間和運行時間開銷,但我沒有試圖驗證。

function assert(func) { 
    var name; 
    if (typeof(ENABLE_ASSERTIONS) !== "undefined" && !ENABLE_ASSERTIONS) { 
     return; 
    } 
    name = arguments.callee.caller; 
    name = name ? name.name : "(toplevel)"; 
    if (!func()) { 
     throw name + ": assertion failed: " + ('' + func).replace(/function[^(]*\([^)]*\)[^{]*{[^r]*return/, '').replace(/;[ \t\n]*}[ \t\n]*$/, ''); 
    } 
} 

使用它看起來像:

function testAssertSuccess() { 
    var i = 1; 
    assert(function() { return i === 1; }); 
} 
function testAssertFailure() { 
    var j = 1; 
    assert(function() { return j === 2; }); 
} 
ENABLE_ASSERTIONS = true; 
testAssertSuccess(); 
testAssertFailure(); 

HTH!