首页 > 解决方案 > HTML 事件给出 'Uncaught TypeError: X is not a function'

问题描述

我有一个问题。这是非常简化的代码:

<!DOCTYPE html>
<html>
<head>
    <script>
        function ended(e) {
            alert("Ended");
        }
        
        function paused(e) {
            alert("Paused");
        }

        function played(e) {
            alert("Played");
        }       
    </script>
</head>
<body>
    <div>
        <video src="videoFile.mp4" controls onended="ended(event)" onpause="paused()" onplay="played(event)" >
        </video>
    </div>
</body>
</html>

每当我暂停、播放或结束视频时,我都会收到错误消息:

Uncaught TypeError: played is not a function
    at HTMLVideoElement.onplay

或相同但用pausedorended代替played, onpauseandonended代替onplay.

我已经解决了,所以我把答案放在下面,给那些遇到类似问题的人。

标签: javascripthtmlfunctioneventstypeerror

解决方案


这是使用onxyz-attribute-style 事件处理程序的众多原因之一。它们不仅只能调用全局函数(这不是最佳实践),而且它们在复杂的范围环境中运行,其中不仅包括当前元素的属性(您遇到的问题),而且在某些情况下还包括来自其他元素的属性(例如formaninput位于)。(更多下文。)

相反,使用现代事件处理(尽可能使用模块[所有现代浏览器都支持它们])。

例如:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <div>
        <video src="videoFile.mp4" controls></video>
    </div>
    <script type="module">
        function ended(e) {
            console.log("Ended");
        }
        
        function paused(e) {
            console.log("Paused");
        }

        function played(e) {
            console.log("Played");
        }       

        const videoElement = document.querySelector(`video[src="videoFile.mp4"]`);
        videoElement.addEventListener("ended", ended);
        videoElement.addEventListener("pause", paused);
        videoElement.addEventListener("play", played);
    </script>
</body>
</html>

关于“复杂的作用域环境”:onxyz-attribute-style 事件处理程序中的代码在这样有效地创建的作用域中运行(对于您的示例):

with (document) {
    with (theTargetVideoElement) {
        // ...your code here...
    }
}

(没错,可怕的(和过时的)with声明。)

对于 a 中的元素form,情况更糟:

with (document) {
    with (theForm) {
        with (theTargetElementInTheForm) {
            // ...your code here...
        }
    }
}

这是一个例子:

<form method="POST">
    <input type="button" onclick="
        console.log(documentElement.tagName); // 'HTML'
        console.log(method); // 'post'
        console.log(type); // 'button'
    " value="Click Me">
</form>

  • documentElement来自document
  • method来自form元素
  • type来自input元素

拒绝吧。


推荐阅读