[乐意黎原创] 深入学习理解JS中的typeof和NaN

typeof操作符返回一个字符串,表示未经计算的操作数的类型。

语法

typeof运算符后跟操作数:

typeof operand
or
typeof (operand)

参数

operand 是一个表达式,表示对象或原始值,其类型将被返回。

括号是可选的。

描述

下表总结了typeof可能的返回值。有关类型和原始值的更多信息,可查看 JavaScript数据结构 页面。

类型结果
Undefined"undefined"
Null"object"(见下文)
Boolean"boolean"
Number"number"
String"string"
Symbol (ECMAScript 6 新增)"symbol"
宿主对象(由JS环境提供)Implementation-dependent
函数对象([[Call]] 在ECMA-262条款中实现了)"function"
任何其他对象"object"

示例

// Numbers
typeof 37 === 'number';
typeof 3.14 === 'number';
typeof Math.LN2 === 'number';
typeof Infinity === 'number';
typeof NaN === 'number'; // 尽管NaN是"Not-A-Number"的缩写
typeof Number(1) === 'number'; // 但不要使用这种形式!

// Strings
typeof "" === 'string';
typeof "bla" === 'string';
typeof (typeof 1) === 'string'; // typeof总是返回一个字符串
typeof String("abc") === 'string'; // 但不要使用这种形式!

// Booleans
typeof true === 'boolean';
typeof false === 'boolean';
typeof Boolean(true) === 'boolean'; // 但不要使用这种形式!

// Symbols
typeof Symbol() === 'symbol';
typeof Symbol('foo') === 'symbol';
typeof Symbol.iterator === 'symbol';

// Undefined
typeof undefined === 'undefined';
typeof declaredButUndefinedVariable === 'undefined';
typeof undeclaredVariable === 'undefined'; 

// Objects
typeof {a:1} === 'object';

// 使用Array.isArray 或者 Object.prototype.toString.call
// 区分数组,普通对象
typeof [1, 2, 4] === 'object';

typeof new Date() === 'object';

// 下面的容易令人迷惑,不要使用!
typeof new Boolean(true) === 'object';
typeof new Number(1) === 'object';
typeof new String("abc") === 'object';

// 函数
typeof function(){} === 'function';
typeof class C{} === 'function'
typeof Math.sin === 'function';
typeof new Function() === 'function';

null

typeof null === 'object'; // 从一开始出现JavaScript就是这样的

