在大部分语言的中,检测对象是否是类的最直接方法是使用操作符instanceof。例如,在Java中,使用操作符instanceof检测左边的类和右边的类是否是同一个子类。它的作用是用来判断,instanceof 左边对象是否为instanceof 右边类的实例,返回一个boolean类型值。还可以用来判断子父类的所属关系。
虽然在JavaScript中操作符instanceof与java中基本类似,但是仍然有些不同。在JavaScript中,操作符instanceof使用在原型链中。例如,查看如下表达式:
ninjaTest instanceof NinjaTest
操作符instanceof用于检测NinjaTest函数是否存在于ninjaTest 实例的原型链中。
console.log("---------------探讨instanceof操作符--------------------");
function Person() {}
function NinjaTest() {}
NinjaTest.prototype = new Person();
//ninjaTest是NinjaTest的实例,同时也是Person的实例
const ninjaTest = new NinjaTest();
if (ninjaTest instanceof NinjaTest) {
console.log("Our ninjaTest is a NinjaTest");
}
if (ninjaTest instanceof Person) {
console.log("A ninjaTest is also a Person.");
}
ninjaTest是NinjaTest的实例,同时也是Person的实例,这一点符合预期。
下面是其工作原理:
ninjaTest实例的原型链是由new Person()对象与Person的原型组成的。
ninjaTest实例的原型链是由new Person()对象与Person的原型组成的,通过原型链实现继承。当执行ninjaTest instanceof NinjaTest表达式时,JavaScript引擎检查NinjaTest函数的原型——new Person()对象,是否存在于ninjaTest实例的原型链上。new Person()对象是ninjaTest实例的原理,因此,表达式的执行结果为true。
在检查ninjaTest instanceof Person时,javaScript引擎查找Person函数的原型,检查它是否存在于ninjaTest实例的原型链上。由于Person的原型的确存在于ninjaTest实例的原型链上,Person是new Person()对象的原型,所以Person也是ninjaTest实例原型。
尽管instanceof操作符最常见的用途就是提供一个清晰的方法来确定一个实例是否由特定的构造函数创建的,但并不完全是这样。事实上,它会检查操作符右边的函数的原型是否存在于操作符左边的对象的原型链上。
instanceof操作符的警告
因为JavaScript是一门动态语言,在程序的执行过程中,我们可以修改很多内容,例如,我们可以修改一个构造函数的原型。
console.log("-----------------------当心构造函数原型的改变------------------");
function NinjaTest() {}
const ninjaTest = new NinjaTest();
if (ninjaTest instanceof NinjaTest) {
console.log("nijaTest is a NinjaTest");
}
//修改'Ninja'的原型
NinjaTest.prototype = {};
//虽然ninjaTest仍然是由NinjaTest构造器创建的,但是instanceof操作符结果显示ninjaTest不是NinjaTest的实例
if(!(ninjaTest instanceof NinjaTest)) {
console.log("The ninja is now not a Ninja!");
}
从上面的代码中可以发现:我在ninjaTest实例创建完毕之后,修改了NnijaTest构造函数的原型,再次执行测试ninjaTest instanceof NinjaTest,发现结果发生了变化。此时假设坚持错误地假设instanceof操作符检测对象是否是由某一个构造函数创建的结论,就是错误了。事实上,它会检查操作符右边的函数的原型是否存在于操作符左边的对象的原型链上。
instanceof操作符检查右边的函数原型是否存在于操作符左边的对象的原型链上。小心函数的原型可以随时发生改变。
参考《JavaScript忍者秘籍》