JavaScript基础面试题3--typeof 与 instanceof 区别
前言
1. typeof
typeof
操作符返回的是一个字符串,表示未经计算的操作符类型
例:
typeof 1 // number
typeof '1' // string
typeof undefined // undefined
typeof true // boolean
typeof Symbol() // sumbol
typeof [] //objrct
typeof {} // object
typeof console // object
typeof console.log // function
typeof null // object
- 上面的例子当中,前面五个是基本数据类型。最后一个
typeof null
为object
,这是JavaScript存在的一个悠久历史Bug
,不代表null
就是引用数据类型,而且null
本身也不是对象。 null
在typeof
之后返回的是有问题的结果,不能作为判断null
的方法。如果需要在if
语句中判断是否为null
,直接通过=== null
进行判断。- 引用类型若使用
typeof
进行判断,除了function
会被识别外,其余全部输出object
。 - 如果要判断一个变量是否存在,可以使用
typeof
。(若使用if(a)
,且a
未声明,则会报错)
if(typeof a != 'undefined'){
// 变量存在
}
2. instanceof
instanceof
运算符用于检测构造函数的 prototype
属性是否出现在某个实例对象的原型链上。构造函数通过 new
可以实例化对象,instanceof
能判断这个对象是否是之前那个构造函数所生成的对象。
let Student = function () {}
let s1 = new Student();
console.log(s1 instanceof Student); // true
let str = 'Hello'
console.log(str instanceof String) // false
这里模拟 instanceof
实现原理:
function myInstanceof (leftObj,rightObj){
// 先使用 typeof 判断是否为基本类型 如果是直接返回 false
if(typeof leftObj !=='object' || leftObj === null){
return false;
}
// getProtoTypeOf 是Object 自带的 API, 能够获取到参数的原型对象
let proto = Object.getProtoTypeOf(leftObj);
while(true){
if(proto === null) return false;
// 找到相同的原型对象, 返回 true
if(proto === rightObj.prototype) return true;
// 顺着原型链去找,直到找到相同的原型对象
proto = Object.getProtoTypeOf(proto);
}
}
let Student = function (){}
let s1 = new Student()
console.log(myInstanceof(s1,Student)) //true
3.区别
typeof
与 instanceof
都是判断数据类型的操作符,区别如下:
typeof
返回一个变量的基本类型,instanceof
返回的是一个布尔值;instanceof
可以准确的判断复杂引用数据类型,但是不能正确判断基本数据类型;typeof
虽然可以判断基本数据类型(null
除外),但是引用类型除了function
可以识别,其他类型都无法判断。
4.实现全局通用数据类型判断方法
若需要通用的检测数据类型,可以采用 Object.prototype.toString
,调用该方法时,统一返回格式为 [Object Xxx]
的字符串。这里的 .call()
会改变toString
方法内部的 this
指向,使其指向传递的参数。因此会返回要查看参数类型。
Object.prototype.toString({}) // "[object Object]"
Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call(10) // "[object Number]"
Object.prototype.toString.call('10') // "[object String]"
Object.prototype.toString.call(false) // "[object Boolean]"
Object.prototype.toString.call(function () {}) // "[object Function]"
Object.prototype.toString.call(() => {}) // "[object Function]"
console.log(Object.prototype.toString.call(null)); // "[object Null]"
console.log(Object.prototype.toString.call(undefined)); // "[object Undefined]"
console.log(Object.prototype.toString.call(/abc/g)); // "[object RegExp]"
console.log(Object.prototype.toString.call([])); // "[object Array]"
根据上面的调用形式,实现一个全局通用的数据类型判断方法:
function getObjType (obj){
// 判断若为基本类型 直接返回
if (typeof obj !== 'object'){
return typeof obj;
}
// 正则构建返回具体类型
return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/,'$1'));
}