我正在开发一个JavaScript网络应用程序,用于在阵列中存储闪存卡的集合(堆栈)。
现在我遇到了循环内部闭包的问题。我查看了这个例子(https://stackoverflow.com/a/15466863/1822824)并试图实现类似的东西,但我收到一个错误:“TypeError:'null'不是一个对象(评估'document.getElementById(temp)')”。
Web应用程序应将所有闪存卡集(堆栈)列为链接,当您单击链接时,它会使用您单击的闪存卡堆栈的名称提醒您。在我尝试添加提醒您的链接部分之前,一切正常。
小提琴:http://jsfiddle.net/xmYug/
以下是我的代码:
<p>
<strong>Flashcard Stack Name:</strong>
<input type="text" id="textStackName">
</p>
<p>
<strong>Enter one flashcard per line, seperate the front and back of each flashcard with a comma:</strong><br>
<textarea name="textarea" id="textareaFlashcards" cols="45" rows="15"></textarea>
</p>
<p>
<input type="submit" id="buttonSubmit" value="Submit">
</p>
<div id="allStacks">
</div>
<script>
var funcs = [];
function createfunc(i) {
var temp = "link" + i;
return document.getElementById(temp).onclick = function() {
// Alert the user of the stack name they just clicked on
alert("Stack name: " + allStacks[i].stackName);
};
}
/* Constructors */
// Constructs a new stack of flashcards - a stack of flashcards is usually about a single topic such as States & Capitals
function newStackConstructor(stackName) {
this.stackName = stackName;
this.stack = new Array();
}
// Constructs a new flashcard - a stack can have an unlimited number of flashcards
function newFlashcardConstructor(flashcardFront, flashcardBack) {
this.flashcardFront = flashcardFront;
this.flashcardBack = flashcardBack;
}
// Contains all of the flashcard stacks
var allStacks = new Array();
// SAMPLE DATA //////////////////////////////////////////////////////////////////////
// Make a test stack
allStacks.push(new newStackConstructor("States & Capitals"));
// Test data
allStacks[0].stack.push(new newFlashcardConstructor("Alabama", "Montgomery"));
allStacks[0].stack.push(new newFlashcardConstructor("Alaska", "Juneau"));
allStacks[0].stack.push(new newFlashcardConstructor("Arizona", "Phoenix"));
////////////////////////////////////////////////////////////////////////
buttonSubmit.onclick = function () {
newFlashcardStack();
};
// Make a new flashcard stack
function newFlashcardStack() {
allStacks.push(new newStackConstructor(textStackName.value));
var textareaFlashcardsTemp = textareaFlashcards.value;
// Split flashcards by line break
var flashcards = textareaFlashcardsTemp.split("\n");
for (var i = 0; i < flashcards.length; i++) {
// Split front & back of flashcards by comma
flashcard = flashcards[i].split(",");
allStacks[(allStacks.length - 1)].stack.push(new newFlashcardConstructor(flashcard[0], flashcard[1]));
}
// Update stack display to display all of the stacks and the new stack
displayAllStacks();
}
// Display all flashcard stacks
function displayAllStacks() {
// Clear stack display
document.getElementById("allStacks").innerHTML = "";
for (var i = 0; i < allStacks.length; i++) {
funcs[i] = createfunc(i);
document.getElementById("allStacks").innerHTML += '<p><a href="#" id="link' + i + '">' + allStacks[i].stackName + '</a></p>';
}
}
displayAllStacks();
</script>
答案 0 :(得分:2)
我不确定为什么你在其中分配点击处理程序的闭包返回该处理程序,并将所有这些存储在funcs
数组中。
然而,
funcs[i] = createfunc(i);
document.getElementById("allStacks").innerHTML += '<p><a href="#" id="link' + i + '">' + allStacks[i].stackName + '</a></p>';
在创建该元素之前,您尝试创建并分配处理函数。然而,
document.getElementById("allStacks").innerHTML += '<p><a href="#" id="link' + i + '">' + allStacks[i].stackName + '</a></p>';
funcs[i] = createfunc(i);
也不会正常工作,因为通过分配给innerHTML
覆盖当前DOM并创建尚未分配任何事件处理程序的新链接。相反,使用
var display = document.getElementById("allStacks");
display.innerHTML = "";
for (var i=0; i<allStacks.length; i++) {
var p = document.createElement("p");
var a = document.createElement("a");
p.appendChild(a);
a.appendChild(document.createTextNode(allStacks[i].stackName));
a.href="#";
// a.id = "link"+i; is not necessary
var func = (function(i) {
return function() {
// Alert the user of the stack name they just clicked on
alert("Stack name: " + allStacks[i].stackName);
};
})(i);
// funcs[i] = func; if you want that
a.onclick = func;
display.appendChild(p);
}