0

我知道 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)是一个对象,看起来像:

  • dtos 数组
  • dtos[0],静态总是在这里
  • dtos[0].result,静态总是在这里
  • dtos[0].questions 数组
  • dtos[0].questions.index0 - indexN。这描述了我们的问题,每一个都是一个对象
  • dtos[0].students 数组
  • dtos[0].students[0]-[n].answers 数组。每个学生数组/对象都有一个 Answers 数组。每个学生将在此答案数组中拥有与 dtos[0].questions 中的问题一样多的元素。每个元素都是一个对象

现在我们在这里做的是创建这个对象阶段。这里重要的是它有一个名为“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 是一个对象,因此通过引用传递。

在 for 循环的下一次迭代中,当我点击这一行时:

questionObject.answer = dtos[0].result.students[i].answers[j].studentAnswer;

它出错了。这会更改 questionObject 的本地副本,但它也会更改传递给 addPageSet 并在第一次迭代中添加到 studentsPages 数组的 questionObjec 的副本。所以,如果我只有 2 个学生进来,那么当一切都说完之后,studentPages 包含 2 个相同的对象。这不应该是真的。

问题是 doGradeAssignmentContent 函数中的 questionObject 保留对在前一次迭代中创建的对象的引用,然后在所有后续迭代中覆盖它。

我能做些什么来解决这个问题?

谢谢您的帮助!

4

1 回答 1

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 的深层复制来生成您不希望保留引用的对象的副本。

于 2013-05-14T03:03:01.837 回答