# JS 中类型的一锅粥

# 三种方法

一般来说我们常用于判断一个数据的类型有这七种兵器三种方法

typeof
instanceof
Object.prototype.toString()

# typeof

typeof 操作符返回一个字符串,表示未经计算的操作数的类型
typeof 只会检查 JS 的基本数据类型

console.log(0, typeof 0); // 0 "number"
console.log(1, typeof 1); // 1 "number"
console.log(NaN, typeof NaN); // NaN "number"
console.log("0", typeof "0"); // 0 "string"
console.log("1", typeof "1"); // 1 "string"
console.log(false, typeof false); // false "boolean
console.log(true, typeof true); // true "boolean"
console.log(undefined, typeof undefined); // undefined "undefined"
console.log(null, typeof null); // null "object"
console.log([], typeof []); // [] "object"
console.log({}, typeof {}); // {} "object"
console.log(function () {}, typeof function () {}); // [Function] "function"

两个注意点

console.log([], typeof []); // [] "object"
console.log(NaN, typeof NaN); // NaN "number"

记住两个特例

console.log(null, typeof null); // null "object"
console.log(function () {}, typeof function () {}); // [Function] "function"

此外还有 ES6 新增的 BigInt 数据类型

const x = 1n;
console.log(x, typeof x); // 1n "bigint"
console.log(Object(x), typeof Object(x)); // BigInt {1n} "object"

# instanceof

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

使用方法

object instanceof constructor; //即检查object是否是constructor的一个实例
// 定义构造函数
function C() {}
function D() {}
var o = new C();
o instanceof C; // true,因为 Object.getPrototypeOf(o) === C.prototype
o instanceof D; // false,因为 D.prototype 不在 o 的原型链上
o instanceof Object; // true,因为 Object.prototype.isPrototypeOf(o) 返回 true
C.prototype instanceof Object; // true,同上
C.prototype = {};
var o2 = new C();
o2 instanceof C; // true
o instanceof C; // false,C.prototype 指向了一个空对象,这个空对象不在 o 的原型链上.
D.prototype = new C(); // 继承
var o3 = new D();
o3 instanceof D; // true
o3 instanceof C; // true 因为 C.prototype 现在在 o3 的原型链上

注意

虽然在目前的 ES 规范中,我们只能读取对象的原型而不能改变它,但借助于非标准的 proto 伪属性,是可以实现的。比如执行 obj.proto = {} 之后,obj instanceof Foo 就会返回 false 了。

# Object.prototype.toString()

每个对象都有一个 toString() 方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。默认情况下,toString() 方法被每个 Object 对象继承。

如果此方法在自定义对象中未被覆盖,toString() 返回 "[object type]",其中 type 是对象的类型。

因此可以通过 toString() 来获取每个对象的类型。 为了每个对象都能通过 Object.prototype.toString() 来检测,需要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式来调用,传递要检查的对象作为第一个参数,称为 thisArg。

var toString = Object.prototype.toString;

toString.call(new Date()); // [object Date]
toString.call(new String()); // [object String]
toString.call(Math); // [object Math]
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]