非法调用jQuery HTML5音频播放

时间:2013-12-13 16:47:38

标签: javascript jquery html5 html5-audio

背景

基本上,这段代码会获取页面上的所有音频标签,当一个完成后,它会启动DOM中的下一个。

问题

调用fnPlay时,我收到Illegal Invocation错误。

//THIS CODE FAILS
var lastAudio = null;
$('audio').each(function(index) {
    var fnPlay = $(this)[0].play;
    if (lastAudio != null) {
        lastAudio.bind("ended", function() {
            fnPlay(); 
        });
    }
    lastAudio = $(this);
});

现在我肯定其余代码没问题,因为以下方法有效。

//WORKS GREAT!
var lastAudio = null;
$('audio').each(function(index) {
    var lastAudioObj = $(this)[0];
    if (lastAudio != null) {
        lastAudio.bind("ended", function() {
            lastAudioObj.play(); 
        });
    }
    lastAudio = $(this);
});

问题

任何人都可以解释为什么我无法将play()函数存储在我的变量fnPlay中并调用fnPlay(),但我可以存储该对象并调用play()函数对象?

1 个答案:

答案 0 :(得分:2)

这是因为JavaScript函数的上下文如何工作。函数内部的上下文(或this)在运行时设置,而不是在设置时设置。

当您致电lastAudioObj.play();时,play()功能会在lastAudioObj的上下文中调用。在play()内,thislastAudioObj,所以一切正常。

但是,当你执行fnPlay()时,它没有上下文。函数内的this将为null(或window)。 play()不喜欢这样,所以它会引发异常。

有几种方法可以解决这个问题。

一种是用.call()调用函数来手动设置上下文。

设置变量如:

var lastAudioObj = $(this)[0];
var fnPlay = lastAudioObj.play;

然后致电:

fnPlay.call(lastAudioObj);

您还可以使用.bind()在设置变量时设置上下文。

var lastAudioObj = $(this)[0];
var fnPlay = lastAudioObj.play.bind(lastAudioObj);

然后你可以这样称呼它:

fnPlay();