详解javascrpit中类型判断的各种方法

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判断:

  1. 基本数据表类型,number、string、bool
  2. 判断undefined
  3. 判断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的数据

注意事项

  1. 原型链被修改:如果对象的原型链被修改或构造函数被替换,constructor属性可能不再指向原始构造函数。
  2. 继承:在涉及继承的情况下,即使子类实例的constructor属性指向子类构造函数,有时你可能还需要检查其原型链上的其他构造函数。
  3. 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()是更可靠和灵活的类型检测方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晨枫阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值