◆
JavaScript instanceof 原理与手写实现
instanceof
用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
语法:
object instanceof constructorobject:某个实例对象constructor:某个构造函数
返回值:
boolean表示对象是否为某个构造函数的实例。
用来检测
constructor.prototype是否存在于参数object的原型链上。
示例
// 定义构造函数
function C() {}
function D() {}
// 实例化一个 o 对象
var o = new C();
// true,true --> C.prototype 在 o 的原型链上
console.log(
o instanceof C,
o.__proto__ === C.prototype,
'此时 o 的 __proto__:',
o.__proto__,
'此时 C 的 prototype:',
C.prototype,
);
// false,false --> D.prototype 不在 o 的原型链上
console.log(o instanceof D, o.__proto__ === D.prototype);
// true true --> Object.prototype 在 o 的原型链上
console.log(o instanceof Object, o.__proto__.__proto__ === Object.prototype);
// 这时我们修改构造函数 C 的原型为一个空对象
C.prototype = {};
// 实例化一个 o2 对象
var o2 = new C();
// true --> C.prototype 在 o2 的原型链上
console.log(o2 instanceof C);
// false,C.prototype 指向了一个空对象,这个空对象不在 o 的原型链上.
console.log(
o instanceof C,
'此时 o 的 __proto__:',
o.__proto__,
'此时 C 的 prototype:',
C.prototype,
);
console.log('此时 D 的 prototype:', D.prototype);
// 继承
D.prototype = new C();
console.log('此时 D 的 prototype:', D.prototype);
var o3 = new D();
// true, true --> 因为 o3 是 构造函数 D new 出来的实例对象,所以 D.prototype 一定在 o3 的原型链上
console.log(o3 instanceof D, o3.__proto__ === D.prototype);
// true --> 因为 C.prototype 现在在 o3 的原型链上
console.log(o3 instanceof C);
// true,true --> 上面的结果为什么为 true 呢,看如下代码,D.prototype 是 构造函数 C new 出来的实例对象,所以 C.prototype 一定在 D.prototype 的原型链上
console.log(
o3.__proto__ === D.prototype,
D.prototype.__proto__ === C.prototype,
);
// true 相当于如下代码
console.log(o3.__proto__.__proto__ === C.prototype);
运行结果如图所示

一些容易出错的点
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);
// 返回 false, simpleStr 并不是对象
simpleStr instanceof String;
// 返回 true
myString instanceof String;
// 返回 true
newStr instanceof String;
// 返回 true
myString instanceof Object;
// 返回 true
myObj instanceof Object;
// 返回 true
({}) instanceof Object;
// 返回 false, 一种创建非 Object 实例的对象的方法
myNonObj instanceof Object;
// 返回 false
myString instanceof Date;
// 返回 true
myDate instanceof Date;
// 返回 true
myDate instanceof Object;
// 返回 false
myDate instanceof String;
Object.create(null)会造成创建的对象其__proto__指向为空instanceof运算符只能用于对象,不适用原始类型的值。

instanceof 判断基本数据类型的方法
tip
其实就是自定义 instanceof 行为的一种方式,这里将原有的 instanceof 方法重定义,换成了 typeof,因此能够判断基本数据类型。
class PrimitiveNumber {
static [Symbol.hasInstance](x) {
return typeof x === 'number';
}
}
// true
console.log(111 instanceof PrimitiveNumber);
手动实现一下 instanceof 的功能
function copyInstanceof(source, target) {
// 基本数据类型以及 null 直接返回 false
if (typeof source !== 'object' || source === null) return false;
// getProtypeOf 是 Object 对象自带的一个方法,能够拿到参数的原型对象
let proto = Object.getPrototypeOf(source);
while (true) {
// 查找到尽头,还没找到
if (proto == null) return false;
// 找到相同的原型对象
if (proto == target.prototype) return true;
proto = Object.getPrototypeOf(proto);
}
}
console.log(copyInstanceof('111', String)); // false
console.log(copyInstanceof(new String('111'), String)); // true

还没有留言,来发表第一条吧~