为何setTimeout(audio.play,500)不生效?两种写法及报错解析
问题解答:setTimeout调用audio.play失效的原因及错误解析
先拆解你看到的错误提示
那个报错 TypeError: 'play' called on an object that does not implement interface HTMLMediaElement. 直白点说就是:你在一个不是HTML媒体元素(比如<audio>/<video>)的对象上调用了play方法。而play是HTML5媒体元素专属的方法,只有在这些元素实例上调用才会生效。
为什么两种写法结果天差地别?
核心问题出在函数的this上下文绑定上,我给你掰碎了说:
第一种写法踩的坑:
setTimeout(document.getElementsByTagName('audio')[0].play,1000.5)你这里把
audio元素的play方法单独拎出来作为参数传给了setTimeout。当setTimeout在1秒后执行这个函数时,这个函数的this已经和原来的audio元素脱钩了——在浏览器里,它会默认指向全局对象window。而window显然不是HTMLMediaElement类型,浏览器自然就抛出了那个错误。第二种写法能跑通的原因:
setTimeout(function(){document.getElementsByTagName('audio')[0].play()}, 1000.5)这里你传递的是一个匿名函数,当这个函数被执行时,我们是通过
audio元素.play()的形式调用方法的。这种情况下,play方法的this会自动绑定到点号前面的audio元素上(也就是正确的媒体元素实例),所以play能正常触发音频播放。
额外补充:另一种更简洁的可行写法
如果你不想用匿名函数,也可以用bind方法手动把play的this绑定到audio元素上:
const audio = document.getElementsByTagName('audio')[0]; setTimeout(audio.play.bind(audio), 1000.5);
bind会返回一个新函数,这个新函数的this会被固定成你传入的audio元素,这样setTimeout执行它的时候就不会出问题了。
内容的提问来源于stack exchange,提问作者illiterate
相关产品推荐
相关产品推荐

