JavaScript
前端JS规范

前段 JS 规范

前端不参与金额计算

  • 前端由于 JS 天生的计算精度问题会导致计算结果不复合预期。因此,所有数值计算类全部交由服务端开发统一计算,前端只做透传,不做任何计算

  • 金额前端保存,必须使用 string 类型,前端请求服务端传参,涉及到金额字段必须使用 string 传递(禁止使用 number 类型)以此避免 number 类型的值 可能会在表示数值区间外数据溢出 还有 当数值过大默认转为科学计算法显示 的问题。

不使用双等号进行判断

JavaScript 中使用两等号会因为 隐式类型转换 (opens in a new tab) 而导致结果和预期不符,进而导致程序 bug,例如:

"10" == 10; // true
null == undefined; // true
"" == 0; // true
true == 1; // true
false == 0; // true
  • 判断是否相等请使用 ===,请勿使用 ==
  • 判断是否不相等请使用 !==,请勿使用 !=

危险的内置函数需要 catch

一些内置函数对不当的参数会抛错,导致功能不可用,严重甚至白屏:

  • JSON.parse 当接收一个不能被反序列化的字符串时会抛错
JSON.parse("{sum: 123},");
// Uncaught SyntaxError: Expected property name or '}' in JSON at position 1
// ✅ good case
// 将 JSON.parse 封装成通用的 jsonParseSafely
export function jsonParseSafely<T>(str: string, defaultValue: any = {}): T {
  try {
    return JSON.parse(str);
  } catch (error) {
    console.warn("JSON.parse", str, "failed", error);
 
    return defaultValue;
  }
}
 
// 在业务代码中使用 jsonParseSafely 而非 JSON.parse
const jsonData = jsonParseSafely(data.jsonData || "[]");
  • decodeURIComponent 如果 encodedURI 包含一个 % 后面不跟随两个十六进制数字,或者转义序列没有编码有效的 UTF-8 字符,则会抛出 URIError (opens in a new tab) 异常
decodeURIComponent("%="); // Uncaught URIError: URI malformed
// JSON.stringify 处理循环引用
var obj1 = {};
var obj2 = {};
 
obj1.prop = obj2;
obj2.prop = obj1;
JSON.stringify(obj1); // Uncaught TypeError: Converting circular structure to JSON
 
// JSON.stringify 处理 BigInt
var obj = {
  num: BigInt(123456),
};
JSON.stringify(obj); // Uncaught TypeError: Do not know how to serialize a BigInt

避免直接访问嵌套属性

访问层级过深的属性容易引起空指针,导致页面白屏等严重错误。

  • 优先推荐 TS 可选级联语法,即 Optional Chaining (opens in a new tab):props?.maybeObj?.a,但是请勿滥用,滥用的坏处在于
    • 在本来该进行错误处理的地方,用这种方式绕过
    • 本来应该能监控发现问题的地方,被这种方式掩盖掉
    • 让 undefined 继续传递下去,引发更深层次的问题
  • 若变量缺少类型定义则使用 lodash.get (opens in a new tab)

业务场景下禁止使用客户端时间

  • 客户端时间可被用户随意更改,任何与日期时间相关的业务逻辑都必须采用服务端下发的时间

禁止使用 JS 保留字 和 浏览器全局变量 作为变量和模块名

  • 使用 JS 保留字 和 浏览器全局变量 作为变量和模块名可能导致不可预知的问题

避免在 this 上随意添加属性

  • 在 this 上随意挂载属性可能会覆盖内置属性导致不可预期的运行时错误,如果必须加则应当使用 $_ 前缀