ES6中如何覆盖原生类方法?扩展File类后FileReader调用异常如何解决
问题根因
- 原生
FileReader是浏览器宿主API,不会调用JS层面你重写的stream()、text()、arrayBuffer()方法,而是直接读取Blob/File实例的内部二进制数据插槽。你之前继承File时构造器参数传错(原生File构造器第一个参数是内容片段数组,你传了文件名作为第一个参数),父类初始化时没有拿到你自定义的内容,所以读出来是空值。 - 你移除
extends File之后,就算自定义了Symbol.toStringTag和Symbol.hasInstance,也过不了宿主API的类型校验:浏览器的类型检查是判断对象是否有Blob对应的内部专属插槽,不会读取JS层面的自定义类型标识,所以直接抛出类型错误。
解决方法
方案1:修正继承参数,适配FileReader调用
如果你需要兼容FileReader的调用逻辑,直接把你自定义的内容(或者自定义的ReadableStream实例,新浏览器支持)传给父类File的构造器即可:
class MyFile extends File { constructor (name, options) { // 第一个参数填你自定义的内容,支持字符串、ArrayBuffer、ReadableStream等类型 super([getYourCustomContent()], name, options) this.customField = options.customField } // JS层面调用的方法可以正常重写 stream () { return new ReadableStream({ async start(controller) { /* 你的实现 */ }, async pull(controller) { /* 你的实现 */ }, async cancel() { /* 你的实现 */ } }) } async text () { // 你的实现 } async arrayBuffer () { // 你的实现 } }
方案2:直接调用自定义方法,跳过FileReader
如果没有强制使用FileReader的需求,直接调用你自己实现的text()、arrayBuffer()方法即可,比走FileReader逻辑更直接,也能完全触发你的自定义逻辑。
方案3:第三方库兼容处理
如果你的MyFile实例是要传给只能接收Blob/File类型的第三方库,你可以在传参前先把自定义内容转成标准Blob实例:
// 调用你自定义的arrayBuffer方法生成内容,转成标准Blob给第三方库 const standardBlob = new Blob([await myFile.arrayBuffer()]) thirdPartyMethod(standardBlob)
内容的提问来源于stack exchange,提问作者osy
相关产品推荐
相关产品推荐

