类型检测

typeof

因为 ECMAScript 的类型系统是松散的,所以需要一种手段来确定任意变量的数据类型。因此,ECMAScript提供了一个可以查看值类型的运算符:typeof,它返回的是类型的字符串值。

JavaScript中的变量是没有类型的,只有值才有。变量可以随时持有任何类型的值。在对变量执行 typeof操作时,得到的结果并不是该变量的类型,而是该变量持有的值的类型,因为 JavaScript中变量是没有类型的。

变量在未持有值的时候为 undefined

1let a;
2typeof a; // undefined

对一个值使用 typeof 会返回下列字符串之一:

返回值 含义
undefined 表示值未定义
boolean 表示值为布尔值
string 表示值为字符串
number 表示值为数值
object 表示值为对象
function 表示值为函数
symbol 表示值为符号

typeof 是一个操作符而不是函数,所以它的写法和函数有所不同。它直接跟在你想要检测的变量之前,而不是像函数那样使用括号。

1// 简单数据类型
2let num = 123;
3console.log(typeof num); // number
4
5let str = "Hello";
6console.log(typeof str); // string
7
8let bool = true;
9console.log(typeof bool); // boolean
10
11let nul = null;
12console.log(typeof nul); // object
13
14let und = undefined;
15console.log(typeof und); // undefined
16
17let sym = Symbol();
18console.log(typeof sym); // symbol
19
20// 复杂数据类型
21let obj = {};
22console.log(typeof obj); // object
23
24let arr = [];
25console.log(typeof arr); // object
26
27let fun = function () {};
28console.log(typeof fun); // function

需要注意的是,typeof 对于 null 和 数组的检测会返回 object,这是 JavaScript 的一个历史遗留问题。如果你需要更加准确地检测这些类型,可能需要使用其他方法,例如 :

null 是 “假值”(falsy或者falsy-like),也是唯一一个用 typeof 检测会返回 object 的基本类型。

1// 使用 Array.isArray() 来检测数组
2let arr = [];
3console.log(Array.isArray(arr)); // true
4
5// 对于 null 的检测,你可以直接使用 === 来判断
6// 这里需要注意的是,如果你使用 == 来比较,那么 null 和 undefined 会被认为是相等的
7let nul = null;
8console.log(nul === null); // true
9console.log(!nul && typeof nul === 'object'); // true

function 实际上是 object 的一个子类型。函数是“可调用对象”,它有一个内部属性 [[Call]],该属性使其可以被调用。

数组也是 object 的一个子类型,数组的元素按数字顺序来进行索引(而非像普通对象那样通过字符串键值),其length属性是元素的个数。

然而,尽管 typeof 不是函数,但你仍然可以在它后面使用括号。这样并不影响结果,这些括号只是用于改变运算优先级或者提高代码可读性。例如:

1let num = 123;
2console.log(typeof(num)); // number
3
4let str = "Hello";
5console.log(typeof(str)); // string

instanceof

1function Foo() {}
2const a = new Foo();
3
4console.log(a instanceof Foo); // true

instanceof 操作符左操作数是一个普通对象,右操作数是一个函数。

instanceof 回答的问题是:在 a 的整条 [[prototype]] 链中是否有 Foo.prototype 指向的对象?

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

也可以理解为是否为某个对象的实例,typeof 不能区分数组,但 instanceof 则可以。

值类型与对象

下面是使用字面量与对象方法创建字符串,返回的是不同类型。

1let name1 = "xiaosutongxue";
2let name2 = new String("xstx");
3console.log(typeof name1, typeof name2); //string object

只有对象才有方法使用,但在JS中也可以使用值类型调用方法,因为它会在执行时将值类型转为对象。

1let name1 = "xiaosutongxue";
2let name2 = new String("xstx");
3console.log(name1.length); //13
4console.log(name2.length); //4