instanceof 和 typeof 原理回顾

本文深入探讨了JavaScript中instanceof和typeof操作符的原理及应用,解析了它们如何判断对象类型,包括基本类型和引用类型的区别,以及如何通过自定义函数模拟instanceof的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

instanceof

概念

  • 官方定义: instanceof 运算符用来检测构造函数的prototype 属性是否出现在某个实例对象的原型链上.
  • 通俗的讲: instanceof 用来判断某个对象是否为某个构造函数的实例.
  • 形象的讲: 沿着操作符左边对象的proto这条线查找,沿着操作符右边对象的prototype查找.若两条线能找到同一个引用,则返回true.若到终点还未相交,则返回false.

语法

object instanceof constructor  // object为要测试的实例对象    constructor为构造函数 

注意: instanceof 无法判断基本类型,只能判断引用类型

let obj = new Object()
console.log(obj instanceof Object)  // true

class Person {}
const p = new Person()
console.log(p instanceof Person)  // true

// 判断 f 是否是 F 类的实例
function F(){}
const f = new F()
console.log(f.__proto__ === F.prototype)  // true   因为F的prototype === f的__proro__ 符合 instanceof 检测条件,所以下面为true
console.log(f instanceof F)  // true

下面的代码说明了 Date 也属于 Object 类型, Date 是由 Object 类派生出来的

const d = new Date()
console.log(d instanceof Date)  // true
console.log(Date instanceof Object)  // true
console.log(d instanceof Object)  // true

练习解题

题型1
console.log(Function instanceof Function)  
console.log(Function instanceof Object)
console.log(Object instanceof Function)
console.log(Object instanceof Object)

思路如下:

console.log(Function.__proto__ === Function.prototype)
console.log(Function.__proto__.__proto__ === Object.prototype)
console.log(Object.__proto__ === Function.prototype)
console.log(Object.__proto__.__proto__ === Object.prototype)
题型2
function Fun(){}
const f = new Fun()
console.log(f instanceof Fun)  // true

function Fun2(){return {}}
const f2 = new Fun2()
console.log(f2 instanceof Fun2)  // false

因为 instanceof 操作符是判断原型链上的对象,而当一个对象并不是通过原型构造出来的时候(直接return一个对象),此方法就失效了.

模拟实现instanceof函数

function instanceOf(obj, constructor){
  if(obj === null){
    return false
  }
  if(typeof obj !== 'object' && typeof obj !== 'function' ){
     return false
  }
  let proto = obj.__proto__
  while(proto){
    if(proto === constructor.prototype){
      return true
    }
    proto = proto.__proto__
  }
  return false
}

typeof

概念

typeof 操作符返回一个字符串,表示未经计算的操作数的类型

语法

typeof operand
typeof(operand)  // operand 是一个表示对象或原始值的表达式,其类型将被返回

历史发展

在很早之前,使用的32位系统,为了性能考虑使用低位存储了变量的类型信息.

  • 000 对象
  • 1 整数
  • 010 浮点数
  • 100 字符串
  • 110 布尔

此外还有2个比较特殊的指: undefinednull

  • undefined 用 (-2^30) 表示
  • null 对应机器码的 NULL 指针,一般是全零

这样一来,null 就出了一个bug.因为它对应的空指针,低位是000,因此被判断成一个对象了.且这个bug,应该是永远都不会去修复了.

可检测类型

console.log(typeof undefined)  // undefined
console.log(typeof null)  // object
console.log(typeof 123n)  // bigint
console.log(typeof Symbol('str'))  // symbol
console.log(typeof (() => {}))  // function
console.log(typeof {})  // object

在ES2015之前,typeof 总能保证对任何所给的操作数返回一个字符串,即使是未声明的标识符,也能返回undefined. 但是在有了letconst 块级作用域后,在其被声明之前对块中的letconst 变量使用 typeof 将会抛出一个 ReferenceError .

console.log(typeof obj2)  // Uncaught ReferenceError: Cannot access 'obj2' before initialization
const obj2 = {}

当前所有的浏览器都暴露了一个类型为 undefined 的非标准宿主对象 document.all

console.log(typeof document.all)  // undefined

获取类型的终结方案

我们通过 toString 来获取类型,算是一个比较完美的方案.

function getType(obj){
  let reg = /\[object\s(.+)\]/
  let type = Object.prototype.toString.call(obj)
  return type.replace(reg, '$1').toLowerCase()
}

// 或者下面的写法
function getType(obj){
  let type = Object.prototype.toString.call(obj)
  let reg = /\[object\s([^\s]+)\]/g
  if(reg.test(type)){
    return RegExp.$1.toLowerCase()
  }
}

总结

通常,我们使用 typeof 来判断基本类型 , instanceof 判断引用类型.

参考链接:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值