NaN(特殊的数字)以及Object.is()的实现

231 阅读2分钟

特殊的数字

NaN"不是数字的数字"

NaN概念:数学运算的操作数不是数字类型,无法返回一个有效数字。例如:a/'dw'

let a = 2 / "dw";
console.log(a); 		//NaN
console.log(typeof a === "number");		//true
console.log(NaN === NaN);		//false

可以看到对NaN进行typeof的类型判断居然是number类型。

并且在JS里,NaN唯一一个与自身不全等(===)

关于isNaN()这个函数会检查参数是否不是NaN,也不是数字。

let a = 2 / "dw";
console.log(isNaN(a));		//true
console.log(isNaN(1));		//false
console.log(isNaN("1"));	//false
console.log(isNaN("a"));	//true

这里第三行和第四行很奇怪,为什么同样是字符串会有两种结果?因为isNaN这个函数会将参数转换为数字转换不成功就自然是NaN,所以最后两行有差异。

那么,如何精准判断一个值是不是NaN呢?JS给了我们一个方法Number.isNaN()

let a = 2 / "dw";
console.log(Number.isNaN(a));//true
console.log(Number.isNaN(1));//false
console.log(Number.isNaN("1"));//false
console.log(Number.isNaN("a"));//false

可以看到最后一行变成了false,判断完全正确。

Number.isNaN()是如何实现的呢?

这个函数主要是解决isNaN函数对参数的强制转换为数字的问题,可以对参数类型进行判断限制。

比如:

let a = 2 / "dw";
//这里我模拟Number.isNaN()取名为iNaN
function iNaN(arg) {
        return typeof arg === "number" && isNaN(arg);
}
console.log(iNaN(a));//true
console.log(iNaN(1));//false
console.log(iNaN("1"));//false
console.log(iNaN("a"));//false

可以达到预期效果,

还可以利用他与自身不等实现。

function iNaN(arg) {
  return arg !== arg;
}

结果与上面一样。

-0

console.log(0 === 0);					//true
console.log(-0 === 0);				//true
console.log(-0 === +0);				//true
console.log(-0 == +0);				//true
console.log(-0 == +0);				//true

console.log(-0 > 0);					//false
console.log(-0 < 0);					//false

console.log(Object.is(-0, 0));//false
console.log(Object.is(-0, +0));//false

-0,0这两个数在js中是存在的,基本的相等符号(==和===)对于这三个数都是true

Object.is()可以判断两个值是不是相同值,可以分出区别,

console.log(Object.is(NaN, NaN)); 可以判断NaN

[详情见MDN](Object.is() - JavaScript | MDN (mozilla.org))

应用:这个值可以在需要判断0值时上升还是下降趋势时进行判断,比如股票,地理方向。更语义化。

实现Object.is()

实现思路:解决NaN与自身不等和-0与0相等的难题,其他都交给”===“处理即可。

Object.is = function (a, b) {
  let aIsNegZero = isNegZero(a);
  let bIsNegZero = isNegZero(b);
  
  if (aIsNegZero || bIsNegZero) {
    return aIsNegZero && bIsNegZero;
  }
  else if (isNanValue(a) && isNanValue(b)) {
    return true;
  } 
  else if (a === b) {
    return true;
  } 
  else return false;

  // 判断参数是不是-0
  function isNegZero(x) {
    return x === 0 && 2 / x === -Infinity;
  }

  //判断参数是不是NaN
  function isNanValue(x) {
    return x !== x;
  }
};