我知道JavaScript通过引用传递对象,因此我在使用以下代码时遇到了很多麻烦:
function doGradeAssignmentContent(dtos) {
var x = 5;
var allPages = [];
var stage = new App.UI.PopUpDisplay.PopUpStageAssignmentGrader(null, that);// pass launch element
for(var i = 0; i < dtos[0].result.students.length; ++i) {
var pagesSet = [];
for(var j = 0; j < dtos[0].result.questions.length; ++j) {
var questionObject = jQuery.extend(true, {}, new Object());
questionObject = dtos[0].result.questions[j];
if(dtos[0].result.students[i].answers[j].assignmentQuestionId === questionObject.questionId) {// expected, if not here something is wrong
questionObject.answer = dtos[0].result.students[i].answers[j].studentAnswer;
questionObject.pointsReceived = dtos[0].result.students[i].answers[j].pointsReceived;
} else {
var theAnswer = findAssociatedStudentAnswer(questionObject.questionId, dtos[0].result.students[i].answers[j]);
if(theAnswer !== null) {
questionObject.answer = theAnswer.studentAnswer;
questionObject.pointsReceived = theAnswer.pointsReceived;
} else {
alert("Unexpected error. Please refresh and try again.");
}
}
pagesSet[pagesSet.length] = new App.UI.PopUpDisplay.StageAssignmentGradingPages[dtos[0].result.questions[j].questionType.charAt(0).toUpperCase() + dtos[0].result.questions[j].questionType.slice(1) + "QuestionAssignmentGradingPage"](j + 1, questionObject);
}
var studentInfo = {};
studentInfo.avatar = dtos[0].result.students[i].avatar;
studentInfo.displayName = dtos[0].result.students[i].displayName;
stage.addPageSet(pagesSet, studentInfo);
}
stage.launch();
}
首先让我告诉你结果(dtos)是什么样的,这样你就可以更好地理解这个函数如何解析它了:
结果(dtos)是一个Object,看起来像:
现在我们在这里做的是创建这个Object阶段。这里重要的是它有一个名为“this.studentsPages”的数组。这个数组最终将拥有与dtos [0] .students中的学生一样多的条目。
所以我们循环遍历这个for循环来处理dtos数组并创建一个pagesSet数组。 这是我的问题。在第一次迭代通过for循环我创建了这个questionObject元素。我也试过做var questionObject = {},但你现在看到的只是尝试修复我看到的问题,但它也没有用。
所以在外部for循环的第一次迭代结束时,我调用stage.addPageSet,这就是这里发生的事情:
var pageObject = [];
pageObject["questions"] = pageSet;
pageObject["displayName"] = studentInfo.displayName;
this.studentsPages[this.studentsPages.length] = pageObject;
if(this.studentsPages.length === 1) {// first time only
for(var i = 0; i < pageSet.length; ++i) {
this.addPage(pageSet[i]);
}
}
需要注意的重要一点是我将pageObject添加到this.studentsPages上,这是第一次调用之前的空数组。 pageObject现在有pageSet以及更多信息。请记住,pageSet是一个Object,因此通过引用传递。
在for循环的下一次迭代中,当我点击这一行时:
questionObject.answer = dtos[0].result.students[i].answers[j].studentAnswer;
出错了。这会更改questionObject的本地副本,但它也会更改传递给addPageSet并在第一次迭代中添加到studentsPages数组的questionObjec副本。所以,如果我只有2名学生进来,那么当完成所有工作时,studentPages会保留2个相同的对象。这不应该是真的。
问题是在doGradeAssignmentContent函数中的questionObject保持对在上一次迭代中创建的Object的引用,然后在所有后续迭代中覆盖它。
我该怎么做才能解决这个问题?
感谢您的帮助!
答案 0 :(得分:1)
如果仔细观察它,我相信您需要更改以下内容:
// Before:
var questionObject = jQuery.extend(true, {}, new Object());
questionObject = dtos[0].result.questions[j];
// After:
var questionObject = jQuery.extend(true, {}, dtos[0].result.questions[j]);
如果代码中还有其他需要应用的实例,我没有仔细看,但核心概念是利用jQuery的深层副本生成对象的副本,不希望保留引用到。