为什么函数在全局声明变量而不是 var 时起作用
Why function works when declaring variable globally but not with var
我想将 属性 soundFileName
声明为 var soundFileName = 'audio/60.wav';
以便 soundFileName
不是全局定义的,但是当我这样做时我得到 ReferenceError: soundFileName is not defined
.
我将 soundFileName
的值作为参数传递给 loop(soundFileName)
,我认为 'audio/60.wav'
的值应该可以很好地传递。
我怀疑这与范围或嵌套有关,但我不确定如何解决该问题。当我使用不带 var 的 soundFileName = 'audio/60.wav';
时,代码确实有效。
我错过了什么?谢谢!
编辑:代码现在可以工作并已更新!
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script src="js/howler.core.js"></script>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<script src="timeprobabilities.js"></script>
<script>
///////////////////////////////////////////////////////////////
// MASTER START ///////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// initiates fist call to all clocks to each will start and can then be called again
(function masterStart() {
setTimeout(function() {
//// LOOP SOUNDS \\
A();
}, 0);
}());
///////////////////////////////////////////////////////////////
// LOOPS SHARED OPTIONS ///////////////////////////////////////
///////////////////////////////////////////////////////////////
var options = {
numberOfSounds: 0,
maxNumberOfSounds: 4
};
function logNumberOfSounds() { // passing options into this before is what broke code
options.numberOfSounds++;
//console.log('Number of sounds is: ' + options.numberOfSounds + '########');
}
///////////////////////////////////////////////////////////////
// LOOP A ////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
function A() {
var optionsA = {
playDurationMin: 0,
playDurationMax: 60000,
// start time minimum and maximum
startMinA: 0,
startMaxA: 8000,
maxVolumeA: 1,
//
startMinB: 0,
startMaxB: 30000,
maxVolumeB: 1,
//
startMinC: 0,
startMaxC: 30000,
maxVolumeC: 1,
//
startMinD: 0,
startMaxD: 30000,
maxVolumeD: 1,
//
startMinE: 0,
startMaxE: 30000,
maxVolumeE: 1,
//
startMinF: 0,
startMaxF: 30000,
maxVolumeF: 1,
//
startMinG: 0,
startMaxG: 30000,
maxVolumeG: 1,
//
startMinH: 0,
startMaxH: 30000,
maxVolumeH: 1,
//
startMinI: 0,
startMaxI: 30000,
maxVolumeI: 1,
//
startMinJ: 0,
startMaxJ: 30000,
maxVolumeJ: 1,
//
startMinK: 0,
startMaxK: 30000,
maxVolumeK: 1
};
masterClock();
function masterClock() {
setTimeout(function() {
soundA(options, optionsA);
}, 10); // these need to be called with delay so they don't use the other functions' paramaters
}
function soundA() {
var soundFileName = 'audio/60.wav';
fadeIn = 8000;
fadeOut = 8000;
console.log('soundFileName in A: ' + soundFileName);
calculateStartDelay(optionsA.startMinA, optionsA.startMaxA);
function calculateStartDelay(startMin, startMax) {
startDelay = Math.floor(Math.random() * startMax) + startMin;
}
function calculatePlayDuration(playDurationMin, playDurationMax) {
playDuration = Math.floor((Math.random() * playDurationMax) + playDurationMin);
}
function executePlayTools() {
calculatePlayDuration(optionsA.playDurationMin, optionsA.playDurationMax);
loop(options, playDuration, soundFileName, fadeIn, fadeOut);
console.log('A: ////////////////////////////////// ');
masterClock();
}
setTimeout(function() {
if (probabilityValue < probabilityPointA) {
maxVolume = optionsA.maxVolumeA;
executePlayTools();
} else if (probabilityValue < probabilityPointB) {
maxVolume = optionsA.maxVolumeB;
executePlayTools();
} else if (probabilityValue < probabilityPointC) {
maxVolume = optionsA.maxVolumeC;
executePlayTools();
} else if (probabilityValue < probabilityPointD) {
maxVolume = optionsA.maxVolumeD;
executePlayTools();
} else if (probabilityValue < probabilityPointE) {
maxVolume = optionsA.maxVolumeE;
executePlayTools();
} else if (probabilityValue < probabilityPointF) {
maxVolume = optionsA.maxVolumeF;
executePlayTools();
} else if (probabilityValue < probabilityPointG) {
maxVolume = optionsA.maxVolumeG;
executePlayTools();
} else if (probabilityValue < probabilityPointH) {
maxVolume = optionsA.maxVolumeH;
executePlayTools();
} else if (probabilityValue < probabilityPointI) {
maxVolume = optionsA.maxVolumeI;
executePlayTools();
} else if (probabilityValue < probabilityPointJ) {
maxVolume = optionsA.maxVolumeJ;
executePlayTools();
} else {
maxVolume = optionsA.maxVolumeK;
console.log('Probability Else');
}
console.log('startDelay: ' + startDelay)
}, startDelay);
}
}
///////////////////////////////////////////////////////////////
// SHARED LOOP ///////////////////////////////////////////////
///////////////////////////////////////////////////////////////
function loop(options, playDuration, soundFileName, fadeIn, fadeOut) {
console.log('soundFileName in loop: ' + soundFileName);
if (options.numberOfSounds < options.maxNumberOfSounds) { //Don't create more than the max number of sounds.
var sound = getSound(soundFileName);
var id2 = sound.play();
logNumberOfSounds();
sound.volume(0); // don't think I need this since it's declared above and in getSound(), but it stops blips?
sound.fade(0, maxVolume, fadeIn, id2); // FADE IN
setTimeout(function() {
sound.fade(maxVolume, 0, fadeOut, id2); // FADE OUT
options.numberOfSounds--;
// Attempt to clean up the sound object
setTimeout(function() {
sound.stop();
sound.unload();
}, fadeOut + 1000);
}, playDuration);
}
}
// PLAYER FOR MAIN SOUND FUNCTION /////////////////////////////
function getSound(soundFileName) {
return new Howl({
src: [soundFileName],
autoplay: true,
loop: true,
volume: 0,
fade: 0 // removes the blip
});
}
</script>
<script src="js/howler.core.js"></script>
<script src="js/siriwave.js"></script>
<script src="js/player.js"></script>
</body>
</html>
或许可以尝试改变这个
function loop() {
至:
function loop(param1,param2.....){
你的情况:
function loop(soundFileName,playDuration, ...){
您没有正确使用变量的值。它的值在 soundA()
函数内部定义,然后传递给函数 loop()
,它无法知道哪个变量是哪个。
这个问题有两种解决方法。像这样设置预定义的参数名称 function loop(options, options, playDuration, soundFileName, fadeIn, fadeOut){...}
然后在函数体中使用这些名称,或者您可以使用 arguments
函数对象。 arguments
对象是一个类数组对象,由每个函数(不包括箭头函数)创建,包含其所有传递的参数,通过它您可以轻松地使用传递给它的变量。请参阅下面的示例:
loop(options, playDuration, soundFileName, fadeIn, fadeOut);
function loop() {
console.log('soundFileName in loop: ' + arguments[2]); //The arguments object will contain all five parameters passed to the function call.
}
尽管如此,一些人认为对函数使用未知数量的参数是一种不好的做法,因为与使用预定义参数相比,它可能会导致更多的错误和陷阱。尽管如此,arguments
对象仍供您使用,您可以按照自己的意愿构建应用程序。请记住,其他人可能会阅读代码并对其中的内容感到困惑。
此外,在解决此问题后,我遇到了另一个问题,即您在实际函数声明之前的单独脚本标记中使用函数,从而导致 undefined
错误。
另外,请将此答案标记为解决方案,以帮助路过的人。
编辑#1:从 ES6+ 开始,您可以指定默认参数值,以防您希望始终保持函数按预期运行,即使值未正确传递也是如此。
编辑#2:正如@nikolairiedel 在评论中提到的,函数 getSound()
超出了该变量的声明范围,因此无法获取其值。您可以为该函数设置一个参数 and/or 指定一个默认参数值以确保它始终如上文编辑#1 中所述那样工作。
每个函数都有自己的作用域,函数内声明的变量仅存在于该函数的作用域内。
在这种情况下,soundFileName
被声明为 soundA
中的 var
,因此它仅存在于 soundA
.
的范围内
您正在将 soundFileName
作为参数传递给 loop
,并从那里将其传递给 getSound
,但是您的 function definitions 用于 loop
并且 getSound
不包含任何命名参数。
您需要更改 loop
和 getSound
的 function definition 以包含预期参数:
function loop(options, playDuration, soundFileName, fadeIn, fadeOut) {
...
// soundFileName is now availabie in this scope
...
}
function getSound(soundFileName) {
...
// soundFileName is now availabie in this scope
...
}
请注意,在 JavaScript
中的每个函数中(不包括包含函数调用参数的 arrow functions) there is a special arguments
object,因此自从您将 soundFileName
作为第三个参数传递给 loop
传递的值也将在 loop
中作为 arguments[2]
可用,并且由于它作为第一个参数传递给 getSound
,它也将在 getSound
中作为 arguments[0]
.
我想将 属性 soundFileName
声明为 var soundFileName = 'audio/60.wav';
以便 soundFileName
不是全局定义的,但是当我这样做时我得到 ReferenceError: soundFileName is not defined
.
我将 soundFileName
的值作为参数传递给 loop(soundFileName)
,我认为 'audio/60.wav'
的值应该可以很好地传递。
我怀疑这与范围或嵌套有关,但我不确定如何解决该问题。当我使用不带 var 的 soundFileName = 'audio/60.wav';
时,代码确实有效。
我错过了什么?谢谢!
编辑:代码现在可以工作并已更新!
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script src="js/howler.core.js"></script>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<script src="timeprobabilities.js"></script>
<script>
///////////////////////////////////////////////////////////////
// MASTER START ///////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// initiates fist call to all clocks to each will start and can then be called again
(function masterStart() {
setTimeout(function() {
//// LOOP SOUNDS \\
A();
}, 0);
}());
///////////////////////////////////////////////////////////////
// LOOPS SHARED OPTIONS ///////////////////////////////////////
///////////////////////////////////////////////////////////////
var options = {
numberOfSounds: 0,
maxNumberOfSounds: 4
};
function logNumberOfSounds() { // passing options into this before is what broke code
options.numberOfSounds++;
//console.log('Number of sounds is: ' + options.numberOfSounds + '########');
}
///////////////////////////////////////////////////////////////
// LOOP A ////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
function A() {
var optionsA = {
playDurationMin: 0,
playDurationMax: 60000,
// start time minimum and maximum
startMinA: 0,
startMaxA: 8000,
maxVolumeA: 1,
//
startMinB: 0,
startMaxB: 30000,
maxVolumeB: 1,
//
startMinC: 0,
startMaxC: 30000,
maxVolumeC: 1,
//
startMinD: 0,
startMaxD: 30000,
maxVolumeD: 1,
//
startMinE: 0,
startMaxE: 30000,
maxVolumeE: 1,
//
startMinF: 0,
startMaxF: 30000,
maxVolumeF: 1,
//
startMinG: 0,
startMaxG: 30000,
maxVolumeG: 1,
//
startMinH: 0,
startMaxH: 30000,
maxVolumeH: 1,
//
startMinI: 0,
startMaxI: 30000,
maxVolumeI: 1,
//
startMinJ: 0,
startMaxJ: 30000,
maxVolumeJ: 1,
//
startMinK: 0,
startMaxK: 30000,
maxVolumeK: 1
};
masterClock();
function masterClock() {
setTimeout(function() {
soundA(options, optionsA);
}, 10); // these need to be called with delay so they don't use the other functions' paramaters
}
function soundA() {
var soundFileName = 'audio/60.wav';
fadeIn = 8000;
fadeOut = 8000;
console.log('soundFileName in A: ' + soundFileName);
calculateStartDelay(optionsA.startMinA, optionsA.startMaxA);
function calculateStartDelay(startMin, startMax) {
startDelay = Math.floor(Math.random() * startMax) + startMin;
}
function calculatePlayDuration(playDurationMin, playDurationMax) {
playDuration = Math.floor((Math.random() * playDurationMax) + playDurationMin);
}
function executePlayTools() {
calculatePlayDuration(optionsA.playDurationMin, optionsA.playDurationMax);
loop(options, playDuration, soundFileName, fadeIn, fadeOut);
console.log('A: ////////////////////////////////// ');
masterClock();
}
setTimeout(function() {
if (probabilityValue < probabilityPointA) {
maxVolume = optionsA.maxVolumeA;
executePlayTools();
} else if (probabilityValue < probabilityPointB) {
maxVolume = optionsA.maxVolumeB;
executePlayTools();
} else if (probabilityValue < probabilityPointC) {
maxVolume = optionsA.maxVolumeC;
executePlayTools();
} else if (probabilityValue < probabilityPointD) {
maxVolume = optionsA.maxVolumeD;
executePlayTools();
} else if (probabilityValue < probabilityPointE) {
maxVolume = optionsA.maxVolumeE;
executePlayTools();
} else if (probabilityValue < probabilityPointF) {
maxVolume = optionsA.maxVolumeF;
executePlayTools();
} else if (probabilityValue < probabilityPointG) {
maxVolume = optionsA.maxVolumeG;
executePlayTools();
} else if (probabilityValue < probabilityPointH) {
maxVolume = optionsA.maxVolumeH;
executePlayTools();
} else if (probabilityValue < probabilityPointI) {
maxVolume = optionsA.maxVolumeI;
executePlayTools();
} else if (probabilityValue < probabilityPointJ) {
maxVolume = optionsA.maxVolumeJ;
executePlayTools();
} else {
maxVolume = optionsA.maxVolumeK;
console.log('Probability Else');
}
console.log('startDelay: ' + startDelay)
}, startDelay);
}
}
///////////////////////////////////////////////////////////////
// SHARED LOOP ///////////////////////////////////////////////
///////////////////////////////////////////////////////////////
function loop(options, playDuration, soundFileName, fadeIn, fadeOut) {
console.log('soundFileName in loop: ' + soundFileName);
if (options.numberOfSounds < options.maxNumberOfSounds) { //Don't create more than the max number of sounds.
var sound = getSound(soundFileName);
var id2 = sound.play();
logNumberOfSounds();
sound.volume(0); // don't think I need this since it's declared above and in getSound(), but it stops blips?
sound.fade(0, maxVolume, fadeIn, id2); // FADE IN
setTimeout(function() {
sound.fade(maxVolume, 0, fadeOut, id2); // FADE OUT
options.numberOfSounds--;
// Attempt to clean up the sound object
setTimeout(function() {
sound.stop();
sound.unload();
}, fadeOut + 1000);
}, playDuration);
}
}
// PLAYER FOR MAIN SOUND FUNCTION /////////////////////////////
function getSound(soundFileName) {
return new Howl({
src: [soundFileName],
autoplay: true,
loop: true,
volume: 0,
fade: 0 // removes the blip
});
}
</script>
<script src="js/howler.core.js"></script>
<script src="js/siriwave.js"></script>
<script src="js/player.js"></script>
</body>
</html>
或许可以尝试改变这个
function loop() {
至:
function loop(param1,param2.....){
你的情况:
function loop(soundFileName,playDuration, ...){
您没有正确使用变量的值。它的值在 soundA()
函数内部定义,然后传递给函数 loop()
,它无法知道哪个变量是哪个。
这个问题有两种解决方法。像这样设置预定义的参数名称 function loop(options, options, playDuration, soundFileName, fadeIn, fadeOut){...}
然后在函数体中使用这些名称,或者您可以使用 arguments
函数对象。 arguments
对象是一个类数组对象,由每个函数(不包括箭头函数)创建,包含其所有传递的参数,通过它您可以轻松地使用传递给它的变量。请参阅下面的示例:
loop(options, playDuration, soundFileName, fadeIn, fadeOut);
function loop() {
console.log('soundFileName in loop: ' + arguments[2]); //The arguments object will contain all five parameters passed to the function call.
}
尽管如此,一些人认为对函数使用未知数量的参数是一种不好的做法,因为与使用预定义参数相比,它可能会导致更多的错误和陷阱。尽管如此,arguments
对象仍供您使用,您可以按照自己的意愿构建应用程序。请记住,其他人可能会阅读代码并对其中的内容感到困惑。
此外,在解决此问题后,我遇到了另一个问题,即您在实际函数声明之前的单独脚本标记中使用函数,从而导致 undefined
错误。
另外,请将此答案标记为解决方案,以帮助路过的人。
编辑#1:从 ES6+ 开始,您可以指定默认参数值,以防您希望始终保持函数按预期运行,即使值未正确传递也是如此。
编辑#2:正如@nikolairiedel 在评论中提到的,函数 getSound()
超出了该变量的声明范围,因此无法获取其值。您可以为该函数设置一个参数 and/or 指定一个默认参数值以确保它始终如上文编辑#1 中所述那样工作。
每个函数都有自己的作用域,函数内声明的变量仅存在于该函数的作用域内。
在这种情况下,soundFileName
被声明为 soundA
中的 var
,因此它仅存在于 soundA
.
您正在将 soundFileName
作为参数传递给 loop
,并从那里将其传递给 getSound
,但是您的 function definitions 用于 loop
并且 getSound
不包含任何命名参数。
您需要更改 loop
和 getSound
的 function definition 以包含预期参数:
function loop(options, playDuration, soundFileName, fadeIn, fadeOut) {
...
// soundFileName is now availabie in this scope
...
}
function getSound(soundFileName) {
...
// soundFileName is now availabie in this scope
...
}
请注意,在 JavaScript
中的每个函数中(不包括包含函数调用参数的 arrow functions) there is a special arguments
object,因此自从您将 soundFileName
作为第三个参数传递给 loop
传递的值也将在 loop
中作为 arguments[2]
可用,并且由于它作为第一个参数传递给 getSound
,它也将在 getSound
中作为 arguments[0]
.