JavaScript使用class语法定义的子类为何不是父类的实例?
关于JS继承中构造函数本身instanceof父类返回false的问题
本站存在其他几乎完全相同的相关问题,但都属于TypeScript、Babel这类转译器的应用场景,本次讨论针对原生ECMAScript规则。
问题现象
使用class <child> extends <parent>语法创建的类,在执行<child> instanceof <parent>表达式时不会返回true,但继承了父类的子类的实例,同时属于父类和子类的实例。
相关测试代码如下:
class Parent { constructor(name) { this.name = name; } } class Child extends Parent { constructor(name) { super(name); } } var child = new Child(""); var typeError = new TypeError(""); console.log(child instanceof Child); // true console.log(child instanceof Parent); // true console.log(Child instanceof Parent); // false console.log(typeError instanceof TypeError); // true console.log(typeError instanceof Error); // true console.log(TypeError instanceof Error); // false
很多开发者会有疑问:如果Child继承了Parent,难道它不应该同时属于Parent的实例吗?
原因解释
这个结果完全符合ECMAScript的标准规则,核心是对构造函数本身和构造函数生成的实例的原型链逻辑认知有误:
instanceof运算符的判定规则是:检查右侧构造函数的.prototype属性,是否出现在左侧操作对象的原型链上- 当你使用
extends声明继承时,JS引擎只会修改Child.prototype的原型指向为Parent.prototype,保障子类的实例能继承到父类原型上的方法属性 Child作为构造函数本身,本质是Function的实例,它的原型链是Child -> Function.prototype -> Object.prototype,Parent.prototype根本不在这个链上,所以Child instanceof Parent必然返回false
你提到的TypeError和Error的逻辑也完全一致:只有new TypeError()生成的实例的原型链上才有Error.prototype,TypeError构造函数本身的原型链上不存在Error.prototype,所以TypeError instanceof Error返回false。
内容的提问来源于stack exchange,提问作者Melab
相关产品推荐
相关产品推荐

