JavaScript类型检测:从基础到高级的代码实践

152 阅读2分钟

在 JavaScript 中,正确地识别数据类型对于程序的健壮性和性能至关重要。我会通过一些代码示例,从基础的 typeof 检测开始,逐步揭示不同类型判断方法。

1. typeof 操作符

console.log(typeof 42);          // "number"
console.log(typeof "Hello");     // "string"
console.log(typeof true);        // "boolean"
console.log(typeof undefined);   // "undefined"
console.log(typeof Symbol());    // "symbol"
console.log(typeof {});          // "object"
console.log(typeof null);        // "object",这是 `typeof` 的一个陷阱

typeof 是最简单的类型检测方式,用于识别原始类型。但是,它不能区分不同的引用类型,对于所有引用类型,包括 null,都会返回 "object"。这是因为所有引用类型在底层都表现为对象,其二进制表示的前三位均为 0。因此,typeof 并不足以区分不同的引用类型。

2. instanceof 操作符

function Person() {}
const person = new Person();

console.log(person instanceof Person); // true
console.log(person instanceof Object); // true

instanceof 用于检查一个对象是否是另一个构造函数的实例。它通过检查原型链来实现这一点。instanceof 并非万能。它依赖于原型链的完整性,如果原型链被破坏(例如,手动修改原型),instanceof 的判断可能会失效。此外,instanceof 不能跨域工作,即无法判断来自其他窗口或框架的对象类型。

3. Object.prototype.toString.call()

为了克服 typeofinstanceof 的限制,Object.prototype.toString.call() 提供了一种更精细的类型检测方法,可以区分不同引用类型,甚至 nullundefined

function checkType(value) {
    return Object.prototype.toString.call(value);
}

console.log(checkType(42));          // "[object Number]"
console.log(checkType("Hello"));     // "[object String]"
console.log(checkType(true));        // "[object Boolean]"
console.log(checkType(undefined));   // "[object Undefined]"
console.log(checkType(null));        // "[object Null]"
console.log(checkType([]));          // "[object Array]"
console.log(checkType({}));          // "[object Object]"

4. Array.isArray()

在 ES5 中引入的 Array.isArray() 专门用于判断一个值是否为数组,它比 instanceof Array 更加安全,因为不受原型链污染的影响。

console.log(Array.isArray([]));         // true
console.log(Array.isArray({}));         // false
console.log(Array.isArray(document.body.children)); // false,虽然这是一个类数组对象

5. 自定义类型检查函数

我们还可以定义自己的类型检查函数,例如 isObjectmyInstanceof 来满足特定需求。

function isObject(obj) {
    return obj !== null && typeof obj === 'object';
}

function myInstanceof(L, R) {
    let proto = L.__proto__ || L.constructor.prototype;
    while (proto) {
        if (proto === R.prototype) {
            return true;
        }
        proto = proto.__proto__;
    }
    return false;
}

const arr = [];
console.log(isObject(arr));       // true
console.log(myInstanceof(arr, Array)); // true

通过以上代码示例,我们可以清晰地看到 JavaScript 中不同类型检测方法的特点和适用场景。从简单的 typeof 到更为复杂的 Object.prototype.toString.call(),再到专门化的 Array.isArray(),每种方法都有其独特的作用,了解并掌握它们,将有助于编写更高质量的代码。