JavaScript在将对象传递给函数后停止引用对象

时间:2013-05-14 01:37:49

标签: javascript copy clone pass-by-reference pass-by-value

我知道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,看起来像:

  • dtos数组
  • dtos [0],静态总是在这里
  • dtos [0] .result,static always here
  • dtos [0] .questions Array
  • dtos [0] .questions.index0 - indexN。这描述了我们的问题,每个问题都是一个对象
  • dtos [0] .students Array
  • dtos [0] .students [0] - [n] .answers数组。每个学生数组/对象都有一个Answers数组。每个学生在这个答案数组中都有尽可能多的元素,dtos [0] .questions中存在问题。每个元素都是一个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的引用,然后在所有后续迭代中覆盖它。

我该怎么做才能解决这个问题?

感谢您的帮助!

1 个答案:

答案 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的深层副本生成对象的副本,不希望保留引用到。