2011-09-12 76 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!