gpt4 book ai didi

javascript - 调整onclick回调函数的范围

转载 作者:行者123 更新时间:2023-12-01 02:42:40 25 4
gpt4 key购买 nike

我正在尝试解决一个编程练习,其中有几个错误需要修复。最终,它应该用细胞网格来表示一个动画,其中在每个时间步,如果一个细胞恰好有 3 个存活的邻居(每个细胞有 8 个邻居),那么它就会“复活”,如果它的邻居数量更少,那么它就会“复活”。超过 2 个或超过 3 个邻居,它就会“死亡”(邻居“环绕”网格)。初始脚本如下:

<html>
<head>
<script type="text/javascript">
var Board;
var xsize = 10;
var ysize = 10;

var dead = 0;
var alive = 1;

function Neighbors(Board, x, y)
{
var n = 0
for(dx=-1;dx < 1; ++dx)
for(dy=-1;dy < 1; ++dy)
{
var ax = x+dx;
var ay = y+dy;
if(Board[ax][ay]==alive) ++n;
}
return n;
}

function Kill(Board,x,y)
{
if(Board[x][y] == alive)
Board[x][y] = dead;
}

function MakeLive(Board,x,y)
{
if(Board[x][y] == dead)
Board[x][y] = alive;
}

function NextStep(Board)
{
for(var x = 0; x <= xsize; ++x)
{
for(var y = 0; y <= ysize; ++x)
{
n = Neighbors(Board,x,y);
if(n=3) MakeLive(Board,x,y);
if((n<2)||(n>3)) Kill(Board,x,y);
}
}
}

function DrawBoard(Board)
{
var Text = "";
for(var y = 0; y < ysize; ++y)
{
for(var x = 0; x < xsize; ++x)
Text += Board[x][y]==alive ? "o":"_";
Text += "<br/>";
}
document.getElementById("board").innerHTML = Text;
}

function Main()
{
// *** Change this variable to choose a different baord setup from below
var BoardSetup = "blinker";

Board = new Array(xsize);
for(var x = 0; x < xsize; ++x)
{
Board[x] = new Array(ysize);
for(var y = 0; y < ysize; ++y)
Board[x][y] = 0;
}

if(BoardSetup == "blinker")
{
Board[1][0] = 1;
Board[1][1] = 1;
Board[1][2] = 1;
}
else if(BoardSetup == "glider")
{
Board[2][0] = 1;
Board[2][1] = 1;
Board[2][2] = 1;
Board[1][2] = 1;
Board[0][1] = 1;
}
else if(BoardSetup == "flower")
{
Board[4][6] = 1;
Board[5][6] = 1;
Board[6][6] = 1;
Board[7][6] = 1;
Board[8][6] = 1;
Board[9][6] = 1;
Board[10][6] = 1;
Board[4][7] = 1;
Board[6][7] = 1;
Board[8][7] = 1;
Board[10][7] = 1;
Board[4][8] = 1;
Board[5][8] = 1;
Board[6][8] = 1;
Board[7][8] = 1;
Board[8][8] = 1;
Board[9][8] = 1;
Board[10][8] = 1;
}

DrawBoard(Board);
}
</script>
</head>
<body onload="Main()">
<div id="board">
</div>
<a href="#IGoNowhere" onclick="NextStep(Board);DrawBoard(Board);">Next -></a>
</body>
</html>

问题是,如果我按“下一步”按钮,我会在控制台中看到以下错误:

Uncaught TypeError: Cannot read property '-1' of undefined
at Neighbors (life_broken__281_29.html:19)
at Function.NextStep (life_broken__281_29.html:42)
at HTMLAnchorElement.onclick (life_broken__281_29.html:117)
Neighbors @ life_broken__281_29.html:19
NextStep @ life_broken__281_29.html:42
onclick @ life_broken__281_29.html:117

我认为问题在于 Board定义于 Main()函数,它不在 onclick 的范围内回调函数。

我最初的方法是移动 Board 的初始化Main()之外函数,使其成为全局变量,并删除 Board来自所有函数调用。然而,这似乎不是一个优雅的方法。相反,我尝试使用 Function.prototype.call()如下:

<a href="#IGoNowhere" onclick="NextStep.call(Main, Board); DrawBoard.call(Main, Board);">Next -></a>

此外,我实现了 wrapAround避免索引越界的函数:

function Neighbors(Board, x, y)
{
var n = 0
for(dx=-1;dx < 1; ++dx)
for(dy=-1;dy < 1; ++dy)
{
var ax = x+dx;
var ay = y+dy;
ax = wrapAround(ax, xsize);
ay = wrapAround(ay, ysize);
if(Board[ax][ay]==alive) ++n;
}
return n;
}

function wrapAround(coordinate, size) {
var result = coordinate % size;
if (result < 0) {
result += size;
}
return result;
}

但是,现在我收到一个新错误:

life_broken__281_29.html:42 Uncaught TypeError: Cannot read property '0' of undefined
at MakeLive (life_broken__281_29.html:42)
at Function.NextStep (life_broken__281_29.html:53)
at HTMLAnchorElement.onclick (life_broken__281_29.html:127)

显然,Neighbors函数现在不会引发任何错误,但 NextStep 中的下一个函数会引发任何错误。 , MakeLive , 是。然而我不明白,因为它们都是在同一“级别”定义的,并且在NextStep中有类似的调用。 。谁能解释一下这里的问题是什么?

更新

确实Board是在全局范围内声明的,因此不需要 Function.prototype.call() 。 (我习惯了Python,其中声明和定义总是在同一个地方)。我还将 bool 表达式更改为 (x === 3)

