使用bind()定义自定义元素报错,继承表现异常原因咨询
Web Components中bind()绑定自定义元素构造器失效的原因
一、直接用bind()注册为何抛出Illegal constructor?
自定义元素规范对注册的构造器有严格要求:
- 必须是原生类构造器(或符合规范的函数),能被
new无参调用(浏览器创建元素时会自动无参执行new 构造器()) - 构造器的
prototype必须继承自对应内置元素的原型(如HTMLElement.prototype)
而Function.prototype.bind()返回的是绑定函数(bound function),它不满足规范要求:
- 绑定函数不属于原生类构造器类型,浏览器的自定义元素创建逻辑会直接校验失败
- 即便跳过校验,浏览器无参调用绑定函数时,预设的参数会导致原构造器接收到的参数完全不符合预期,违反自定义元素构造器不能接收外部参数的规范
对应示例代码的错误场景:
customElements.define( "my-custom-element", LogOnClickComponent.bind(void 0, console) );
浏览器创建<my-custom-element>时,调用绑定函数触发规范校验失败,抛出Illegal constructor。
二、继承绑定后的类为何出现异常?
当使用class extends LogOnClickComponent.bind(void 0, console)时,JS引擎会将绑定函数视为父类构造器,但存在两个核心问题:
- 原型链断裂:绑定函数的
prototype是普通对象,而非原类LogOnClickComponent的prototype,导致子类无法继承HTMLElement的原生特性(如getter/setter、预定义事件) - 参数传递混乱:子类构造器无参调用
super()时,实际调用的是已预设参数的绑定函数,导致原构造器的参数接收逻辑混乱。比如示例中this.logger被赋值为console,但后续执行this.logger(this, 'in constructor')时,console不是函数,抛出TypeError: this.logger is not a function
三、自定义bound函数为何能正常工作?
自定义bound函数返回的是一个合法的原生子类,完全符合自定义元素规范:
function bound(it, ...args) { return class extends it { constructor() { super(...args, ...arguments) } } }
- 返回的是原生类构造器,能通过浏览器的规范校验
- 子类的
prototype正确继承自原类it的prototype,进而继承HTMLElement.prototype,保证内置元素特性正常 - 子类构造器调用
super()时,主动将预设参数args和构造时的参数(浏览器无参传入)传递给父类,确保原构造器能正确接收logger参数
当注册bound(LogOnClickComponent, console)时,浏览器无参调用子类构造器,super(...args, ...arguments)将console正确传递给LogOnClickComponent的构造器,所有逻辑符合规范,因此能正常运行。
总结
bind()返回的绑定函数不是合法的自定义元素构造器,无法通过浏览器的规范校验- 继承绑定函数会破坏原型链,导致内置元素的原生特性失效
- 自定义
bound函数通过返回合法子类,既实现了参数预设,又严格符合自定义元素规范
内容的提问来源于stack exchange,提问作者asdru
相关产品推荐
相关产品推荐

