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

而Car和Object的原型对象``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
  • 所以两者可以说是互补,在合适的地方使用
相关推荐
米米商聊2 小时前
同名附件为什么被 Map 覆盖?重复键与一对多索引
前端·javascript
echome8883 小时前
Python 异常处理:try、else、finally 的正确搭配
开发语言·前端·python·异常处理·编程技巧
时间的情敌3 小时前
OpenLayers 实战|Vue3 + OpenLayers 完整工程案例(加载天地图、要素、弹窗、绘制、WFS)
前端·openlayers
陈随易3 小时前
下载神器!Motrix 停更三年后重写回归
前端·后端·程序员
前端的日常4 小时前
一个人+AI做情侣食谱小程序,0 费用的服务器
前端·后端
计算机魔术师4 小时前
谷歌搜索广告踩刹车,AI广告成为救命稻草
前端
总要学点什么4 小时前
第81篇:数据可视化-PM2.5分布——让圆点的胖瘦替每座城市报出浓度
前端·信息可视化·echarts·cesium·空间分析
IT_陈寒4 小时前
Vue的v-for里用了个临时变量,页面直接挂了
前端·人工智能·后端
hunter_0764 小时前
一次 iOS 真机签名 409 的完整排查:证书、设备、描述文件为什么总是"对不上"
前端
枣把儿5 小时前
开源!公众号排版+一键发布工具懒人版
前端