但是,由于某种原因x仍在上升至10即使我替换 <=通过< 。这是更新后的代码,带有 console.log调试语句:

<html>
<head>
<script type="text/javascript">
var Board;
var xsize = 10;
var ysize = 10;

var dead = 0;
var alive = 1;

function Neighbors(Board, x, y)
{
var n = 0
for(dx=-1;dx < 1; ++dx)
for(dy=-1;dy < 1; ++dy)
{
var ax = x+dx;
var ay = y+dy;
ax = wrapAround(ax, xsize);
ay = wrapAround(ay, ysize);
if(Board[ax][ay]==alive) ++n;
}
return n;
}

function wrapAround(coordinate, size) {
var result = coordinate % size;
if (result < 0) {
result += size;
}
return result;
}

function Kill(Board, x, y)
{
if (Board[x][y] == alive)
Board[x][y] = dead;
}

function MakeLive(Board, x, y)
{
if (Board[x][y] == dead)
Board[x][y] = alive;
}

function NextStep(Board)
{
for(var x = 0; x < xsize; ++x)
{
for(var y = 0; y < ysize; ++x)
{
n = Neighbors(Board,x,y);
console.log("x = " + x + ", y = " + y + ", n = " + n);
if (n===3) MakeLive(Board,x,y);
if ((n<2)||(n>3)) Kill(Board,x,y);
}
}
}

function DrawBoard(Board)
{
var Text = "";
for(var y = 0; y < ysize; ++y)
{
for(var x = 0; x < xsize; ++x)
Text += Board[x][y]==alive ? "o":"_";
Text += "<br/>";
}
document.getElementById("board").innerHTML = Text;
}

function Main()
{
// *** Change this variable to choose a different baord setup from below
var BoardSetup = "blinker";

Board = new Array(xsize);
for(var x = 0; x < xsize; ++x)
{
Board[x] = new Array(ysize);
for(var y = 0; y < ysize; ++y)
Board[x][y] = 0;
}

if(BoardSetup == "blinker")
{
Board[1][0] = 1;
Board[1][1] = 1;
Board[1][2] = 1;
}
else if(BoardSetup == "glider")
{
Board[2][0] = 1;
Board[2][1] = 1;
Board[2][2] = 1;
Board[1][2] = 1;
Board[0][1] = 1;
}
else if(BoardSetup == "flower")
{
Board[4][6] = 1;
Board[5][6] = 1;
Board[6][6] = 1;
Board[7][6] = 1;
Board[8][6] = 1;
Board[9][6] = 1;
Board[10][6] = 1;
Board[4][7] = 1;
Board[6][7] = 1;
Board[8][7] = 1;
Board[10][7] = 1;
Board[4][8] = 1;
Board[5][8] = 1;
Board[6][8] = 1;
Board[7][8] = 1;
Board[8][8] = 1;
Board[9][8] = 1;
Board[10][8] = 1;
}

DrawBoard(Board);
}
</script>
</head>
<body onload="Main()">
<div id="board">
</div>
<a href="#IGoNowhere" onclick="NextStep(Board); DrawBoard(Board);">Next -></a>
</body>
</html>

这是当我单击“下一步”时控制台的结果:

x = 0, y = 0, n = 0
life_broken__281_29.html:53 x = 1, y = 0, n = 1
life_broken__281_29.html:53 x = 2, y = 0, n = 0
life_broken__281_29.html:53 x = 3, y = 0, n = 0
life_broken__281_29.html:53 x = 4, y = 0, n = 0
life_broken__281_29.html:53 x = 5, y = 0, n = 0
life_broken__281_29.html:53 x = 6, y = 0, n = 0
life_broken__281_29.html:53 x = 7, y = 0, n = 0
life_broken__281_29.html:53 x = 8, y = 0, n = 0
life_broken__281_29.html:53 x = 9, y = 0, n = 0
life_broken__281_29.html:53 x = 10, y = 0, n = 0
life_broken__281_29.html:36 Uncaught TypeError: Cannot read property '0' of undefined
at Kill (life_broken__281_29.html:36)
at NextStep (life_broken__281_29.html:55)
at HTMLAnchorElement.onclick (life_broken__281_29.html:128)

我有点困惑为什么会发生这种情况,因为一个简单的 for以这种方式循环确实有效:

for (var i = 0; i < 10; ++i) {
console.log("i = " + i);
}
VM158:2 i = 0
VM158:2 i = 1
VM158:2 i = 2
VM158:2 i = 3
VM158:2 i = 4
VM158:2 i = 5
VM158:2 i = 6
VM158:2 i = 7
VM158:2 i = 8
VM158:2 i = 9
undefined

控制台是否以某种方式使用旧代码的缓存版本? (我正在使用括号中的实时预览)。

更新2

这是因为我应该使用后增量而不是前增量(参见 http://jsforallof.us/2014/07/10/pre-increment-vs-post-increment/ )。更改 ++xx++问题解决了。

最佳答案

该错误与变量范围无关。 Board是一个全局变量,因此任何函数都可以访问它。

您最初的问题是因为您正在访问 Board 外部数组当 x = 0dx = -1 ,然后你用 wrapAround() 修复了这个问题功能。

下一个问题是你的循环 NextStep走的太远了。行索引从0开始至xsize-1列从 0 开始至ysize-1 。但那里的循环使用 x <= xsizey <= ysize ,因此它将尝试访问 Board[xsize] ,它不存在。更改那些<=< ,就像 Main() 中的循环一样.

关于javascript - 调整onclick回调函数的范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47446570/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com