Question

I know JavaScript passes Objects by reference and thus I'm having a lot of trouble with the following code:

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();
                }

First let me show you what the result (dtos) looks like so you can better understand how this function is parsing it:

The result (dtos) is an Object and looks something like:

  • dtos Array
  • dtos[0], static always here
  • dtos[0].result, static always here
  • dtos[0].questions Array
  • dtos[0].questions.index0 - indexN. This describes our Questions, each one is an Object
  • dtos[0].students Array
  • dtos[0].students[0]-[n].answers Array. Each student array/Object has an Answers array. Each student will have as many elements in this answers Array that there were questions in dtos[0].questions. Each element is an Object

Now what we do in this here is create this Object stage. Important things here are it has an array called "this.studentsPages". This array will ultimately have as many entries as there were students in dtos[0].students.

So we loop through this for loop disecting the dtos array and creating a pagesSet array. Here comes my problem. On the first iteration through the for loop I create this questionObject element. I also have tried just doing var questionObject = {}, but what you see now was just an attempt to fix the problem I was seeing, but it didn't work either.

So at the end of the first iteration of the outer for loop I call stage.addPageSet, this is what happens here:

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]);
                }
            }

The important thing to take notice of here is where I add pageObject on to this.studentsPages which was an empty array before the first call. pageObject now has pageSet plus a little bit more information. Remember, pageSet was an Object and thus passed by reference.

On the next iteration of the for loop, when I hit this line:

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

It goes wrong. This changes the local copy of questionObject, BUT it also changes the copy of questionObjec that was passed to addPageSet and added to the studentsPages array in the first iteration. So, if I only had 2 students coming in, then when all is said and done, studentsPages hold 2 identical Objects. This should not be true.

The problem is questionObject in the doGradeAssignmentContent function is keeping a reference to the Object created on the previous iteration and then overrides it on all subsequent iterations.

What can I do to fix this?

Thanks for the help!

Était-ce utile?

La solution

With out having looked at it too closely I believe you need to change the following:

// 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]);

I didn't look too closely if there are other instances in the code where this needs to be applied, but the core concept is to utilize jQuery's deep copy to generate a duplicate of the object you do not wish to retain a reference to.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top