为什么在setTimeout中使用音频时会出现ReferenceError?

时间:2017-11-02 00:06:18

标签: javascript audio settimeout

我想安排音频播放。为什么这段代码会为?

返回一个ReferenceError
function playSound()
{
  var a = new Audio("mp3/win.mp3");
  setTimeout("a.play('mp3/win.mp3');", 1000);
}
playSound();

3 个答案:

答案 0 :(得分:2)

a变量定义移动到全局上下文:

var a = new Audio("mp3/win.mp3");
function playSound()
{
  setTimeout("a.play('mp3/win.mp3');",1000);
}
playSound();

或使用function表示法而不是code表示法

function playSound()
{
  var a = new Audio("mp3/win.mp3");
  setTimeout(function() {
    a.play('mp3/win.mp3');
  },1000);
}
playSound();

我认为问题的原因与setTimeout code符号的eval类似。让我们看看MDN在setTimeout (1)上说了什么:

  

将字符串而不是函数传递给setTimeout()会受到影响   与使用eval相同的危险。

然后在eval (2)

  

如果你间接使用eval函数,可以通过a调用它   除了eval之外的参考,从ECMAScript 5开始,它在全球范围内起作用   范围而不是本地范围。这意味着,例如,那   函数声明创建全局函数,代码是   评估无法访问范围内的局部变量   在哪里被召唤。

setTimeout("a.play('mp3/win.mp3')", 1000)就像是间接的eval电话。

答案 1 :(得分:0)

当你在setTimeout上使用字符串表示法时,它并没有像你想象的那样被视为一个函数(因为第一个参数通常是一个函数)。相反,它被视为一个脚本,只要经过了毫秒数就会运行。

所以它好像在添加:

<script>a.play('mp3/win.mp3');</script>

每1000毫秒。

由于a不是全局的(它是执行setTimeout的函数的一部分),因此它无法看到它,因此引用了ReferenceError。

答案 2 :(得分:0)

不要使用字符串作为setTimeout的参数,它在全局范围内执行,因此它无法访问局部变量。使用函数参数。

function playSound()
{
    var a = new Audio("mp3/win.mp3");
    setTimeout(() => a.play('mp3/win.mp3'),1000);
}
playSound();