【问题标题】:Event listener throwing "Undefined" error when variable is quite clearly defined当变量被明确定义时,事件监听器抛出“未定义”错误
【发布时间】:2015-11-20 14:07:39
【问题描述】:

基本上我正在为 html5 视频元素创建一个自定义视频控制栏。一切正常,除了我使用范围输入元素的搜索栏。

现在,对于控制栏中的每个元素,我将其分配给 js 函数中的一个变量,该变量在窗口加载和添加事件侦听器时被调用。像这样:

function handleWindowLoad() {
    var video = document.getElementById ("video");
    var playPause = document.getElementById ("playPause");
    var muteUnmute = document.getElementById ("muteUnmute");    
    var fullScreen = document.getElementById ("toggleFullscreen");
    var scrubSlider = document.getElementById ("seekBar");
    playPause.addEventListener ("click", togglePlay);
    muteUnmute.addEventListener("click", toggleMute);
    fullScreen.addEventListener("click", toggleFullscreen);
    scrubSlider.addEventListener("change", scrubVideo);
}

所有事件处理程序都可以顺利工作。

例如:

function togglePlay() {
if (video.paused) {
    video.play();
    playPause.innerHTML = "Pause";
}
else {
    video.pause();
    playPause.innerHTML = "Play";
}
}

工作得很好。

但是,scrubSlider 事件处理程序,scrubVideo()

function scrubVideo() {
var scrubTime = video.duration * (scrubSlider.value/100);
video.currentTime = scrubTime;  
}

抛出“scrubSlider undefined”错误。

事件监听器工作正常,因为 scrubVideo() 在预期时被调用,但在 handleWindowLoad() 函数之外我无法访问 scrubSlider。我尝试过解决此错误的唯一方法是使用 document.getElementById 而不是 var 或全局声明 scrubSlider

我觉得这很有趣,因为 scrubSlider 和其余元素之间的唯一区别是,有问题的元素是 <input> 而不是 <button> 并且正在侦听的事件是“更改”而不是“点击”。

这个错误是由 HTML 元素的某种固有功能造成的,还是由于我忽略的更微不足道的原因?

Here's a JSFiddle

【问题讨论】:

  • 不针对 OP:我讨厌人们仅仅因为提问的人是一个犯了简单错误的新手而对问题投反对票。如果有人搜索“JavaScript 作用域是如何工作的”,他也很可能会发现这一点,但他不会仅仅从它显示的错误中知道这一点。
  • @JonathanG 问题标题不应包含标签。请不要重新编辑标签。

标签: javascript html scope addeventlistener


【解决方案1】:

如果我没看错,您可以在 handleWindowLoad 函数中定义 scrubSlider(这使其仅在该范围内可用),然后您尝试在 scrubVideo 中访问它。要使其正常工作,请执行以下操作:

var scrubSlider;
function handleWindowLoad() {
    scrubSlider = document.getElementById ("seekBar");
    ...
}

编辑: 我不知道的有趣的事情:如果您订阅DOMContentLoaded 事件,显然您可以通过他们的id 在javascript 中访问html 元素。 https://jsfiddle.net/22oqpcLu/1/

因此,这就是您在访问video 变量时不会得到未定义的原因。我猜你可以使用seekBar 访问scrubSlider

【讨论】:

  • 正如我所说,当我在全球范围内声明scrubSlider 时,它确实有效。但为什么我必须这样做?我可以访问handleWindowLoad() 之外的所有其他变量。
  • 也许在代码的某些部分你也全局声明了这些变量,但从我看到的代码中,我很确定你不能在 handleWindowLoad 之外访问它们。
  • @Chris 想象一下这是一个没有“范围”特征的世界。在一个简短的一次性计算函数中,您可以编写var x = calculateVelocity();。然后,在后面的函数中,您声明了另一个名为 x 的变量,然后因为它出现在循环中,您碰巧在使用它之前检查了它的值。它仍然是速度。变量作用域有助于防止变量值出现在与它们所使用的函数无关的地方。
  • @Katana314 好的,让我反过来说,scrubSlider 在 handleWindowLoad() 中声明,并且正如预期的那样,在全局级别上无法访问。但是,video、playPause、muteUnmute 和 fullScreen 都在 handleWindowLoad() 中声明并且可以从外部访问。为什么是这样?我假设这与从事件处理程序访问它们有关,在这种情况下,scrubSlider 也应该可以访问。
  • @laszlokiss88 这将解释它!非常感谢!
猜你喜欢
  • 1970-01-01
  • 2022-01-11
  • 1970-01-01
  • 2017-02-18
  • 1970-01-01
  • 1970-01-01
  • 2021-09-13
相关资源
最近更新 更多