通过Ajax XMLHttpRequest发送FormData时如何避免TypeError报错
问题根因
核心问题是函数名和内部赋值的全局变量重名,导致函数被覆盖:
- 你声明了全局函数
insertUser,但在函数内部执行insertUser = document.getElementById("insert_user")时,该变量没有加let/const声明,默认挂载到全局作用域 - 第一次调用
insertUser函数后,全局下的insertUser就从函数被覆盖成了id为insert_user的表单DOM对象,第二次点击按钮调用insertUser()时,自然会抛出「不是函数」的类型错误
额外注意:你代码里所有的xhttp、formData变量都没有声明,全部是隐式全局变量,也容易引发其他变量污染问题。
修正方案
只需要把insertUser函数内部的变量改名,同时给所有变量加上声明即可,修改后的JS代码如下:
function loadUsers() { // 给xhttp加const声明,避免全局污染 const xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { document.getElementById("users_row").innerHTML = this.responseText; } }; xhttp.open("GET", "views/users_view.php", true); xhttp.send(); } function insertUser() { const xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { document.getElementById("saved_user").innerHTML = "<b class='text-primary'>用户已添加<b>"; loadUsers(); setTimeout(function() { document.getElementById("saved_user").innerHTML = ""; }, 3000); } }; xhttp.open("POST", "controller/insert_user.php", true); // 变量名改成和函数名不冲突的名字,加const声明 const userForm = document.getElementById("insert_user"); const formData = new FormData(userForm); xhttp.send(formData); }
可选优化建议
如果要进一步规避这类作用域问题,可以放弃内联onclick绑定,改用JS事件绑定:
- 删除HTML按钮上的
onclick="insertUser()"属性 - 在JS代码末尾新增如下绑定逻辑:
document.querySelector('#insert_user button[type="button"]').addEventListener('click', insertUser);
内容的提问来源于stack exchange,提问作者Fez
相关产品推荐
相关产品推荐

