You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何第一个脚本调用replaceAll会触发第二个脚本的自定义方法并报错?

问题与解决方案

问题描述

两段脚本运行时出现异常:第一个脚本调用replaceAll时触发了第二个脚本的自定义函数,导致正则语法错误,最终第一个脚本也终止运行。已知失败原因,但不清楚第二个脚本为何被触发,且无法修改第二个脚本,需修复第一个脚本。

当前执行流程

  • 调用evaluate(expression)
  • 执行cleanExpression.replaceAll("[","")时触发第二个脚本的自定义函数
  • 自定义function(search, replacement)执行return target.replace(new RegExp(search, 'g'), replacement)时因正则语法错误失败
  • 最终导致evaluate函数执行失败

第一个脚本

class CustomProduct extends HTMLElement {

  evaluate(expression) {

    let cleanExpression = expression;
    cleanExpression = cleanExpression.replaceAll("[","");
    return math.evaluate(cleanExpression)
  }

}

第二个脚本

function SocialLoginNamespace() {

(function() {

    String.prototype.replaceAll = function(search, replacement) {
        var target = this;
        return target.replace(new RegExp(search, 'g'), replacement);
    };

}).call(this);

var socialLogin = new SocialLoginNamespace().socialLogin;
socialLogin.init();

报错信息

resource.js?shop=ccc.myshopify.com&cache_key=1650344:1241 Uncaught (in promise) SyntaxError: Invalid regular expression: /[/: Unterminated character class
    at new RegExp (<anonymous>)
    at SocialLoginNamespace.String.replaceAll (resource.js?shop=ccc.myshopify.com&cache_key=1650344:1241:31)
    at CustomProduct.evaluate (global.js:7956:39)
    at CustomProduct.evaluateFormula (global.js:7017:43)
    at async CustomProduct.textSelecting (global.js:5935:31)
    at async HTMLInputElement.<anonymous> (global.js:8564:9)

原因分析

  • 第二个脚本在String.prototype上添加了自定义的replaceAll方法,该方法会覆盖环境中原生的String.replaceAll(若环境支持ES2021+原生方法),或在不支持原生方法的环境中直接成为replaceAll的唯一实现。
  • 第一个脚本中调用cleanExpression.replaceAll("[", "")时,本质是调用字符串原型链上的replaceAll方法,也就是第二个脚本定义的自定义函数,因此触发了第二个脚本的代码执行。
  • 自定义replaceAll方法直接将未转义的search参数传入new RegExp,而[是正则的特殊字符(字符类起始标记),未转义会导致正则语法错误,进而抛出异常终止执行。

修复方案

由于无法修改第二个脚本,可通过以下两种方式在第一个脚本中规避自定义replaceAll:

方式1:使用String.replace配合全局正则

将原replaceAll调用替换为正则全局替换,手动转义特殊字符:

class CustomProduct extends HTMLElement {

  evaluate(expression) {

    let cleanExpression = expression;
    cleanExpression = cleanExpression.replace(/\[/g, ""); // 转义[后用全局正则替换
    return math.evaluate(cleanExpression)
  }

}

这里\[是转义后的左方括号,g标记实现全局替换,效果与原生replaceAll一致,且不会触发自定义方法。

方式2:强制调用原生String.replaceAll

通过call方法直接调用原生的replaceAll,绕过原型上的自定义实现(要求环境支持ES2021+):

class CustomProduct extends HTMLElement {

  evaluate(expression) {

    let cleanExpression = expression;
    // 直接调用原生replaceAll方法,指定上下文为cleanExpression
    cleanExpression = String.prototype.replaceAll.call(cleanExpression, "[", "");
    return math.evaluate(cleanExpression)
  }

}

内容的提问来源于stack exchange,提问作者Guy Online

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 06:40:43