改进的isNumeric()函数? [英] An improved isNumeric() function?

查看:119
本文介绍了改进的isNumeric()函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在某些项目中,我需要验证一些数据,并尽可能确定它是可以在数学运算中使用的javascript数值.

jQuery和其他一些javascript库已经包含了这样的函数,通常称为isNumeric.在stackoverflow上还有一个帖子,它已被广泛接受为答案,与前面提到的库是相同的常规例程使用.

function isNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

作为我的第一篇文章,我无法在该主题中回复.我在被录用的职位上遇到的问题是,似乎有些极端情况影响了我正在做的某些工作,因此我进行了一些更改以尝试解决我遇到的问题.

首先,如果参数是长度为1的数组,并且上面的逻辑将该单个元素的类型视为数字,则上面的代码将返回true.我认为,如果它是一个数组,那么它不是数字.

为缓解此问题,我从逻辑上添加了对折扣数组的检查

function isNumber(n) {
  return Object.prototype.toString.call(n) !== '[object Array]' &&!isNaN(parseFloat(n)) && isFinite(n);
}

当然,您也可以使用Array.isArray代替Object.prototype.toString.call(n) !== '[object Array]'

我已更改代码以反映对数组的通用测试,或者您可以使用jquery $.isArray或原型Object.isArray

我的第二个问题是负十六进制整数文字字符串("-0xA"-> -10)未被计为数字.但是,正十六进制整数文字字符串("0xA"-> 10)被视为数字.我需要两个都是有效的数字.

然后我修改了逻辑以考虑到这一点.

function isNumber(n) {
  return Object.prototype.toString.call(n) !== '[object Array]' &&!isNaN(parseFloat(n)) && isFinite(n.toString().replace(/^-/, ''));
}

如果您担心每次调用该函数时都会创建正则表达式,则可以在闭包内重写它,类似这样

isNumber = (function () {
  var rx = /^-/;

  return function (n) {
      return Object.prototype.toString.call(n) !== '[object Array]' && !isNaN(parseFloat(n)) && isFinite(n.toString().replace(rx, ''));
  };
}());

然后,我选择了CMS +30个测试用例,克隆对jsfiddle进行测试添加了我的额外测试用例和上述解决方案./p>

一切似乎都按预期进行,我还没有遇到任何问题.您是否可以看到任何问题,代码或理论上的问题?

它可能不能替代广泛接受/使用的答案,但是如果这是您期望的isNumeric函数结果,那么希望会对您有所帮助.

编辑:如 Bergi 所述,还有其他可能的对象可能是认为是数字,将白名单比黑名单更好.考虑到这一点,我将添加到条件中.

我希望我的isNumeric函数仅考虑数字或字符串

考虑到这一点,最好使用

function isNumber(n) {
  return (Object.prototype.toString.call(n) === '[object Number]' || Object.prototype.toString.call(n) === '[object String]') &&!isNaN(parseFloat(n)) && isFinite(n.toString().replace(/^-/, ''));
}

已将其添加为测试22

解决方案

我认为,如果它是一个数组,那么它不是数字.为了缓解这个问题,我从逻辑上为折扣数组添加了一个检查

您也可能会遇到其他任何对象的问题,例如{toString:function(){return "1.2";}}.您认为哪些对象是数字的? Number对象?没有吗?

与其尝试将无法通过测试的某些事物列入黑名单,还应将要数字化的事物明确列入白名单.您的函数应该得到什么,原始字符串和数字?然后为他们进行准确的测试:

(typeof n == "string" || typeof n == "number")

During some projects I have needed to validate some data and be as certain as possible that it is javascript numerical value that can be used in mathematical operations.

jQuery, and some other javascript libraries already include such a function, usually called isNumeric. There is also a post on stackoverflow that has been widely accepted as the answer, the same general routine that the fore mentioned libraries are using.

function isNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

Being my first post, I was unable to reply in that thread. The issue that I had with the accepted post was that there appear to be some corner cases that affected some work that I was doing, and so I made some changes to try and cover the issue I was having.

First, the code above would return true if the argument was an array of length 1, and that single element was of a type deemed as numeric by the above logic. In my opinion, if it's an array then its not numeric.

To alleviate this problem, I added a check to discount arrays from the logic

function isNumber(n) {
  return Object.prototype.toString.call(n) !== '[object Array]' &&!isNaN(parseFloat(n)) && isFinite(n);
}

Of course, you could also use Array.isArray instead of Object.prototype.toString.call(n) !== '[object Array]'

EDIT: I've changed the code to reflect a generic test for array, or you could use jquery $.isArray or prototypes Object.isArray

My second issue was that Negative Hexadecimal integer literal strings ("-0xA" -> -10) were not being counted as numeric. However, Positive Hexadecimal integer literal strings ("0xA" -> 10) wrere treated as numeric. I needed both to be valid numeric.

I then modified the logic to take this into account.

function isNumber(n) {
  return Object.prototype.toString.call(n) !== '[object Array]' &&!isNaN(parseFloat(n)) && isFinite(n.toString().replace(/^-/, ''));
}

If you are worried about the creation of the regex each time the function is called then you could rewrite it within a closure, something like this

isNumber = (function () {
  var rx = /^-/;

  return function (n) {
      return Object.prototype.toString.call(n) !== '[object Array]' && !isNaN(parseFloat(n)) && isFinite(n.toString().replace(rx, ''));
  };
}());

I then took CMSs +30 test cases and cloned the testing on jsfiddle added my extra test cases and my above described solution.

Everything appears to be working as expected and I haven't experienced any issues. Are there any issues, code or theoretical, that you can see?

It may not replace the widely accepted/used answer but if this is what you are expecting as results from your isNumeric function then hopefully this will be of some help.

EDIT: As pointed out by Bergi, there are other possible objects that could be considered numeric and it would be better to whitelist than blacklist. With this in mind I would add to the criteria.

I want my isNumeric function to consider only Numbers or Strings

With this in mind, it would be better to use

function isNumber(n) {
  return (Object.prototype.toString.call(n) === '[object Number]' || Object.prototype.toString.call(n) === '[object String]') &&!isNaN(parseFloat(n)) && isFinite(n.toString().replace(/^-/, ''));
}

This has been added as test 22

解决方案

In my opinion, if it's an array then its not numeric. To alleviate this problem, I added a check to discount arrays from the logic

You can have that problem with any other object as well, for example {toString:function(){return "1.2";}}. Which objects would you think were numeric? Number objects? None?

Instead of trying to blacklist some things that fail your test, you should explicitly whitelist the things you want to be numeric. What is your function supposed to get, primitive strings and numbers? Then test exactly for them:

(typeof n == "string" || typeof n == "number")

这篇关于改进的isNumeric()函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