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

为什么JS内置函数无初始化前访问报错,自定义函数却会,如何解决?

报错根因

这个报错是JavaScript**暂时性死区(Temporal Dead Zone, TDZ)**的特性导致的,具体原因如下:

  • 使用const声明的箭头函数本质是变量赋值,和所有let/const声明的变量一样,存在暂时性死区约束:在代码执行到该变量的声明语句之前,任何访问该变量的操作都会抛出Cannot access 'xxx' before initialization错误。
  • 你的代码中先定义enteredIngredientIsValid时就直接调用了hasAllowedChars,但hasAllowedChars的声明语句在后面,赋值执行时hasAllowedChars还处于暂时性死区,因此触发报错。
  • JS内置函数在全局执行上下文初始化阶段就已经完成创建挂载,不存在死区限制,所以调用时不会触发同类报错。
  • 你把校验逻辑直接写在判断里时,不需要引用后方声明的变量,自然不会触发死区错误。
可行解决方案

以下三个方案都可以解决问题,你可以根据代码习惯选择:

  1. 调整变量声明顺序,把hasAllowedChars的声明放到enteredIngredientIsValid之前
//Ingredients
// 先完成自定义函数的初始化
const hasAllowedChars = (string) => {
  const allowedChars = /^[a-zA-Z]*$/;
  return allowedChars.test(String(string));
};

const [enteredIngredient, setIngredientName] = useState("");
const [enteredIngredientTouched, setIngredientTouched] = useState(false);          

// 再定义校验变量,此时hasAllowedChars已完成初始化
const enteredIngredientIsValid =
  enteredIngredient.trim() !== "" && hasAllowedChars(enteredIngredient);
  1. 把hasAllowedChars改为普通函数声明,普通函数声明存在全作用域提升,不受声明顺序影响
//Ingredients
const [enteredIngredient, setIngredientName] = useState("");
const [enteredIngredientTouched, setIngredientTouched] = useState(false);          

// 普通函数声明存在提升,此处调用不会报错
const enteredIngredientIsValid =
  enteredIngredient.trim() !== "" && hasAllowedChars(enteredIngredient);

// 使用普通函数声明语法,而非箭头函数赋值
function hasAllowedChars(string) {
  const allowedChars = /^[a-zA-Z]*$/;
  return allowedChars.test(String(string));
}
  1. 将enteredIngredientIsValid改为函数形式,只有实际触发校验时才会执行内部逻辑,只要调用时hasAllowedChars已经初始化就不会报错
//Ingredients
const [enteredIngredient, setIngredientName] = useState("");
const [enteredIngredientTouched, setIngredientTouched] = useState(false);          

// 改为函数形式,赋值时不会执行内部的hasAllowedChars调用
const enteredIngredientIsValid = () => enteredIngredient.trim() !== "" && hasAllowedChars(enteredIngredient);

const hasAllowedChars = (string) => {
  const allowedChars = /^[a-zA-Z]*$/;
  return allowedChars.test(String(string));
};

// 点击按钮触发校验时,调用该函数即可:enteredIngredientIsValid()

内容的提问来源于stack exchange,提问作者Lajos Bela

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 16:42:02