Подтвердить что ты не робот

Перерыв на NaN в JavaScript

Существует ли какой-либо современный браузер, который вызывает исключения при распространении NaN (т.е. умножение или добавление числа на NaN) или может быть настроен для этого?

Бесшумное распространение NaN - ужасный и коварный источник ошибок, и мне бы хотелось, чтобы они могли обнаружить их рано, даже при снижении производительности.


Вот пример ошибки, что use strict, jshint et al. не подобрал бы:

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
4b9b3361

Ответ 1

Чтобы ответить на заданный вопрос:

Существует ли какой-либо современный браузер, который вызывает исключения при распространении NaN (т.е. умножение или добавление числа на NaN) или может быть настроен для этого?

Нет. Javascript - очень прощающий язык, и вам все равно, хотите ли вы умножить Math.PI на "картофель" (подсказка: it NaN). Это только одна из плохих частей (или хороших частей, в зависимости от вашей точки зрения) относительно языка, с которым нам приходится сталкиваться разработчикам.

Обращаясь к ошибке, в которой вы задаете этот вопрос (предположительно), использование геттеров и сеттеров в ваших объектах является одним из надежных способов обеспечения этого, а также не позволяет вам совершать такие ошибки.

Ответ 2

Код может помочь вам.

Чтобы решить эту проблему полностью, я думаю, нам нужно что-то вроде operator reload. Мы можем перезагрузить такие операторы, как "+ -/*", и проверить, является ли операнд номером, если нет, а затем выбросить ошибку.

В качестве частичного решения, когда JavaScript выполняет операцию типа "a + b", он вызывается методом valueOf, который наследует от Object.prototype, мы можем переписать 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

(подсказка: вы можете удалить созданный код и добавить его в свою среду разработки.)

Ответ 3

Самый чистый способ сделать это - иметь короткую удобную функцию, которая каждый раз проверяет результат выражения

Я знаю, что не тот ответ, который вы ищете, но это характер javascript, и вы не можете его изменить.

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

Ответ 4

Я думаю, что это ситуация, когда геттер и сеттер пригождаются.

Ниже приведен пример кода 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.

Я думаю, что это лучше, чем реализация фальшивой перегрузки оператора и усложнение ситуации.

Ответ 5

Я знаю, что это старый поток, но я думаю, что может быть очень простой ответ на ваш вопрос. Вы можете либо создать функцию для оператора ниже, либо добавить его в строку.

JavaScript имеет некоторые уникальные поведения для определенных значений. Одно из этих уникальных действий вращается вокруг значения не-число или NaN. Значение NaN не будет сравниваться с любым другим значением, включая NaN. По этой причине следующее утверждение:

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

будет содержать true , если и только если значение x равно NaN.