JavaScript 在变量声明时无需指定类型,但我们在使用时肯定免不了要判断变量的类型,比如实现一个加法函数 add(a, b),变量是数字还是字符串,最后的结果就很不一样,因此我们经常要做的是对输入数据进行合法性校验,不合法直接抛出错误,对于编写健壮的代码至关重要。
1、typeof 操作符
typeof是JavaScript中用于获取变量类型的操作符,它返回一个表示变量类型的字符串,返回值包括:
"undefined"、"string"、"boolean"、"number"、"bigint"、"symbol"、"object" 、 "function"。
let undefinedVar;
let stringVar = "Hello, World!";
let booleanVar = true;
let numberVar = 42;
let bigintVar = 1234567890123456789012345678901234567890n;
let symbolVar = Symbol("example");
let objectVar = { key: "value" };
let functionVar = function() { console.log("This is a function"); };
// 使用 typeof 操作符获取变量类型
console.log(typeof undefinedVar); // 输出: "undefined"
console.log(typeof stringVar); // 输出: "string"
console.log(typeof booleanVar); // 输出: "boolean"
console.log(typeof numberVar); // 输出: "number"
console.log(typeof bigintVar); // 输出: "bigint"
console.log(typeof symbolVar); // 输出: "symbol"
console.log(typeof objectVar); // 输出: "object"
console.log(typeof functionVar); // 输出: "function"
//typeof null 返回 "object"
let nullVar = null;
console.log(typeof nullVar);
但是空类型 null 用 typeof 判断不出来,据说这是 JavaScript 当年的设计者引入的一个 Bug,由于兼容性的考虑一代代传承了下来。
但我们可以不使用 typeof来简单地判断 null:
let a =null;
console.log(a===null)//true
简单总结一下,typeof 可以准确判断除null之外的原始类型,也可以判断引用类型中的function,但无法判断对象和数组等其他引用类型。
2、instanceof 操作符
instanceof是通过原型链的查找来判断的,只能判断引用类型,它的工作原理是检查对象的原型链,看是否能找到指定构造函数的prototype。但是它不能准确判断基本数据类型,因为基本数据类型的变量不是对象,也没有原型链。
function MyObject(value) {
this.value = value;
}
let obj1 = new MyObject(10);
let obj2 = {};
let arr = [1, 2, 3];
let num = 42;
let str = "Hello, World!";
let bool = true;
let nullValue = null;
let undefinedValue;
console.log(obj1 instanceof MyObject); // 输出: true,因为 obj1 是 MyObject 的实例
console.log(obj2 instanceof Object); // 输出: true
console.log(arr instanceof Array); // 输出: true
console.log(obj1 instanceof Array); // 输出: false
// 尝试使用 instanceof 判断基本数据类型(会失败)
console.log(num instanceof Number); // 输出: false
console.log(str instanceof String); // 输出: false
console.log(bool instanceof Boolean); // 输出: false
3、Object.prototype.toString.call 方法
Object.prototype.toString.call 方法返回一个对象的详细类型信息,不仅可以判断基本数据类型,还可以准确地判断复杂对象类型。
let num = 42;
let str = "Hello, World!";
let bool = true;
let arr = [1, 2, 3];
let obj = { key: "value" };
let func = function() {};
let nullValue = null;
let undefinedValue;
let date = new Date();
let regExp = /regex/;
let sym = Symbol("symbol");
console.log(Object.prototype.toString.call(num)); // 输出: [object Number]
console.log(Object.prototype.toString.call(str)); // 输出: [object String]
console.log(Object.prototype.toString.call(bool));// 输出: [object Boolean]
console.log(Object.prototype.toString.call(arr)); // 输出: [object Array]
console.log(Object.prototype.toString.call(obj)); // 输出: [object Object]
console.log(Object.prototype.toString.call(func)); // 输出: [object Function]
console.log(Object.prototype.toString.call(nullValue)); // 输出: [object Null]
console.log(Object.prototype.toString.call(undefinedValue));// 输出: [object Undefined]
console.log(Object.prototype.toString.call(date));// 输出: [object Date]
console.log(Object.prototype.toString.call(regExp));// 输出: [object RegExp]
console.log(Object.prototype.toString.call(sym)); // 输出: [object Symbol]
4、Array.isArray 方法
Array.isArray() 是专门用来判断是否为数组的方法,不会受到原型链的影响。
const normalArray = [1, 2, 3];
console.log(Array.isArray(normalArray)); // 输出: true
// 创建一个类数组对象(拥有 length 属性和索引属性,但不是数组)
const arrayLikeObject = {
0: 'a',
1: 'b',
length: 2
};
console.log(Array.isArray(arrayLikeObject)); // 输出: false
// 创建一个数组的实例,但修改了它的原型链
const arrayWithModifiedPrototype = [];
arrayWithModifiedPrototype.__proto__ = {};
console.log(Array.isArray(arrayWithModifiedPrototype)); // 输出: true
// 通过 Object.create() 创建一个对象,其原型链指向 Array.prototype
const objectWithArrayPrototype = Object.create(Array.prototype);
objectWithArrayPrototype[0] = 'x'; // 可以添加索引属性,但这仍然不是真正的数组
console.log(Array.isArray(objectWithArrayPrototype)); // 输出: false
// 尽管这个对象的原型链指向 Array.prototype,Array.isArray() 仍然能正确识别它不是真正的数组实例
5、总结
在 JavaScript 编程中,确保类型判断的准确性对于编写稳定可靠的代码至关重要。不同的类型判断方法各有其独到之处,适用于不同的场景:
typeof操作符主要用于检测 JavaScript 中的基本数据类型,如字符串、数字、布尔值、undefined、function以及 ES6 引入的symbol类型。instanceof关键字则用于判断一个对象是否由某个特定的构造函数创建,即验证对象是否为该构造函数的实例。Object.prototype.toString.call方法因其广泛的适用性而受到青睐。它能够返回一个表示对象内部[[Class]]属性的字符串,从而揭示对象的真实类型。这种通用性使得它在处理各种复杂类型判断时尤为有效。Array.isArray函数则是专为数组类型判断而设计的。它能够准确判断一个对象是否为数组,且不受对象原型链的影响,确保判断的准确性和可靠性。
因此,在 JavaScript 编程中,开发者应根据具体需求选择合适的类型判断方法,以确保代码的稳定性和可靠性。