[英]HTML event gives 'Uncaught TypeError: X is not a function'
I had a problem.我有问题。 Here's the very simplified code:这是非常简化的代码:
<!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>
Any time I paused, played, or ended the video, I would get the error:每当我暂停、播放或结束视频时,都会收到错误消息:
Uncaught TypeError: played is not a function
at HTMLVideoElement.onplay
or the same but with paused
or ended
instead of played
, and onpause
and onended
instead of onplay
.或相同但paused
或ended
而不是played
,以及onpause
和onended
而不是onplay
。
I've already solved it, so I put the answer below, for those who encounter a similar problem.我已经解决了,所以我把答案放在下面,给遇到类似问题的人。
It turns out that the HTMLMediaElement
, which the <video>
element is, contains some boolean properties: ended
, paused
and played
.事实证明, <video>
元素所在的HTMLMediaElement
包含一些布尔属性: ended
、 paused
和played
。
And it turns out that when the browser (Chrome, maybe others) calls the event, it gets the value of those properties (which is true
or false
), instead of using my already defined functions.事实证明,当浏览器(Chrome,也可能是其他人)调用该事件时,它会获取这些属性的值( true
或false
),而不是使用我已经定义的函数。 So then it tries to call true(event)
or false(event)
, and since true
and false
are not functions, it gives the error that played is not a function
.然后它尝试调用true(event)
或false(event)
,并且由于true
和false
不是函数,因此它给出了played is not a function
的错误played is not a function
。
So the answer is, make sure that the function names you use for events do not match properties within the relevant HTMLElement that is firing the event, and then you shouldn't have any problems.所以答案是,确保您用于事件的函数名称与触发事件的相关 HTMLElement 中的属性不匹配,然后您就不会有任何问题。 (I haven't checked, but it seems likely this would occur with other HTMLElements) (我没有检查过,但其他 HTMLElements 似乎可能会发生这种情况)
In my case I changed them to doMyEnded
, doMyPaused
and doMyPlayed
and all was well.就我而言,我将它们更改为doMyEnded
、 doMyPaused
和doMyPlayed
,一切都很好。
NOTE: I strongly recommend anyone who wants to know more about this read the answer by TJ Crowder注意:我强烈建议任何想了解更多信息的人阅读 TJ Crowder 的答案
This is one of the many reasons not to use onxyz
-attribute-style event handlers.这是不使用onxyz
样式事件处理程序的众多原因之一。 Not only can they only call global functions (which aren't best practice), but they run in a complicated scoping environment which includes not only the current element's properties (the problem you had) but in some cases properties from other elements as well (such as the form
an input
is located in).它们不仅可以调用全局函数(这不是最佳实践),而且还可以在复杂的范围环境中运行,该环境不仅包括当前元素的属性(您遇到的问题),而且在某些情况下还包括其他元素的属性(例如input
所在的form
)。 (More below.) (更多见下文。)
Instead, use modern event handling (and modules when possible [all modern browsers support them]).相反,使用现代事件处理(和模块(如果可能)[所有现代浏览器都支持它们])。
For example:例如:
<!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>
About the "complicated scoping environment": The code in an onxyz
-attribute-style event handler runs in a scope that is effectively created like this (for your example):关于“复杂的范围环境”: onxyz
-attribute-style 事件处理程序中的代码在有效创建的范围内运行(对于您的示例):
with (document) {
with (theTargetVideoElement) {
// ...your code here...
}
}
(That's right, the dreaded (and deprecated) with
statement .) (没错,可怕的(和弃用的) with
statement 。)
For an element in a form
, it's even worse:对于form
的元素,情况更糟:
with (document) {
with (theForm) {
with (theTargetElementInTheForm) {
// ...your code here...
}
}
}
Here's an example of that:这是一个例子:
<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
comes from document
documentElement
来自document
method
comes from the form
element method
来自form
元素type
comes from the input
element type
来自input
元素Just Say No. 😃只说不😃
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.