在JavaScript中突破NaN

在JavaScript中突破NaN,javascript,nan,Javascript,Nan,是否有任何现代浏览器会在NaN传播时引发异常(即将数字乘以或添加到NaN),或者可以配置为引发异常 无声的NaN传播是一个可怕而阴险的bug来源,我希望能够及早发现它们,即使是在性能下降的情况下 下面是一个示例bug,使用strict,jshint等都不会出现: object = new MyObject(); object.position.x = 0; object.position.y = 10; // ... lots of code var newPosition = objec

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

无声的NaN传播是一个可怕而阴险的bug来源,我希望能够及早发现它们,即使是在性能下降的情况下


下面是一个示例bug,
使用strict
jshint
等都不会出现:

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
object=newmyobject();
object.position.x=0;
object.position.y=10;
// ... 很多代码

var newPosition=object.position+1;// 我认为在这种情况下,getter和setter会派上用场

下面是一个psuedo代码示例,旨在为您提供一个想法

//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.

我认为这比实施假运算符重载要好,使事情变得更复杂。

要回答问题:

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

不。Javascript是一种非常宽容的语言,它不在乎你是否想用“土豆”乘以
Math.PI
(提示:它是
NaN
)。这只是美国开发人员必须处理的语言的一个不好的部分(或好的部分,取决于你的观点)


解决让您提出这个问题的bug(大概是这样的),在对象上使用getter和setter是一种很好的方法来实现这一点,并防止您犯类似的错误。

下面的代码可能会对您有所帮助

为了完全解决这个问题,我认为我们需要类似于
操作符重载的东西。我们可以重新加载像“+-/*”这样的运算符,并检查操作数是否为number,如果不是,则抛出错误

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

Object.prototype.originalValueOf = Object.prototype.valueOf;

Object.prototype.valueOf = function() {
  if (typeof this !== 'number') {
    throw new Error('Object is not a Number');
  }

  return this.originalValueOf();
}

var a = 1 + 2; // -> works
console.log(a); // -> 3

var b = {};
var c = b + 2; // -> will throw an Error

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

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

我知道这不是你想要的答案,但这是javascript的本质,你无法改变它

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

我知道这是一个古老的线索,但我认为可能有一个超级简单的答案来回答你的问题。您可以为下面的语句创建一个函数,也可以内联添加它

JavaScript对于某些值有一些独特的行为。这些独特的行为之一是围绕非数字值或
NaN
展开的。
NaN
的值不会与任何其他值(包括
NaN
本身)进行比较。因此,以下声明:

if(x != x) {
    throw "Value is NaN!";
}

当且仅当
x
的值为
NaN

时,才会成立我真的不想每次添加任何数字时都在代码中加上isnan。在计算中使用数据之前,您不能确保数据正确吗?这是GIGO原则在起作用——这对Monads来说可能是一个例子吗?:)@杰克:你真的能读懂我的心思。但是-不。@zerkms与RUJordan的想法基本相同-自由使用一堆资产?我正在寻找一种方法来快速检测编码错误,而不是处理垃圾输入。我同意getter和setter,但你不应该期望
isNaN
是任何方法,调用
anything.isNaN()
会自动抛出异常是的,对不起。但这只是一个psuedo代码,可以给你一个想法。
isFinite
是另一个方便的函数。有时,您希望防止传入诸如
无限
-无限
之类的内容!这是理想的!这在什么浏览器上工作?Chrome和Safari至少不允许替换本机原型这不仅会影响数字,而且会影响任何对象,因此您不想使用:(@Wesabi,我很高兴能获得性能成功,如果成功的话,我可以克服这些限制。不幸的是,我无法做到这一点。将其添加到Chrome中,然后运行我的代码会使选项卡和开发工具都崩溃。但仍在探索!讨厌的、讨厌的想法!
.valueOf()
不仅仅用于数字!我接受这个答案,因为它最直接地回答了这个问题。然而,@Jerry的答案解决了使用对象执行数字操作的问题,这很好地解决了实际问题的大量情况(除了乘以
未定义的
*3或类似情况)我会叫它
number
或者别的什么,但这看起来像是
typeof(100*“abc”)
返回
“number”
,因为具有讽刺意味的是
NaN
是一个
数字。你想要
isNaN()