#javascript #angularjs
У меня есть пара массивов. Нужно занести определенные значения в нужные места. Здесь
даже не столько AngularJS нужен, сколько чистый JS: проход по массивам и т.д.
Мои массивы:
$scope.usersNew - массив пользователей с ответами на вопрос анкеты. Структура такая:
id - идентификатор, понятно.
user - имя пользователя,
questions - массив ответов на вопросы. Его структура следующая:
id вопроса,
name вопроса,
answer - собственно, ответ. По умолчанию записана строка "No answer".
$scope.anss - массив всех ответов из базы данных. Структура (та ее часть, которую
я использую):
sessionID - идентификатор сессии, аналог имени пользователя,
questionAnswer - структура, в которой хранится информация о вопросе и
ответе. Из нее беру:
question - структура с информацией о вопросе. Я использую только поле id,
answer - структура с информацией об ответе. Я использую поле text
Мой код:
// формирование массива пользователей с ответами
// проход по пользователя
for (var k = 0; k < $scope.usersNew.length; k++) {
// проход по ответам
for (var i = 0; i < $scope.anss.length; i++) {
// принадлежность ответа пользователю
if ($scope.anss[i].sessionID == $scope.usersNew[k].user) {
// проход по ответам пользователя
for (var j = 0; j < $scope.usersNew[k].questions.length; j++) {
// соответствие ответов по id вопроса
if ($scope.usersNew[k].questions[j].id ==
$scope.anss[i].questionAnswer.question.id) {
// присвоение ответа пользователю
$scope.usersNew[k].questions[j].answer =
$scope.anss[i].questionAnswer.answer.text;
break; break;
}
}
}
}
}
Дебаггер показал, что в строке присвоения ответа пользователю программа записывает
этот ответ сразу всем пользователям, хотя пользователи вроде как перебираются в самом
верхнем for.
У меня появилась мысль: может, дело в том, как я заполняла первый массив usersNew?
Когда записывала в поля answer значение "No answer", это выглядело примерно так:
for (var i = 0; i < $scope.anss.length; i++) {
var item = { id: "", user: "", questions: {} }
item.id = $scope.anss[i].id;
item.user = $scope.anss[i].sessionID;
item.questions = $scope.arrForAns;
users.push(item);
}
Где $scope.arrForAns - массив, созданный таким образом:
$scope.arrForAns = answers.questions;
// answers.questions - это массив объектов, который я достала из JSON, там уже есть
id и name
for (var i = 0; i < $scope.arrForAns.length; i++) {
$scope.arrForAns[i].answer = "No answer";
}
Я вроде читала, уже не уверена где, что с присвоением массивов есть загвоздка: что
копируются не данные, а ссылки, и, возможно, в памяти лежит один несчастный массив
questions на всех пользователей, и он-то и терзается со всех сторон.
Или я ошибаюсь, и это я читала о чем-то другом.
Ответы
Ответ 1
Да. Для всего, кроме примитивных типов копируется ссылка. К примитивным типам относятся созданные без использования new числа, строки и bool'ы, а также null и undefined. PS: Не лень было такой вопрос задавать вместо того, чтобы погуглить про передачу по ссылке? гугл объяснил в чем дело, но его решение почему-то не помогает Не очень разобрался со всей структурой, но подозреваю, что это из-за того, что внутри массива тоже ссылки. Ангуляр позволяет сделать глубокую копию при помощи angular.copy: item.questions = angular.copy($scope.arrForAns);Ответ 2
Хронический пример "Closures". Самый простой способ решения - поместить содержание внутренних for(){} на тот же уровень, где находится сам цикл, например: function closure1() { function binder1(x){ return function(){ return x; }; } var arr = [], i; for (i = 0; i <10; i++){ arr[i] = binder1(i); } return arr; } console.log(closure1()); Или заменить присвоение ответа пользователю на: // соответствие ответов по id вопроса if ($scope.usersNew[k].questions[j].id == $scope.anss[i].questionAnswer.question.id) { // присвоение ответа пользователю (function(k, j, i) { return function() { $scope.usersNew[k].questions[j].answer = $scope.anss[i].questionAnswer.answer.text; }; })(k, j, i) } Проверять, если честно, лень, но смысл в том, что вам надо создать ещё один контекст для хранения j, i и k.
Комментариев нет:
Отправить комментарий