Javascript新手,经过几个小时挖掘其他问题,老实说,我不太确定如何解释这一点,但我会尽力而为,希望你能帮助我。
.HTML:
<div id='header'> <h1> Pastel Land </h1> </div>
<div id='container'>
<div id='readyContainer'>
<h3> This game will start in </h3>
<h1 id='readySeconds'> </h1>
</div>
<div id='shape'> </div>
</div>
<div id='features'>
<button id='start'> START </button>
<button id='stop'> STOP </button>
<p id='timeBox'></p>
<p id='timeAverageBox'></p>
</div>
<div id='testbox'> </div>
完整脚本:
document.getElementById('start').onclick = function () {
document.getElementById('readyContainer').style.display = 'block';
document.getElementById('readySeconds').innerHTML = '3'
setTimeout(function() {document.getElementById('readySeconds').innerHTML = '2'}, 1000);
setTimeout(function() {document.getElementById('readySeconds').innerHTML = '1'}, 2000);
setTimeout(readyAlert,3000);
setTimeout(displayShape, 3000);
var style = document.getElementById('shape').style;
var el = document.getElementById('shape');
el.addEventListener("click", a, false);
el.addEventListener("click", b, false);
function a() {
style.display = "none";
displayShapeDelay(); // calls the delay function
}
function b() {
end = new Date().getTime(); // saves time when clicked
var time = (end - start)/1000 ; // calculates interval from shape creation until click
document.getElementById('timeBox').innerHTML = time + 's';
return time;
}
document.getElementById('testbox').innerHTML = b();
function readyAlert() {
document.getElementById('readyContainer').style.display = 'none';
}
function getRandomColor() {
var hex = ["#96ceb4", "#ffeead", "#ff6f69", "#ffcc5c", "#88db8b0", "#528491"];
var color = hex[Math.floor(Math.random() * 6)]; // generates integer numbers [0,5], selects indexed item from hex
return color;
}
function displayShape () {
var percentages = [];
for (var i=0; i<4; i++){ // generates a list with 4 different random integer values [5,60]
percentages.push((Math.floor(Math.random() * 61) + 5));
}
var width = (Math.floor(Math.random() * 61) + 5); // generates integer numbers [5,60]
var shapeRand = Math.random()
if (shapeRand < 0.3) { // circle
style.borderRadius = "50%";
} else if (shapeRand >= 0.3 && shapeRand < 0.6) { // random shape
style.borderTopLeftRadius = percentages[0] + "%";
style.borderBottomRightRadius = percentages[1] + "%";
style.borderTopRightRadius = percentages[2] + "%";
style.borderBottomLeftRadius = percentages[3] + "%";
} else { // square
style.borderRadius = "0%";
}
//general shape styles
style.width = width + "%";
style.height = width + "%";
style.display = "block";
style.backgroundColor = getRandomColor();
style.top = percentages[0] + "%";
style.left = percentages[3] + "%";
start = new Date().getTime(); // saves time when shape is created
console.log(width);
console.log(getRandomColor());
console.log(shapeRand);
console.log(percentages);
}
function displayShapeDelay () { // calls the main function with a delay between ]0s,2s[
setTimeout(displayShape, Math.random() * 2000);
}
document.getElementById('stop').onclick = function() {
}
}
在我有这个之前:
我的目标是将 var 'time' 返回到全局范围,以便我可以使用它来创建每次单击时创建的每个值的数组。我已经意识到这不可能从匿名函数中实现。
document.getElementById('shape').onclick = function() { // calls the delay function
style.display = "none";
displayShapeDelay();
end = new Date().getTime();
time = (end - start)/1000 ;
document.getElementById('timeBox').innerHTML = time + 's';
return time
}
所以这是我现在的代码:
var shapeClick = document.getElementById('shape');
shapeClick.addEventListener("click", a, false);
shapeClick.addEventListener("click", b, false);
function a() {
style.display = "none";
displayShapeDelay(); // calls the delay function
}
function b() {
end = new Date().getTime(); // saves time when clicked
var time = (end - start)/1000 ; // calculates interval from shape creation until click
document.getElementById('timeBox').innerHTML = time + 's';
return time;
}
document.getElementById('testbox').innerHTML = b();
现在,这有几个问题:
1-我似乎无法理解为什么在按下"开始"按钮后为两个"时间div"分配值。这意味着函数 b 正在运行,但它不应该只在 onClick 事件之后运行吗?
2-在"第一轮"中,我理解为什么两个值都显示为 NaN,因为还没有为变量"时间"赋值。但是在 onClick 事件执行后,在 'timeBox' 中分配的 'time' 值工作正常,但在函数外部调用的值则不能。函数 b 中的"返回时间"不是应该返回"时间"变量的值吗?
提前感谢!
粉彩之地
onclick
函数充当大量代码的外部函数,这些代码在单击开始按钮时执行。此外,每次单击开始按钮时,它都会运行:单击多次快速启动以查看问题。 .
在 #start.onclick() 中,你有
document.getElementById('testbox').innerHTML = b();
在主线单击处理程序代码中:它不在另一个函数中,并在单击"开始"按钮时运行。由于尚未设置end
,因此time
的结果是 NaN
.function b
中的代码也设置 #timebox 的内容。
如果你在严格模式下运行代码,javascript 引擎会告诉你end
尚未声明。它应该是 - 即使在全球范围内需要。
顺便说一句,仅供参考,Date.now()
避免了创建和丢弃Date对象的需要,等效于new Date().getTime()
。
我建议重新设计代码以将 Pastel Land 的逻辑移动到开始按钮单击处理程序之外,并根据需要将单击处理程序调用到主应用程序代码中,但仅包含特定于启动操作本身的逻辑。如果要避免污染全局作用域,可以将所有代码包含在 IIFE(立即调用的函数表达式)中,该代码将提供与单击处理程序当前提供的相同作用域包含规定。善意地,我认为当前状态下的代码提出了一个 x-y 问题:-)
游戏
下面显示了 Pastel Land 的重组版本,原因如下:您有时间自己尝试,大部分代码都是您的,其余代码演示了建议的含义。这是一个非常愚蠢的游戏,值得玩!
<!DOCTYPE html>
<html>
<head>
<title>PastelLand</title>
<meta charset="utf-8">
<script>
window.addEventListener("load", function() // an IIFE
{"use strict"
// Pastel Land
var running = false;
var start = 0;
var end = 0;
var times = []; // calculating average still to do
var el, style;
function getRandomColor() {
var hex = ["#96ceb4", "#ffeead", "#ff6f69", "#ffcc5c", "#88db8b0", "#528491"];
var color = hex[Math.floor(Math.random() * 6)]; // generates integer numbers [0,5], selects indexed item from hex
return color;
}
function displayShape () {
var percentages = [];
for (var i=0; i<4; i++){ // generates a list with 4 different random integer values [5,60]
percentages.push((Math.floor(Math.random() * 61) + 5));
}
var width = (Math.floor(Math.random() * 61) + 5); // generates integer numbers [5,60]
var shapeRand = Math.random()
if (shapeRand < 0.3) { // circle
style.borderRadius = "50%";
} else if (shapeRand >= 0.3 && shapeRand < 0.6) { // random shape
style.borderTopLeftRadius = percentages[0] + "%";
style.borderBottomRightRadius = percentages[1] + "%";
style.borderTopRightRadius = percentages[2] + "%";
style.borderBottomLeftRadius = percentages[3] + "%";
} else { // square
style.borderRadius = "0%";
}
//general shape styles
style.width = width + "px";
style.height = width + "px";
style.position = "absolute"
style.display = "block";
style.backgroundColor = getRandomColor();
style.top = percentages[0] + "%";
style.left = percentages[3] + "%";
start = Date.now(); // saves time when shape is created
console.log(width);
console.log(getRandomColor());
console.log(shapeRand);
console.log(percentages);
}
function displayShapeDelay () { // calls the main function with a delay between ]0s,2s[
setTimeout(displayShape, Math.random() * 2000);
}
function readyAlert() {
document.getElementById('readyContainer').style.display = 'none';
}
function userFound() {
style.display = "none";
end = Date.now();
var time = (end - start)/1000 ; // calculates interval from shape creation until click
document.getElementById('timeBox').innerHTML = time + 's';
displayShapeDelay(); // calls the delay function
times.push( time); // saves time user took to find shape
}
function userStart() {
if( running)
return;
running = true;
document.getElementById('readyContainer').style.display = 'block';
document.getElementById('readySeconds').innerHTML = '3'
setTimeout(function() {document.getElementById('readySeconds').innerHTML = '2'}, 1000);
setTimeout(function() {document.getElementById('readySeconds').innerHTML = '1'}, 2000);
setTimeout(readyAlert,3000);
setTimeout(displayShape, 3000);
times.length = 0; // reset times array
}
function userStop() {
running = false;
style.display="none"
}
function init() {
el = document.getElementById('shape');
style = el.style;
el.addEventListener("click", userFound, false);
document.getElementById('start').onclick=userStart;
document.getElementById('stop').onclick=userStop;
}
return init; // window load listener
}());
</script>
</head>
<body>
<div id='header'> <h1> Pastel Land </h1> </div>
<div id='container'>
<div id='readyContainer'>
<h3> This game will start in </h3>
<h1 id='readySeconds'> </h1>
</div>
<div id='shape' style="height:40px;width:40px;"></div>
</div>
<div id='features'>
<button id='start'> START </button>
<button id='stop'> STOP </button>
<p id='timeBox'></p>
<p id='timeAverageBox'></p>
</div>
<div id='testbox'> </div>
</body>
</html>
平均值的计算和显示以及对页面呈现的微小更改仍有待完成(我不是在编码它们!宽度和高度的单位从"%"更改为"px"(像素),并将"位置:绝对;"添加到shape.style中。函数a
和b
组合成函数userFound
。 涉及"testbox"的代码被省略了。IIEF 返回要在窗口加载后执行的初始化函数。
笔记
userStart
和userStop
单击事件处理程序是使用命名函数声明定义的,而不是将它们编码为调用其他函数的参数列表中的匿名函数。
的函数名称是指由其声明创建的函数对象。因此,将元素的 onclick
属性的值设置为函数名称是有效的,因为该属性需要函数对象值。将onclick
设置为调用其中一个处理程序返回的未定义值将不起作用。
启动/停止处理程序可以注册为"单击"事件侦听器,使用 addEventListener
而不是元素onclick
值。
IIFE 不调用 init
函数。IIFE 本身在以下情况下被称为
window.addEventListener("load", function() { // IIFE code }() );
语句在页面的 head 部分中执行。此时将创建在 IIFE 中顶级声明的所有函数对象。IIFE 返回的函数 init
在为 HTML 正文创建所有 DOM 元素并触发窗口加载事件后,注册为稍后执行的侦听器。
如果您在其他el
和style
初始化后从init
调用userStart
,游戏将开始。尽管通常调用 userStart
以响应单击开始按钮,但如果通过其他方式调用它,它的行为仍然相同。