为何JS父类构造函数直接赋值species报错?类字段写法却可行?
类继承中类字段与构造函数赋值的差异分析与修复
差异原因
第一段代码里的
species = "Homo sapiens"是ES6+类字段语法,这种写法会自动把species作为实例属性挂载到每个Humans实例上,底层逻辑和在构造函数里写this.species = "Homo sapiens"一致。而且类字段的初始化会在super()调用完成后自动执行,所以子类Family实例化时能正常继承并访问这个属性。第二段代码的构造函数里直接写
species = "Homo sapiens",没加this前缀,本质是尝试给未声明的变量赋值:- 非严格模式下会在全局作用域自动创建
species变量,但这不是类的实例属性,子类无法通过实例访问; - 类内部默认是严格模式,这种未声明就赋值的操作会直接抛出
ReferenceError,也就是你看到的"species未定义"报错。
- 非严格模式下会在全局作用域自动创建
修复方法
方法一:给构造函数内的赋值加this前缀
把父类构造函数里的species = "Homo sapiens"改成this.species = "Homo sapiens",这样species就会作为实例属性挂载到类实例上,子类继承后可正常访问:
class Humans { constructor(nameGiven) { this.nameGiven = nameGiven; this.species = "Homo sapiens"; // 添加this前缀 } } class Family extends Humans { constructor(nameGiven) { super(nameGiven); // 把参数传递给父类构造函数 console.log("We are a family") } } let Krishang = new Family("Krishang")
方法二:保留类字段写法(推荐)
如果运行环境支持ES6+类字段语法,直接用第一段代码的写法即可,这种写法更简洁直观,符合现代JS编码习惯。
另外注意:子类Family的构造函数需要接收参数并传给父类的super(),否则父类的this.nameGiven会变成undefined,修正后的代码已包含这部分逻辑。
内容的提问来源于stack exchange,提问作者Krishang Rana
相关产品推荐
相关产品推荐

