likes
comments
collection
share

一起来看看Js中那些常用的的类型判断!在js中,类型判断是一个很常见的需求,在处理一些数据时我们经常需要知道它们的数据类

作者站长头像
站长
· 阅读数 21

前言

在js中,类型判断是一个很常见的需求,在处理一些数据时我们经常需要知道它们的数据类型。在js中我们也有许多方法来进行类型判断。

js中的存储

在聊类型判断之前,我们先聊聊js中的不同数据类型的值是存储在哪里的。

原始类型是以值的形式存储的,且值是存在调用栈中的,而因为调用栈的空间是比较小的,引用类型的数据当量可能会非常大,如果引用类型的数据也存在调用栈里,可能会导致爆栈。

所以js把引用类型的值存在堆结构里,把它们的引用地址存放在栈里。当需要用到这些数据时,只需要通过引用地址就可以快速地在堆中拿到数据。

typeof

typeof这个运算符可以用来判断除null以外所有的原始数据类型,不能判断除function以外的所有引用数据类型。那为什么会这样呢?这和它的判断原理有关:

typeof的判断原理是将数据的值转化为二进制,看其前三位进行判断,而在 JS 的最初版本中使⽤的是 32 位系统,为了性能考虑,使⽤低位存储变量的类型信息,000 开头代表是对象,而除了function以外所有的引用类型转换为二进制前三位都是000,然而null的二进制全为0。


console.log(typeof 10);             // number
console.log(typeof "hello");         // string
console.log(typeof true);            // boolean
console.log(typeof undefined);        // undefined
console.log(typeof null);             // object
console.log(typeof function(){});     // function

instance of

instanceof 只能判断引用类型的数据。因为它的判断原理是根据原型链进行查找,前面我们讲到原始数据类型是以值的形式进行存储的,而不是通过引用存储的对象,所以原始数据类型是没有原型链的。

判断原理:

console.log({} instanceof Function) 首先它会获取右边构造函数Function的原型prototype 然后会检查右边对象的原型链上是否包含构造函数的原型。 如果找到了匹配的原型,则返回true,如果一直找到顶端还没有匹配,则返回false

在面试的时候有的面试官可能会问到typeof 和 instanceof的区别,其实只需要搞懂它们两个的判断原理就可以轻松回答出来了。还有的面试官可能会让我们手写一个instanceof,其实这也很简单:

手写instanceof

我们已经知道instanceof的判断原理是根据原型链进行查找,所以我们只需要用一个while循环一级一级地比对就可以了

function myInstanceof(left, right) {
    while(left !== null) {
        if(left.__proto__ == right.prototype) {
            return true;
        }
        left = left.__proto__;
    }
    return false;
}

var arr = [];
console.log(myInstanceof(arr, Array));          // true
console.log(myInstanceof(arr, Function));       // false

这里还有需要注意的地方,所有原型链最终都会终止于Object.prototype,这是js中的最高原型。Object.prototype__proto__null,所以while循环的条件为left !== null,当找到原型链的顶端还没有找到时,就要返回false。

也正是因为所有原型链顶端都是Object.prototype,所以不管哪个引用类型用instanceof判断是否为Object类型,都会得到true

Object.prototype.toString.call()

这个方法是对象原型上的方法,但它不光可以判断引用类型还可以判断原始类型。它的判断过程是这样的:

如果call里面的参数是null,则返回"[Object Null]" 如果call里面的参数是undefined,则返回"[Object Undefined]" 如果不是上面两者,则会调用ToObject(x)方法,将x转化为对象,这个对象的内部有一个[[class]]属性值,即为代表x的类型的字符串 接着将[[class]]作为class变量的值 接着将会将 "[Objectclass变量 和 ]" 拼接在一起,得到最后的结果。如 "[Object Number]"

注意这里toString后面一定要接.call()方法,因为这里如果不接.call(),那么toString方法的this指向Object,最后判断出来就是 "[Object Object]" ,这里的call可以将this的指向改变到要判断的值身上,这样才能成功判断。

Array.isArray

这个方法是用来判断某个值是不是数组,是则返回true,否则返回false,使用起来也很简单:

const arr = [1, 2, 3];
console.log(Array.isArray(arr));  // true
console.log(Array.isArray('not a Array'))  // false

Number.isNaN()

这个方法是Number对象上的静态方法,可以用来判断一个值是不是NaN

console.log(Number.isNaN(NaN));  // true
console.log(Number.isNaN('NaN'));  // false
转载自:https://juejin.cn/post/7416270933789474831
评论
请登录