1、typeof
console.log(typeof(124))//number
console.log(typeof('123'))//string
console.log(typeof(true))//boolean
console.log(typeof(undefined))//undefined
console.log(typeof(function(){}))//function
console.log(typeof(null))//object
console.log(typeof({}))//object
console.log(typeof([]))//object
console.log(typeof(new Date()))//object
操作实例
typeof函数返回的是字符串,判断代码如下
var kkk = 1234
if(typeof(kkk) == 'number'){
console.log('这个kkk是number类型')
//输出这个kkk是number类型
}
结论:typeof只能判断基本数据类型、undefined和function,复杂的数据类型以及null判断出来全是object
所以可以用typeof判断:
- 基本数据表类型,number、string、bool
- 判断undefined
- 判断function
2、Constructor
Constructor代表的是创建对象实例的构造函数,返回的是构造函数
console.log(undefined.constructor)//报错
console.log(null.constructor)//报错
let num = 123
console.log(num.constructor)//ƒ Number() { [native code] }
console.log('123'.constructor)//ƒ String() { [native code] }
console.log(true.constructor)//ƒ Boolean() { [native code] }
console.log({}.constructor)//ƒ Object() { [native code] }
console.log([].constructor)// Array() { [native code] }
console.log((new Date()).constructor)// Date() { [native code] }
console.log((function(){}).constructor)//ƒ Function() { [native code] }
操作实例
constructor函数返回的是构造函数,判断代码如下
function Person(name) {
this.name = name;
}
const person1 = new Person('Alice');
if (person1.constructor === Person) {
console.log('person1 是一个 Person 实例');
} else {
console.log('person1 不是一个 Person 实例');
}
// 对于内置对象,如Array
const arr = [1, 2, 3];
if (arr.constructor === Array) {
console.log('arr 是一个数组');
} else {
console.log('arr 不是一个数组');
}
结论
- undefined和null没有构造函数,所以执行undefined.constructor报错
- 可以用constructor来判断除了undefined和null的数据
注意事项
- 原型链被修改:如果对象的原型链被修改或构造函数被替换,constructor属性可能不再指向原始构造函数。
- 继承:在涉及继承的情况下,即使子类实例的constructor属性指向子类构造函数,有时你可能还需要检查其原型链上的其他构造函数。
- null 和 undefined:null和undefined没有constructor属性,尝试访问它们会导致错误。
举例子说明:
(1)继承的情况
function Parent() {}
function Child() {}
// 错误地继承,没有设置Child.prototype.constructor
Child.prototype = new Parent();
const childInstance = new Child();
console.log(childInstance.constructor === Child); // false,因为Child.prototype.constructor没有被正确设置
console.log(childInstance.constructor === Parent); // true,但这不是我们想要的
// Object.create方法将原型式继承的概念规范化
/*
这个是 Object.create的实现逻辑
function create(proto) {
function F(){}
F.prototype = proto
return new F()
}
*/
// 正确的继承方式
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child; // 显式设置constructor
const anotherChildInstance = new Child();
console.log(anotherChildInstance.constructor === Child); // true,正确
(2)原型链被修改或被覆盖的情况
function Person(name) {
this.name = name;
}
const person = new Person('Alice');
console.log(person.constructor === Person); // true,初始状态
// 修改原型链
Person.prototype = {
greet: function() {
console.log(`Hello, my name is ${this.name}`);
}
};
// 注意:这里没有显式地设置constructor属性
console.log(person.constructor === Person); // false,因为Person.prototype的constructor属性可能被重置或丢失
// 如果我们想要保留constructor属性,需要在修改原型时显式设置它
Person.prototype.constructor = Person;
console.log(person.constructor === Person); // true,现在正确了
// 创建一个新的Person实例来验证
const newPerson = new Person('Bob');
console.log(newPerson.constructor === Person); // true,对于新实例,constructor属性指向正确的构造函数
上面讲解了两种类型判断的方法:一种是typeof,另一种是constructor,但是两种方法都有自己的局限性,为了更可靠地判断对象的类型,JavaScript 提供了instanceof操作符和Object.prototype.toString.call()方法,下面我们继续讲解这两种方法
3、instanceof:instanceof操作符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上
if (person1 instanceof Person) {
console.log('person1 是 Person 的实例');
}
if (arr instanceof Array) {
console.log('arr 是 Array 的实例');
}
注意事项
instanceof 不能用于基本数据类型(如 Number、String、Boolean、Undefined、Null 和 Symbol),因为这些基本数据类型在 JavaScript 中并不是对象。当你尝试对一个基本数据类型使用 instanceof 时,JavaScript 会先尝试将该基本数据类型转换为对象(例如,通过调用 Number()、String() 等函数),但即便如此,由于基本数据类型的“包装”对象(如 Number 对象的实例)与直接通过字面量创建的基本数据类型值在 instanceof 检查时并不等同,因此这样的检查总是返回 false。
console.log(1 instanceof Number); // false
console.log("hello" instanceof String); // false
console.log(true instanceof Boolean); // false
console.log(undefined instanceof Object); // false
console.log(null instanceof Object); // false
console.log(Symbol('a') instanceof Symbol); // TypeError: Right-hand side of 'instanceof' is not callable
最后一个例子中,Symbol 不是一个构造函数,不能直接用于 instanceof,因此会抛出一个 TypeError。
对于基本数据类型的检查,通常使用 typeof 运算符,它可以直接返回基本数据类型的字符串表示。对于 null 和 Array、Date 等特殊对象类型,可能需要结合使用 typeof 和 instanceof 或其他方法(如 Array.isArray())来进行准确的判断。
4、Object.prototype.toString.call():这个方法返回表示该对象的字符串,其格式遵循[object Type],其中Type是对象的类型。
console.log(Object.prototype.toString.call(undefined))//[object Undefined]
console.log(Object.prototype.toString.call(null))//[object Null]
console.log(Object.prototype.toString.call(123))//[object Number]
console.log(Object.prototype.toString.call('123'))//[object String]
console.log(Object.prototype.toString.call(true))//[object Boolean]
console.log(Object.prototype.toString.call({}))//[object Object]
console.log(Object.prototype.toString.call([]))//[object Array]
console.log(Object.prototype.toString.call(new Date()))//[object Date]
console.log(Object.prototype.toString.call(function(){}))//[objectFunction]
console.log(Object.prototype.toString.call(person1)); // [object Object]
console.log(Object.prototype.toString.call(arr)); // [object Array]
function getType(obj) {
return Object.prototype.toString.call(obj).slice(8, -1);
}
console.log(getType(person1)); // "Object"(对于普通对象,除非重写了toString方法)
console.log(getType(arr)); // "Array"
请注意,对于自定义对象,Object.prototype.toString.call()返回的通常是[object Object],除非对象的toString方法被重写以返回不同的值。在大多数情况下,instanceof和Object.prototype.toString.call()是更可靠和灵活的类型检测方法。