这是我正在处理的内存游戏的当前代码。我正在使用纯JavaScript,而且我的a-tags的onclick功能遇到了问题。我想要的是游戏将点击的图像(问号)与分配给点击图像的类号的图像交换,从而产生翻转效果。
我目前得到的是,无论我在哪里点击,只有最后一张图片被交换。
"use strict"
var newDiv = null;
var innerDiv = null;
var table = null;
var row = null;
var cell = null;
var aTag = null;
var image = null;
// Use this to put class names on the images.
var boxCounter = 0;
// Static memory-object.
var Memory = {
memoryArray: [],
init: function (e) {
// Calls a separate js-file which generates a random numbers.
Memory.memoryArray = RandomGenerator.getPictureArray(4, 4);
// Calls the rendering method
Memory.renderArray(Memory.memoryArray);
},
renderArray: function (myArray) {
// Creates and places div-tags in the HTML-document.
newDiv = document.createElement("div");
document.getElementsByTagName("body")[0].appendChild(newDiv);
innerDiv = document.createElement("div");
newDiv.appendChild(innerDiv);
// Creates a table and places it in the HTML-document.
table = document.createElement("table");
table.border = 1;
// Generates rows and cells, swap the 4's to change the size of the gameboard.
for (var i = 0; i < 4; ++i) {
row = document.createElement("tr");
table.appendChild(row);
// Creates a cell, each with its own respective random number.
for (var j = 0; j < 4; ++j) {
cell = document.createElement("td");
// Adds a "Question-mark"-picture to the cell and places them in a-tags.
image = document.createElement("img");
image.className = myArray[i * 4 + j];
image.src = "https://github.com/1dv403/1dv403-laborationer/blob/master/3-gameon/memory/pics/0.png?raw=true";
aTag = document.createElement("a");
aTag.onclick = function () {
Memory.flipTile(image.className);
};
// Places the pictures in the document, along with its random number for easier testing purposes.
aTag.appendChild(document.createTextNode(myArray[i * 4 + j]));
aTag.appendChild(image);
cell.appendChild(aTag);
row.appendChild(cell);
};
};
innerDiv.appendChild(table);
},
flipTile: function (imageClass) {
console.log(imageClass);
// This should flip the tiles if the number matches the class name.
if (imageClass == 1) {
image.src = "https://github.com/1dv403/1dv403-laborationer/blob/master/3-gameon/memory/pics/1.png?raw=true";
};
if (imageClass == 2) {
image.src = "https://github.com/1dv403/1dv403-laborationer/blob/master/3-gameon/memory/pics/2.png?raw=true";
};
if (imageClass == 3) {
image.src = "https://github.com/1dv403/1dv403-laborationer/blob/master/3-gameon/memory/pics/3.png?raw=true";
};
if (imageClass == 4) {
image.src = "https://github.com/1dv403/1dv403-laborationer/blob/master/3-gameon/memory/pics/4.png?raw=true";
};
if (imageClass == 5) {
image.src = "https://github.com/1dv403/1dv403-laborationer/blob/master/3-gameon/memory/pics/5.png?raw=true";
};
if (imageClass == 6) {
image.src = "https://github.com/1dv403/1dv403-laborationer/blob/master/3-gameon/memory/pics/6.png?raw=true";
};
if (imageClass == 7) {
image.src = "https://github.com/1dv403/1dv403-laborationer/blob/master/3-gameon/memory/pics/7.png?raw=true";
};
if (imageClass == 8) {
image.src = "https://github.com/1dv403/1dv403-laborationer/blob/master/3-gameon/memory/pics/8.png?raw=true";
};
}
};
window.onload = Memory.init;
答案 0 :(得分:1)
这是一个涉及闭包和循环的经典问题。考虑函数表达式
创建的闭包aTag.onclick = function () {
Memory.flipTile(image.className);
};
它从更高的范围引用image
,那么循环中的下一次迭代会发生什么?
image = document.createElement("img");
image
现在指向不同的对象,因此在循环的最后一次迭代中,所有image
指向相同的(最后一个)<img>
元件。
您需要为image
创建一个闭包,这样才不会发生。您可以通过编写一个函数来生成所需的函数
function makeClickListener(elm) {
return function () {
Memory.flipTile(elm.className);
};
}
现在,使用它来创建单击监听器
aTag.onclick = makeClickListener(image);
这可以通过仅传递 String 而不是整个 Object 进一步优化(需要更少的内存)。
答案 1 :(得分:0)
所有点击处理程序都引用相同的图像变量(在for循环结束后将是最后一个图像)。您需要每个处理程序引用不同的图像变量。您可以通过将其作为参数传递给函数来创建它的副本来完成此操作。
替换它:
function () {
Memory.flipTile(image.className);
};
有了这个:
function(classname) {
return function () {
Memory.flipTile(className);
};
}(image.classname);
第二个问题:全球形象。 flipTile函数对图像变量执行某些操作,但在其中没有声明。您实际上想要将图像作为参数传递,如下所示:
为:
flipTile: function (imageClass) {
好:
flipTile: function (image, imageClass) {
现在您还需要更改对函数的调用以传递图像:
function(img, classname) {
return function () {
Memory.flipTile(img, className);
};
}(image, image.classname);
考虑到您将图像作为参数传递给flipTile,看起来您不需要传递image.classname,因此您可以更改函数以使用image.classname。 Thais步骤是可选的,没有它,代码应该可以正常工作。