IOS WebView运行动态加载JS代码报HTMLScriptElement is not a function,疑似appendChild兼容问题
iOS WebView 环境下loadJs函数报错修复方案
问题根因
此前将问题归因于appendChild的兼容性,实际是被旧iOS WebView的失真报错堆栈误导:这类老旧WebView的错误提示不会准确指向真实触发源头,当实际因未给target参数传值、触发空对象方法调用时,堆栈会错误关联到script元素创建流程,弹出「HTMLScriptElement is not a function」的无关报错。
核心问题点
- 无参数兜底:原代码未对传入的target节点设置默认值,调用时漏传参数会直接将undefined作为节点对象,触发空方法调用
- 事件绑定兼容缺陷:在iOS 8-11的老旧UIWebView环境下,直接给动态创建的script元素赋值onerror属性,会触发元素构造阶段的异常
- 插入流程无校验:没有判断传入的target节点是否真的存在appendChild方法,极端场景下传入非节点对象时会直接触发报错
修复后兼容版本代码
const loadJs = (path, fn, target = document.head) => { let elem = document.createElement('script') let loaded = false const handleLoad = () => { if (loaded) return if (elem.readyState && !/^c|loade/.test(elem.readyState)) return loaded = true elem.onload = elem.onreadystatechange = null fn && fn() } elem.async = true // 特性检测,跳过老WebView不支持的onerror属性绑定 if ('onerror' in elem) { elem.onerror = handleLoad } elem.onload = handleLoad elem.onreadystatechange = handleLoad elem.src = path // 兜底校验节点方法存在再执行插入 if (typeof target.appendChild === 'function') { target.appendChild(elem) } }
补充排查提示:如果调整代码后仍出现同类报错,需要检查当前WebView页面的CSP安全策略配置,确认是否禁止了动态插入script标签的执行权限,这类安全拦截的报错在老WebView环境下同样会出现堆栈失真的问题。
内容的提问来源于stack exchange,提问作者wubber
相关产品推荐
相关产品推荐

