2016-02-18 2 views
1

У меня есть функция, которая была создана для управления и создания массива объектов и добавления ключа position к каждому элементу массива, но, похоже, он не работает должным образом. .Свойства объекта массива объекта, меняющегося при возврате массива

Моя функция:

var fillQueue = function(choices, currentQueue) { 
    var choice, i, positionInQueue, previousTitle, resultQueue; 

    resultQueue = []; 
    previousTitle = ""; 

    i = 0; 

    while (i < 10) { 
    positionInQueue = i + 1; 
    console.log('Adding song to position ' + positionInQueue); 

    if (currentQueue[i]) { 
     previousTitle = currentQueue[i].title; 
     currentQueue[i].position = positionInQueue; 
     resultQueue.push(currentQueue[i]); 
    } else { 
     choice = choices[Math.floor(Math.random() * choices.length)]; 

     if (choice.title !== previousTitle) { 
     previousTitle = choice.title; 
     choice.position = positionInQueue; 
     resultQueue.push(choice); 
     } else { 
     choice = choices[Math.floor(Math.random() * choices.length)]; 
     previousTitle = choice.title; 
     choice.position = positionInQueue; 
     resultQueue.push(choice); 
     } 
    } 

    i++; 
    } 

    return resultQueue; 
}; 

Если это называется правильно, подставляя в значениях для choices и currentQueue (currentQueue также может быть пустой массив), как показано ниже, функция возвращает массив, который предназначена, но по какой-то причине винты вокруг с помощью клавиш position на каждом объекте внутри него.

var test = fillQueue([ {title: '1'}, {title: '2'}, {title: '3'}, {title: '4'} ], [ { title: '5', position: 1 } ]); 

выше переменная будет содержать следующее:

[ { title: '5', position: 1 }, 
    { title: '1', position: 9 }, 
    { title: '3', position: 7 }, 
    { title: '1', position: 9 }, 
    { title: '2', position: 10 }, 
    { title: '2', position: 10 }, 
    { title: '3', position: 7 }, 
    { title: '1', position: 9 }, 
    { title: '1', position: 9 }, 
    { title: '2', position: 10 } ] 

Как вы можете видеть, это не добавляя position s правильно в каждом объекте. Каждый объект в возвращаемом массиве должен иметь positioni + 1, но вместо этого он кажется случайным числом от 1 до 10 - некоторые из объектов даже имеют одинаковые position.

Я попытался:

  • переименовании position к чему-то еще, в случае, если это было то, что было уже используется JavaScript
  • Убедившись, что правильно position добавляется к объекту, прежде чем и после .push Ввод его в массив.

Это делает меня действительно смущенным. Ваша помощь будет оценена по достоинству.

Fiddle: https://jsfiddle.net/deansheather/jnw8jdf4/

+0

Какой именно формат вывода необходим? –

+1

То, что вы нажимаете на массив, является ** ссылкой ** на * выбор *, поэтому каждый раз, когда вы обновляете 'choice.position', все экземпляры этого выбора получают одинаковое значение« position », например. все варианты с «Title: 1» будут иметь одинаковую позицию, потому что все они ссылаются на один и тот же объект. Вам нужно создать копию выбора, обновить ее позицию и нажать копию в массив. – RobG

+0

@TajAhmed Я ищу массив, содержащий 10 объектов. Каждый объект в этом массиве ** должен иметь свойство 'position', равное' i + 1'. – deansheather

ответ

1

Вы подталкиваете ссылки в массив, так что каждый раз при обновлении choice.position всех ссылок на тот же выбор в массиве получить такое же значение позиции.

Чтобы исправить это, скопируйте объект , обновите его положение и нажмите его в массив, например.

if (choice.title !== previousTitle) { 
     previousTitle = choice.title; 
     newChoice = objCopyShallow(choice); // see below for copy function 
     newChoice.position = positionInQueue; 
     resultQueue.push(newChoice); 
} 

Для этого приложения, простая функция копирования:

function objCopyShallow(obj) { 
    return Object.keys(obj).reduce(function(acc, v) { 
     acc[v] = obj[v]; 
     return acc; 
    },{}); 
} 

Есть миллион вопросов и ответов здесь о том, «как копировать объект», если вы хотите что-то более глубокое.

0

я смог придумать следующее. Это работает, поскольку я избегаю использования циклов/while, которые имеют ссылку «gotchas» в JS, о которых вам нужно знать при обновлении значений, используя это.

var fillQueue = function(choices, currentQueue) { 
 
    // concat choices to end of currentQueue 
 
    // create a new array instance with updated position property using .map 
 
    // keep 10 elements from new array starting at index 0 
 
    return currentQueue.concat(choices).map((e, i) => { 
 
    return Object.assign({title:e.title, position:i+1}); 
 
    }).splice(0, 10) 
 
};

+0

У этого есть те же проблемы, что и OP. – RobG

1

Как RobG Уже сказано, что вы нажимаете ссылки на свой массив. Создайте копию своего объекта выбора, а затем нажмите на свой массив. создайте копию своего объекта с помощью clone() смените вашу должность на choice = clone(choices[Math.floor(Math.random() * choices.length)]); все готово.

function clone(obj) { 
    if (null == obj || "object" != typeof obj) return obj; 
    var copy = obj.constructor(); 
    for (var attr in obj) { 
     if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr]; 
    } 
    return copy; 
} 
Смежные вопросы