扒下JS的“底裤”之 instanceof 运算符详解

156 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情

详解instanceof

基本概念

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

也就是说

instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。

语法

/*
 *2个参数
 *object 某个实例对象
 *constructor 某个构造函数
*/
object instanceof constructor 

示例

1.简单应用

function C(){}
function D(){}

var o = new C();

o instanceof C; // true,因为 Object.getPrototypeOf(o) === C.prototype

o instanceof D; // false,因为 D.prototype 不在 o 的原型链上

o instanceof Object; // true,因为 Object.prototype.isPrototypeOf(o) 返回 true
C.prototype instanceof Object // true,同上
  1. 改变constructor.prototype的值

如果表达式 obj instanceof Foo 返回 true,则并不意味着该表达式会永远返回 true,因为 Foo.prototype 属性的值有可能会改变,改变之后的值很有可能不存在于 obj 的原型链上,这时原表达式的值就会成为 false。

// 接上前面的例子
C.prototype = {};
var o2 = new C();

o2 instanceof C; // true

o instanceof C; // false,C.prototype 指向了一个空对象,这个空对象不在 o 的原型链上。

D.prototype = new C(); // 继承
var o3 = new D();
o3 instanceof D; // true
o3 instanceof C; // true 因为 C.prototype 现在在 o3 的原型链上
  1. 改变原型链

改变对象 obj 的原型链的情况,虽然在目前的 ES 规范中,我们只能读取对象的原型而不能改变它,但借助于非标准的 proto 伪属性,是可以实现的。比如执行 obj.proto = {} 之后,obj instanceof Foo 就会返回 false 了。

function C() {}
let c = new C()

console.log(c instanceof C); // true

c.__proto__ = {}

console.log(c instanceof C); // false 这里c的原型链已经被修改
  1. 演示 String 对象和 Date 对象都属于 Object 类型和一些特殊情况
  • String 和 Date 对象同时也属于Object 类型(他们是由 Object 类派生出来的)。

  • 使用对象文字符号创建的对象在这里是一个例外:虽然原型未定义,但 instanceof Object 返回 true。

var simpleStr = "This is a simple string";
var myString  = new String();
var newStr    = new String("String created with constructor");
var myDate    = new Date();
var myObj     = {};
var myNonObj  = Object.create(null);

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

myObj instanceof Object;    // 返回 true,尽管原型没有定义
({})  instanceof Object;    // 返回 true,同上
myNonObj instanceof Object; // 返回 false,一种创建非 Object 实例的对象的方法

myString instanceof Date; //返回 false

myDate instanceof Date;     // 返回 true
myDate instanceof Object;   // 返回 true
myDate instanceof String;   // 返回 false

不是...的实例

直接使用if条件,记得加括号!!! 因为!的运算优先级比instanceof高

详情见

运算符优先级表

要检测对象不是某个构造函数的实例时,你可以这样做

if (!(mycar instanceof Car)) {
  // Do something, like mycar = new Car(mycar)
}

这和以下代码完全不同

if (!mycar instanceof Car)

instanceof 和多全局对象 (例如:多个 frame 或多个 window 之间的交互) 待补

涉及原型链,待补