instanceof和typeof的区别

instanceof和typeof的区别

在看他们的区别之前我觉得我们需要先了解两者

instanceof

来自官方的定义:

instanceof 运算符 用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

它是可以检测到每个实例对象是否出现在构造函数的原型对象prototype链上

所以在了解此知识前我们需要先了解原型链知识

在这篇文章中我们就不过多介绍了

所以我们先看关于instanceof的代码例子

js 复制代码
function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
const auto = new Car('Honda', 'Accord', 1998);

console.log(auto instanceof Car);
// 输出: true

console.log(auto instanceof Object);
// 输出: true

因为auto的原型链中是

js 复制代码
auto
↓
Car.prototype
↓
Object.prototype
↓
null

CarObject的原型对象``prototype在auto的原型链中所以结果为true

但是呢其实instanceof的结果也不是一成不变的

我们看以下示例

js 复制代码
//定义两个函数
function C() {}
function D() {}

const o = new C();    //o-->C.prototype-->Object.prototype-->null

o instanceof C;     // true

o instanceof D;      // false  o的原型链中没有D.prototype

o instanceof Object;   // true

C.prototype instanceof Object; // true           C.prototype的原型链为C.prototype-->Object.prototype-->null  
//因为Object的prototype在C.prototype的原型链中  所以结果为true

C.prototype = {};   //在这里重写了C.prototype 赋予了他新的一个对象 
//   原型链变为   C的新prototype--> Object.prototype-->null 
const o2 = new C();  //原型链为   o2-->C的新prototype--> Object.prototype-->null 

o2 instanceof C; // true   综上所述  为true

o instanceof C;  //false   因为此时C的原型不在o的原型链中  因为o的原型链未被改变  其原型链中的元素还是一样  只是其中原本为C的prototype不再是  C的prtotype  但是o的原型链指向不变  还是原来的内存地址上的对象 所以在instanceof运算符执行时发现C的原型不在原型链中

D.prototype = new C();
const o3 = new D();   //其原型链为  o3 ---> D.prototype ---> new C() ---> C.prototype ---> Object.prototype ---> null
o3 instanceof D; // true   
o3 instanceof C; // true 

其实 instanceof 运算符就是检测目标对象的原型链上是否有某个构造函数的prototype 有就返回true 否则 false

但是构造函数的prototype不是一成不变的 所以 instanceof的值也不是一成不变的

还有也要注意目标变量是否为对象

js 复制代码
var simpleStr = "This is a simple string";
var myString = new String();
var newStr = new String("String created with constructor");


simpleStr instanceof String; // 返回 false,非对象实例,因此返回 false   
myString instanceof String; // 返回 true
newStr instanceof String; // 返回 true

在上面simpleStr只是一个基本类型变量不是一个实例对象

让我们来手写一个instanceof

这也是面试经常考察的点

其实中心思想就是按着实例对象的proto在原型链上一直寻找构造函数的prototype在不在上面

js 复制代码
function Instanceof(instance, construction) {
  let instanceval = instance.__proto__;
  let Prototype = construction.prototype;
  while (true) {
    if (instanceval === null) return false;
    if (instanceval === Prototype) return true;
    instanceval = instanceval.__proto__;
  }
}
console.log(Instanceof({},Object));  //输出:true

typeof

typeof 运算符返回一个字符串,表示操作数的类型。

js 在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息

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

null:是 000 所以才判断为对象

js 复制代码
console.log(typeof 42);
// 输出 "number"
console.log(typeof 'blubber');
// 输出 "string"
console.log(typeof true);
// 输出 "boolean"
console.log(typeof undeclaredVariable);
// 输出 "undefined"

我们先看一下能够返回的值的列表

类型 结果
Undefined "undefined"
Null "object"原因
Boolean "boolean"
Number "number"
BigInt "bigint"
String "string"
Symbol "symbol"
Function(在 ECMA-262 中实现 [[Call]];classes也是函数) "function"
其他任何对象 "object"

我们要注意null返回的也是object

我们再看MDN上的例子

typeof 操作符的优先级高于加法(+)等二进制操作符

js 复制代码
// 数值
typeof 37 === "number";
typeof 3.14 === "number";
typeof 42 === "number";
typeof Math.LN2 === "number";
typeof Infinity === "number";
typeof NaN === "number"; // 尽管它是 "Not-A-Number" (非数值) 的缩写
typeof Number(1) === "number"; // Number 会尝试把参数解析成数值
typeof Number("shoe") === "number"; // 包括不能将类型强制转换为数字的值

typeof 42n === "bigint";

// 字符串
typeof "" === "string";
typeof "bla" === "string";
typeof `template literal` === "string";
typeof "1" === "string"; // 注意内容为数字的字符串仍是字符串
typeof typeof 1 === "string"; // typeof 总是返回一个字符串
typeof String(1) === "string"; // String 将任意值转换为字符串,比 toString 更安全

// 布尔值
typeof true === "boolean";
typeof false === "boolean";
typeof Boolean(1) === "boolean"; // Boolean() 会基于参数是真值还是虚值进行转换
typeof !!1 === "boolean"; // 两次调用 !(逻辑非)运算符相当于 Boolean()

// Symbols
typeof Symbol() === "symbol";
typeof Symbol("foo") === "symbol";
typeof Symbol.iterator === "symbol";

// Undefined
typeof undefined === "undefined";
typeof declaredButUndefinedVariable === "undefined";
typeof undeclaredVariable === "undefined";

// 对象
typeof { a: 1 } === "object";

// 使用 Array.isArray 或者 Object.prototype.toString.call
// 区分数组和普通对象
typeof [1, 2, 4] === "object";

typeof new Date() === "object";
typeof /regex/ === "object";

// 下面的例子令人迷惑,非常危险,没有用处。避免使用它们。  new出来的都是对象
typeof new Boolean(true) === "object";
typeof new Number(1) === "object";
typeof new String("abc") === "object";

// 函数
typeof function () {} === "function";
typeof class C {} === "function";
typeof Math.sin === "function";

你在上面也发现了typeof很难准确判断引用类型 因为都是返回object 除了函数 但是对于基础类型数据能够很好的判断

两者区别

根据上面两个介绍我相信大家都有了很好的一个了解,主要总结两者以下的特点

  • typeof 会返回一个运算数的基本类型,instanceof 返回的是布尔值
  • instanceof能够很好的判断引用数据的类型,但是对于基础类型数据无法判断
  • typeof能够很好的判断基础数据类型,但是无法很好的判断引用类型,因为都会返回object
  • 所以两者可以说是互补,在合适的地方使用
相关推荐
崔庆才丨静觅7 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60618 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了8 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅8 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅8 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅9 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment9 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅9 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊9 小时前
jwt介绍
前端
爱敲代码的小鱼9 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax