Это пример из игры, похожей на покемонов. Я создаю объект, и внутри него я пытаюсь создать новый объект «en» и «to», то есть две разные атаки. Проблема в том, что когда я пытаюсь что-то отредактировать в любом из объектов атаки ("en" и "two"), изменение происходит с каждым покемоном с таким же именем. Этого не происходит со «здоровьем», поэтому я думаю, что проблема в this.en = new Object;.
Это код для создания покемонов.
function Fakemon(_navn, _type, _attackPower, _src,
_1Navn, _1Force, _1Antall_, _2Navn, _2Force, _2Antall) {
this.navn = _navn;
this.type = _type;
this.attackPower = _attackPower;
this.src = _src;
this.en = new Object;
this.en.navn = _1Navn;
this.en.force = _1Force;
this.en.antall = _1Antall_;
this.to = new Object;
this.to.navn = _2Navn;
this.to.force = _2Force;
this.to.antall = _2Antall;
this.health = 1000;
console.info(this.en);
this.pushFakemon = function() {
fakemonSamling.push(this);
}
this.pushFakemon();
}
const fakemon1 = new Fakemon("BatCat", "Flying", [10, 50], ["batFront.png", "batBack.png"], "Blood Suck", [25, 38, 60], 10, "Wing Slap", [10, 17, 25], 20);
const fakemon2 = new Fakemon("Muffin Time", "Normal", [15, 45], ["cupcakeFront.png", "cupcakeBack.png"], "Frosting cover", [10, 17, 25], 20, "Cake stomp", [40, 50, 60], 5);
Это код для выдачи трех покемонов каждому игроку.
for (let i = 0; i < 3; i++) {
var temp1 = new Object;
player1.push(Object.assign(temp1, randomFakemon()));
var temp2 = new Object;
player2.push(Object.assign(temp2, randomFakemon()));
}
Нет, проблема не в вашем конструкторе. Скорее дело в том, что randomFakemon() может возвращать фейкмон такой же несколько раз, вместо того, чтобы каждый раз создавать новый.
Кстати, использование new Object довольно однообразно, лучше использовать литералы объектов
Еще одна мысль ... в случае, если OP не может выразить намерение функции, особенно функции конструктора, возможно, с 3 или 4 параметрами, OP может подумать об использовании от 1 до 3 объектов конфигурации в качестве параметров. Для варианта использования OP тем более, что все аргументы просто назначаются как общедоступные свойства... подумайте о Object.assign(this, configA, { en: ...configB, to: ...configC });
... обзор кода, часть 2 ... реализация метода pushFakemon (либо собственного, либо прототипа) необязательна. Вместо этого отправьте только что созданный экземпляр напрямую.
3/4 ... также, и Берги уже касался темы, в случае, если randomFakemon() возвращает случайным образом Рекомендации из коллекции фейкмонов под названием fakemonSamling, Object.assign не защищает эти ссылки от дальнейших мутаций. С другой стороны, назначение истинного экземпляра Fakemon через Object.assign другому (даже пустому) объекту делает последний не экземпляром Fakemon. Он останется поверхностной копией, объектом, который содержит ссылки на более глубокие вложенные свойства своего Fakemon исходного объекта экземпляра.
4/4 ... И использование structuredClone также не решает проблему, поскольку можно потерять так или иначе необязательный метод pushFakemon. Таким образом возникает вопрос... Для чего же нужен конструктор. Здесь нет ни прототипных методов, ни подклассов. Мое последнее предложение... "Используйте фабрику фейкмонов".
Использование StructuredClone сработало, спасибо :)
structuredClone завершится ошибкой (вызовет исключение) с экземплярами исходной функции конструктора Fakemone OP из-за реализации метода pushFakemon.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


По-видимому, у ОП были проблемы с двумя вариантами дизайна.
player1.push(Object.assign(temp1, randomFakemon())); ... выбирает случайный истинный экземпляр Fakemon из коллекции фейкмонов ОП.
Object.assign рассматривает источник как обычный объект. Он присваивает только перечисляемые собственные свойства исходного объекта целевому объекту. Таким образом, вложенные свойства непримитивный по-прежнему будут содержать ссылки на свои источники. Целевой объект также не изменит свой тип. Это не будет вдруг экземпляром Fakemon.
Только что описанную проблему можно решить с помощью надежной собственной реализации функции clone или, если она доступна, с помощью структурированный клон.
При подходе клонирования конструктор, хотя и создает собственные типы, но не расширяет/подкласс и не реализует прототипные методы, становится бесполезным.
Единственный (собственный) метод из примера кода OP в любом случае необязателен, поэтому предлагаемое решение — это рефакторинг кода по отношению к функции Фабрика фейкмонов и использование clone функциональность.
function createFakemon(base, attack1, attack2) {
const fakemon = Object.assign({
health: 1000,
}, base, {
en: { ...attack1 },
to: { ...attack2 },
});
fakemonCollection.push(fakemon);
return fakemon;
};
const fakemonCollection = []; // Dansk: fakemon samling.
function getRandomFakemon() {
return fakemonCollection[
Math.floor(Math.random() * fakemonCollection.length)
];
}
const cloneDataStructure = (
('function' === typeof structuredClone) && structuredClone ||
(value => JSON.parse(JSON.stringify(value)))
);
const fakemon1 = createFakemon({
navn: 'BatCat',
type: 'Flying',
attackPower: [10, 50],
sources: ['batFront.png', 'batBack.png'],
}, {
navn: 'Blood Suck',
force: [25, 38, 60],
antall: 10,
}, {
navn: 'Wing Slap',
force: [10, 17, 25],
antall: 20,
});
const fakemon2 = createFakemon({
navn: 'Muffin Time',
type: 'Normal',
attackPower: [15, 45],
sources: ['cupcakeFront.png', 'cupcakeBack.png'],
}, {
navn: 'Frosting cover',
force: [10, 17, 25],
antall: 20,
}, {
navn: 'Cake stomp',
force: [40, 50, 60],
antall: 5,
});
// create a(ny) player's fakemon as true clone
// of a randomly picked `fakemonCollection` item.
const playerFakemon = cloneDataStructure(
getRandomFakemon()
);
// change a single attack value.
playerFakemon.en.navn = 'Foo Bar';
/*
Thus instead of ...
player1.push(Object.assign(temp1, randomFakemon()));
... one now would do ...
player1.push(cloneDataStructure(getRandomFakemon()));
*/
console.info({
// no mutation at any of the collection's fakemon items.
fakemonCollection,
// single different value for `playerFakemon.en.navn`.
playerFakemon,
});.as-console-wrapper { min-height: 100%!important; top: 0; }Это лучший подход, чем мой, но изменение Object.assign на StructuredClone помогло.
@KristianGjertsen ... «изменение Object.assign на StructuredClone помогло» ... Сомневаюсь. Определенно были и другие изменения. Вызов structuredClone завершится ошибкой (вызовет исключение) с экземплярами исходной функции конструктора Fakemone OP из-за реализации метода pushFakemon.
Можете ли вы поделиться кодом, который вы используете, когда «пытаетесь что-то отредактировать в любом из объектов атаки»?