在JavaScript中打破NaN

时间:2013-12-12 04:10:57

标签: javascript nan

是否有任何现代浏览器引发NaN传播的异常(即将数字乘以或添加到NaN),或者可以配置为这样做?

沉默的NaN传播是一个可怕且阴险的错误来源,我很想能够及早发现它们,即使在性能下降时也是如此。


以下是use strictjshint等人的示例错误。不会接受:

object = new MyObject();
object.position.x = 0;
object.position.y = 10;

// ... lots of code

var newPosition = object.position + 1; // <- this is an error, and should
                                       //    have been object.position.x
                                       //    however it fails *silently*,
                                       //    rather than loudly

newPosition *= 2;                      // <- this doesn't raise any errors either.
                                       //    this code is actually ok if the
                                       //    previous line had been correct

5 个答案:

答案 0 :(得分:37)

回答问题:

  

是否有任何现代浏览器引发NaN传播的异常(即将数字乘以或添加到NaN),或者可以配置为这样做?

没有。 Javascript是一种非常宽容的语言,如果你想将Math.PI乘以“马铃薯”,那么它并不在乎。 (提示:它是NaN)。它只是我们开发人员必须处理的语言中的一个不好的部分(或者很好的部分,取决于你的观点)。

解决你提出这个问题的错误(大概),在你的对象上使用getter和setter是强制执行此操作的一种可靠方法,也可以防止你犯这样的错误。

答案 1 :(得分:26)

以下代码可能会对您有所帮助。

为了完全解决这个问题,我认为我们需要像operator reload这样的东西。我们可以重新加载'+ - / *'之类的运算符,并检查操作数是否为数字,如果没有,则抛出Error。

作为部分解决方案,当JavaScript执行类似'a + b'的操作时,它会调用继承自valueOf的{​​{1}}方法,我们可以重写Object.prototype

Object.prototype.valueOf

(提示:您可以删除生产中的代码,并将其添加到您的开发环境中。)

答案 2 :(得分:10)

最干净的方法是使用一个简短的函数来每次验证表达式的结果

我知道这不是你正在寻找的答案,但这是javascript的本质,你不能伤心地改变它

function v(a){ if(isNaN(a)) throw "error"; return a; }
var test = v(100 * "abc");

答案 3 :(得分:2)

我认为这是getter和setter派上用场的情况。

以下是一个伪代码示例,只是为了给你一个想法。

//Inside your Object class code.
function getPosition() {

  //You don't want the property "position" to be NaN, right?
  if(isNaN(this.position)) 
    throws "NaN is not a correct numerical value!";

  return this.position;

}


//Somewhere in your code
var newPosition = object.getPosition() + 1; //raises an exception.

我认为这比实现伪操作符重载更好,并且使事情变得更复杂。

答案 4 :(得分:2)

我知道这是一个旧帖子,但我认为你的问题可能有一个超级简单的答案。您可以为以下语句创建函数,也可以将其添加到内联。

JavaScript对某些值有一些独特的行为。其中一个独特的行为围绕非数字值或NaNNaN的值不会与包括NaN本身在内的任何其他值相等。出于这个原因,以下声明:

if(x != x) {
    throw "Value is NaN!";
}
当且仅当<{em> x的值为NaN时,

将保持为真