JavaScript继承Array时显式构造传super与默认构造行为差异问题
继承原生类时显式构造函数与默认构造行为不一致问题解析
复现场景
场景1:显式定义自定义构造函数
class MyArray extends Array { constructor(node) { console.log(node) super(node); console.log('nodes in constructor 1', node); // first } }; let argument = ['first','second']; let arr = new MyArray(...argument); console.log(arr) // [first]
实例化时传入
'first'、'second'两个参数,最终生成的arr实例仅包含['first']一个元素。
场景2:省略构造函数使用默认继承逻辑
class MyArray extends Array {}; let argument = ['first','second']; let arr = new MyArray(...argument); console.log(arr) // ['first', 'second']
同样传入两个参数实例化,最终生成的
arr实例包含'first'、'second'两个元素。
核心差异
两种场景的本质区别是传给父类Array构造函数的参数数量不同:
- 显式定义构造函数时,仅向
super()传递了1个参数,第二个入参被自定义构造函数截断丢弃。 - 使用默认构造函数时,所有传入子类的实参会被原封不动全部透传给父类构造函数,没有参数丢失。
根本原因
该行为是两个JS基础语法规则共同作用的结果,并非原生类继承的特殊bug:
- 函数形参匹配规则:JS中函数调用时,超出形参定义数量的实参不会自动绑定到已声明的形参上,除非使用剩余参数(
...args)语法显式接收。场景1中自定义构造函数仅声明了node1个形参,调用new MyArray(...argument)等价于执行new MyArray('first', 'second'),形参node仅能绑定第一个实参'first',第二个实参'second'未被形参接收,调用super(node)时自然只向父类传递了1个参数。 - Array构造函数的重载逻辑:
Array构造函数会根据传入参数的数量和类型执行不同逻辑:- 传入1个正整数参数时,将该值作为数组长度创建对应长度的空位数组
- 传入1个非数值参数时,将该参数作为唯一元素创建单元素数组
- 传入2个及以上参数时,将所有参数按顺序作为数组元素创建数组
场景1中仅向super()传入1个字符串参数'first',符合单参数非数值的逻辑分支,因此生成仅含一个元素的数组;场景2中两个参数全部透传给父类,符合多参数逻辑分支,因此生成包含两个元素的数组。
如果需要显式定义构造函数同时保持和默认构造一致的传参行为,使用剩余参数接收所有入参再展开传递给super即可:
class MyArray extends Array { constructor(...args) { // 自定义逻辑 super(...args); // 自定义逻辑 } }
内容的提问来源于stack exchange,提问作者AshBadCoder
相关产品推荐
相关产品推荐

