typeOf
typeof是一个JavaScript操作符,用于返回一个值的数据类型。它的语法格式为:typeof value,其中value可以是任意JavaScript值。typeof操作符返回的结果是一个字符串,表示value的数据类型。
- 基本数据类型:除了 null 都可以显示正确的类型
- 复杂数据类型(Object):除了函数都会显示 object
console.log(typeof 2); // number
console.log(typeof true); // boolean
console.log(typeof "str"); // string
console.log(typeof []); // object []数组的数据类型在 typeof 中被解释为 object
console.log(typeof function () {}); // function
console.log(typeof {}); // object
console.log(typeof undefined); // undefined
console.log(typeof null); // object null 的数据类型被 typeof 解释为 object
instanceof
instanceof是一个JavaScript操作符,用于检测一个对象是否是某个构造函数的实例。它的语法格式为:object instanceof constructor,其中object是要检测的对象,constructor是要检测的构造函数。如果object是constructor的实例,那么instanceof操作符返回true,否则返回false。
在使用instanceof操作符时,需要注意以下几点:
- constructor必须是一个构造函数(例如Object、Array、Function等),不能是其他类型的值(例如字符串、数字、布尔值等)。
- object必须是一个对象,不能是其他类型的值。
- 如果object的原型链上存在constructor.prototype,那么object就被认为是constructor的实例。因此,即使constructor的原型链上有其他构造函数的prototype,只要object的原型链上存在constructor.prototype,那么object就被认为是constructor的实例。例如,
[] instanceof Object返回true,因为数组的原型链上存在Object.prototype。 - 如果constructor不是一个函数,那么会抛出一个TypeError异常。
示例代码:
console.log((2).constructor === Number); // true
console.log(true.constructor === Boolean); // true
console.log("str".constructor === String); // true
console.log([].constructor === Array); // true
console.log(function () {}.constructor === Function); // true
console.log({}.constructor === Object); // true
function Fn() {}
Fn.prototype = [];
const f = new Fn();
console.log(f.constructor === Fn); // false
console.log(f.constructor === Array); // true
typeOf和instanceof的区别
- typeof可以用来判断基础数据类型,其中除了null,其它基础数据类型都可以判断出来
console.log(typeof 2); // number
console.log(typeof true); // boolean
console.log(typeof "str"); // string
console.log(typeof undefined); // undefined
console.log(typeof null); // object null 的数据类型被 typeof 解释为 object
- typeof在判断对象的时候除了函数可以正确判断以外,其它数据类型都是无法正确的判断的,返回结果都是object
console.log(typeof function () {}); // function
console.log(typeof []); // object []数组的数据类型在 typeof 中被解释为 object
console.log(typeof {}); // object
- instanceof是通过原型链的方式来判断数据类型的
const data = {name: 'Alice'};
function func(){}
console.log(func instanceof Function); // true
console.log(data instanceof Object); // true
//如果要正确判断是否是数组则要使用
Array.isArray([])
- instanceof判断不了基本的数据类型,因为基础数据类型本质上不是对象,它们没有原型链,也没有类似构造函数,所以无法判断它们的类型
const str = "hello";
console.log(str instanceof String); // 抛出 TypeError 错误
- instanceof检测对象的一些示例
// 使用instanceof检测对象的类型
class Person { // 定义一个Person类
constructor(name, age) {
this.name = name;
this.age = age;
}
}
const person1 = new Person("Alice", 18); // 使用Person类创建一个对象
const person2 = { name: "Bob", age: 20 }; // 创建一个普通的对象
console.log(person1 instanceof Person); // 输出true,因为person1是Person类的实例
console.log(person1 instanceof Object); // 输出true,因为person1是Object类的实例
console.log(person2 instanceof Person); // 输出false,因为person2不是Person类的实例
console.log(person2 instanceof Object); // 输出true,因为person2是Object类的实例
// 使用typeof检测变量是否被定义
let x; // 定义一个未赋值的变量x
console.log(typeof x); // 输出“undefined”,因为x未赋值
if (typeof y === "undefined") { // 如果变量y未被定义
console.log("y is not defined"); // 输出“y is not defined”
}
// 使用instanceof检测函数是否是某个类的实例
class Animal { // 定义一个Animal类
constructor(name) {
this.name = name;
}
say() {
console.log(`I am a ${this.name}`);
}
}
function Dog(name) { // 定义一个Dog函数,它相当于Animal的子类
Animal.call(this, name); // 调用Animal的构造函数
}
Dog.prototype = Object.create(Animal.prototype); // Dog继承Animal类的方法和属性
const dog = new Dog("dog"); // 使用Dog函数创建一个对象dog
console.log(dog instanceof Dog); // 输出true,因为dog是Dog类的实例
console.log(dog instanceof Animal); // 输出true,因为dog是Animal类的实例
console.log(dog instanceof Object); // 输出true,因为dog是Object类的实例
constructor
在 JavaScript 中,可以使用 constructor 属性来检查一个值的数据类型。每种数据类型都有其对应的构造函数。
console.log((2).constructor === Number); // true
console.log(true.constructor === Boolean); // true
console.log("str".constructor === String); // true
console.log([].constructor === Array); // true
console.log(function () {}.constructor === Function); // true
console.log({}.constructor === Object); // true
function Fn() {}
Fn.prototype = [];
const f = new Fn();
console.log(f.constructor === Fn); // false
console.log(f.constructor === Array); // true
不过这种方法也有缺点,因为 constructor 的指向可以被更改。
例如,可以通过更改构造函数的 prototype 属性来更改一个对象的 constructor 属性。如下所示:
function Person(name, age) {
this.name = name;
this.age = age;
}
const person = new Person("Tom", 20);
console.log(person.constructor === Person); // 输出: true
Person.prototype.constructor = Array;// 更改constructor的指向
console.log(person.constructor === Person); // 输出: false
console.log(person.constructor === Array); // 输出: true
在上面的代码中,首先创建了一个 Person 构造函数和一个 person 对象,并检查了 person 对象的 constructor 指向,其值是 Person。然后将 Person 的 prototype.constructor 指向更改为 Array,并再次检查 person 对象的 constructor 指向值,发现其值已经变成了 Array,而不再是 Person。
因此,通过 constructor 指向值来确定数据类型并不是一种可靠的方式,不能保证其一定正确。更加可靠的方式是使用 typeof 或 instanceof 运算符来检查数据类型。
Object.prototype.toString.call()
通过 Object.prototype.toString.call() 方法也可用于检查一个值的数据类型。该方法返回一个表示该值数据类型的字符串。
例如,以下代码使用了 Object.prototype.toString.call() 方法来检查对象、数组、字符串、数值、布尔和函数类型的数据:
const obj = { name: "Tom" };
console.log(Object.prototype.toString.call(obj)); // 输出: [object Object]
const arr = [1, 2, 3];
console.log(Object.prototype.toString.call(arr)); // 输出: [object Array]
const str = "hello";
console.log(Object.prototype.toString.call(str)); // 输出: [object String]
const num = 123;
console.log(Object.prototype.toString.call(num)); // 输出: [object Number]
const bool = true;
console.log(Object.prototype.toString.call(bool)); // 输出: [object Boolean]
function foo() {}
console.log(Object.prototype.toString.call(foo)); // 输出: [object Function]
上述代码中,将不同类型的数据作为参数传递给 Object.prototype.toString.call() 方法,并输出了它所返回的字符串。
需要注意的是,返回的字符串包含了 [object ...] 的格式,其中 ... 表示该值的数据类型。例如,[object Object] 表示该值是一个对象类型。
此外,使用 Object.prototype.toString.call() 方法检查数据类型的好处是不会受到 constructor 属性被更改的影响,因为该方法返回的字符串是根据值的数据类型来确定的,而不是根据对象的 constructor 属性来确定的。