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

JavaScript箭头函数配合FormData与fetch的this上下文问题解决

问题:箭头函数下FormData与fetch()的正确使用方式

我有一段JavaScript fetch()代码,可向MySQL数据库发送数据并阻止页面硬刷新,后端用PHP编写,原本运行正常。但将submit事件处理函数改为ES6箭头函数后,FormData()对象出现问题:

  • 把第3行的submit事件处理函数改为箭头函数i.addEventListener('submit', (e) => { ...时,抛出错误Uncaught TypeError: Failed to construct 'FormData': parameter 1 is not of type 'HTMLFormElement',这明显和this上下文有关;
  • 若移除this作为FormData的参数,PHP端会报错Undefined index: create-board-name('create-board-name'是提交按钮的name属性)。

原JavaScript代码

if (form) {
    form.forEach(i => {
    i.addEventListener('submit', function(e) {
        if (e.submitter && e.submitter.classList.contains('js-fetch-button')) {
                e.preventDefault();

                var formData = new FormData(this);

                formData.set(e.submitter.name, e.submitter.value);
                formData.set('json_response', 'yes'); // 和下方PHP的JSON编码逻辑相关

                fetch(
                    theURL, {
                    method: 'post',
                    body: formData
                })
                .then((response) => {
                    if (response.status === 200) {
                        response.json().then((json) => {

                            // --- 后续逻辑

                        });
                    }
                }).catch((error) => {
                    console.error(error);
                })
            }
        })
    }) 
}

PHP代码(非问题根源)

虽然我认为PHP不是问题所在,还是附上代码:创建新看板时,它会更新数据库并以JSON格式返回信息,方便创建后直接使用新看板数据。

// 插入数据库
    $stmt = $connection->prepare(
        "INSERT INTO boards (board_name, user_id) 
        VALUES (:board_name, :user_id )"
    );
    $stmt->execute([
        ':board_name' => $create_board_name,
        ':user_id' => $sessionId
    ]);

    // 以JSON格式返回数据
    if(isset($_POST['json_response'])) {
        $board_stmt = $connection->prepare(
            "SELECT * FROM boards 
            WHERE user_id = :user_id AND board_name = :board_name 
            ORDER BY board_id DESC"
        );

        $board_stmt -> execute([
            ':user_id' => $sessionId,
            ':board_name' => $create_board_name
        ]); 

        $board_row = $board_stmt->fetch();

        header('Content-type: application/json');
        echo json_encode($board_row);
        exit;
    }

解决方案

核心原因

箭头函数没有自己的this上下文,它会继承外层作用域的this。这里外层是forEach的箭头函数,this指向全局对象(非严格模式)或undefined(严格模式),不再指向触发submit事件的表单元素,所以new FormData(this)会报错。

两种可行的修正方法

方法1:从事件对象中获取表单元素

submit事件的e.target或e.currentTarget就是触发事件的表单元素,直接用它们替代原来的this即可:

if (form) {
    form.forEach(i => {
    i.addEventListener('submit', (e) => { // 改为箭头函数
        if (e.submitter && e.submitter.classList.contains('js-fetch-button')) {
                e.preventDefault();

                // 用e.currentTarget或e.target获取表单元素
                var formData = new FormData(e.currentTarget);

                formData.set(e.submitter.name, e.submitter.value);
                formData.set('json_response', 'yes');

                fetch(
                    theURL, {
                    method: 'post',
                    body: formData
                })
                .then((response) => {
                    if (response.status === 200) {
                        response.json().then((json) => {
                            // --- 后续逻辑
                        });
                    }
                }).catch((error) => {
                    console.error(error);
                })
            }
        })
    }) 
}

方法2:直接使用forEach循环中的表单变量i

因为forEach里的i就是当前遍历到的表单元素,直接传入FormData即可,这种方式不受事件函数类型影响:

if (form) {
    form.forEach(i => {
    i.addEventListener('submit', (e) => { // 改为箭头函数
        if (e.submitter && e.submitter.classList.contains('js-fetch-button')) {
                e.preventDefault();

                // 直接用循环中的i变量,它就是当前表单元素
                var formData = new FormData(i);

                formData.set(e.submitter.name, e.submitter.value);
                formData.set('json_response', 'yes');

                fetch(
                    theURL, {
                    method: 'post',
                    body: formData
                })
                .then((response) => {
                    if (response.status === 200) {
                        response.json().then((json) => {
                            // --- 后续逻辑
                        });
                    }
                }).catch((error) => {
                    console.error(error);
                })
            }
        })
    }) 
}

这两种方法都能正确获取表单数据,PHP端也能正常拿到create-board-name等参数,同时保留箭头函数的写法。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 08:45:49