在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),因此,null的类型标签也成为了 0,typeof null就错误的返回了"object"。(reference

ECMAScript提出了一个修复(通过opt-in),但被拒绝。这将导致typeof null === 'object'。

使用 new 操作符

// All constructor functions while instantiated with 'new' keyword will always be typeof 'object'
var str = new String('String');
var num = new Number(100);

typeof str; // It will return 'object'
typeof num; // It will return 'object'

// But there is a exception in case of Function constructor of Javascript

var func = new Function();

typeof func; // It will return 'function'

语法中需要括号

// Parentheses will be very much useful to determine the data type for expressions.
var iData = 99;

typeof iData + ' Wisen'; // It will return 'number Wisen'
typeof (iData + ' Wisen'); // It will return 'string'

正则表达式

对正则表达式字面量的类型判断在某些浏览器中不符合标准:


typeof /s/ === 'function'; // Chrome 1-12 , 不符合 ECMAScript 5.1
typeof /s/ === 'object'; // Firefox 5+ , 符合 ECMAScript 5.1

暂存死区

在 ECMAScript 2015 之前,typeof总是保证为任何操作数返回一个字符串。但是,除了非提升,块作用域的letconst之外,在声明之前对块中的letconst变量使用typeof会抛出一个ReferenceError。这与未声明的变量形成对比,typeof会返回“undefined”。块作用域变量在块的头部处于“暂时死区”,直到被初始化,在这期间,如果变量被访问将会引发错误。

typeof undeclaredVariable === 'undefined';
typeof newLetVariable; let newLetVariable; // ReferenceError
typeof newConstVariable; const newConstVariable = 'hello'; // ReferenceError

例外

所有当前的浏览器都暴露了一个类型为 undefined 的非标准宿主对象 document.all

typeof document.all === 'undefined';

尽管规范允许为非标准的外来对象定制类型标签,但它要求这些类型标签与预定义标签不同。document.all的类型标记为“undefined”的情况必须被列为违反规则的特殊情况。

规范

var o= new Object;
typeof o
//"object"
var o= new Object();
typeof o
//"object"
var o={};
typeof o
//"object"
var o=function(){}
typeof o
//"function"
var o=function(){}
typeof o();
//"undefined"



typeof NaN
"number"
typeof null
"object"
typeof undefined
"undefined"
typeof function(){}
"function"
typeof abc
"undefined"
typeof "abc"
"string"
typeof Number
"function"
typeof Object
"function"
typeof Array

"function"




在JavaScript中,假值有false、null、0、”“、undefined 和 NaN。

false、null、0、”“、undefined都很好判断,直接使用===即可 


全局属性 NaN 的值表示不是一个数字(Not-A-Number)

语法

NaN

描述

NaN 是一个全局对象的属性。

NaN 属性的初始值就是 NaN,和 Number.NaN 的值一样。在现代浏览器中(ES5中), NaN 属性是一个不可配置(non-configurable),不可写(non-writable)的属性。但在ES3中,这个属性的值是可以被更改的,但是也应该避免覆盖。

编码中很少直接使用到 NaN。通常都是在计算失败时,作为 Math 的某个方法的返回值出现的(例如:Math.sqrt(-1))或者尝试将一个字符串解析成数字但失败了的时候(例如:parseInt("blabla"))。

判断一个值是否是NaN

等号运算符(== 和 ===) 不能被用来判断一个值是否是 NaN。必须使用 Number.isNaN() 或 isNaN() 函数。在执行自比较之中:NaN,也只有NaN,比较之中不等于它自己。

NaN === NaN;        // false
Number.NaN === NaN; // false
isNaN(NaN);         // true
isNaN(Number.NaN);  // true

function valueIsNaN(v) { return v !== v; }
valueIsNaN(1);          // false
valueIsNaN(NaN);        // true
valueIsNaN(Number.NaN); // true

isNaN函数(存在问题)

JS中有一个全局函数isNaN(),但这个函数有一个问题,它总会隐式的将参数中的值转换成数字再做判断,这样就在判断很多明显不是NaN的值的时候也返回了true:

> isNaN("foo") 
true 
  • 任意的字符串使用isNaN都会返回true,这样就无法判断真正的isNaN了

解决方案

  • 利用NaN是唯一一个与自身严格不相等的值:
function myIsNaN(value) { 
    return value !== value; 
} 
  • 在使用isNaN()之前先检查一下这个值是不是数字类型,这样就避免了隐式转换的问题:
function myIsNaN2(value) { 
    return typeof value === 'number' && isNaN(value); 
} 

NaN 属性是代表非数字值的特殊值。该属性用于指示某个值不是数字。

typeof NaN返回number

会认为NaN表示的是一个非数字,所以typeof NaN返回的不应该是number,但其实NaN还是属于number类型,只不过用number类型无法表示而已,在ECMAScript标准中也明确定义了NaN属于Number类型。

NaN == NaN返回false

一般情况下一个数或者字符串和自身比较时应该返回true,但NaN和自身比较返回false,这是因为NaN表示一个无法表示的值,而这个无法表示的值可以有很多种,具体见上文。比如0/0返回NaN,0/’fail’也返回NaN,而0/0 != 0/’fail’,所以NaN == NaN返回false。

判断一个值是否是NaN

等号运算符(== 和 ===) 不能被用来判断一个值是否是 NaN。必须使用 Number.isNaN() 或 isNaN() 函数。


NaN == NaN
//false
NaN === NaN

//false

isNaN(NaN); // true

isNaN(undefined); // true

isNaN({}); // true

isNaN(true); // false

isNaN(null); // false

isNaN(37); // false

// strings

isNaN("327"); // false: 可以被转换成数值37

isNaN("327.327"); // false: 可以被转换成数值37.37

isNaN(""); // false: 空字符串被转换成0

isNaN(" "); // false: 包含空格的字符串被转换成0

// dates

isNaN(new Date()); // false

isNaN(new Date().toString()); // true

isNaN("aerchi") // true: "aerchi"不能转换成数值

//其它

isNaN(37)                //false

isNaN("37")             //false


isNaN(aerchi)
//VM248:1 Uncaught ReferenceError: aerchi is not defined
//    at <anonymous>:1:7

//(anonymous) @ VM248:1


isNaN("aerchi")              //true

----------------------------------------------------

isNaN(null)

false
isNaN(0)
false
isNaN(1)
false
isNaN(undefined)
true
isNaN("")
false
isNaN(NaN)
true
null == ""
false
null ===""
false
undefined ==""
false
8!=NaN
true
""==NaN
false



NaN == null
false
NaN === null
false
NaN == Array
false
NaN==undefined
false
NaN==""
false
NaN==8
false
NaN=="8"
false
typeof isNaN

"function"


Number.isNaN()

Number.isNaN()在ES6中定义的,Number.isNaN() 方法用来检测传入的值是否是 NaN。该方法比传统的全局函数 isNaN() 更可靠。该方法不会强制将参数转换成数字,只有在参数是真正的数字类型,且值为 NaN 的时候才会返回 true。

Number.isNaN(NaN); // true

Number.isNaN(Number.NaN); // true

Number.isNaN(0 / 0) // true


// 下面这几个如果使用全局的 isNaN() 时,会返回 true。

Number.isNaN("NaN"); // false,字符串 "NaN" 不会被隐式转换成数字 NaN。

Number.isNaN(undefined); // false

Number.isNaN({}); // false

Number.isNaN("aerchi"); // false


// 下面的都返回 falseNumber.isNaN(true);

Number.isNaN(null);

Number.isNaN(327);

Number.isNaN("327");

Number.isNaN("327.327");

Number.isNaN("");

Number.isNaN(" ");


参考: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/typeof

乐意黎原创

2018-03-27 00:12

本文地址: https://blog.csdn.net/aerchi/article/details/79706471



发布了430 篇原创文章 · 获赞 415 · 访问量 925万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览