Как сделать глубокое клонирование массива

Рейтинг: 0Ответов: 2Опубликовано: 11.06.2023

Мне нужно скопировать массив так, чтобы копия и оригинал вообще не были связаны и копия была полностью идентична оригиналу. В массиве миксер и мэш от three.js. clone() и slice() не копируют полностью, у меня всё равно происходит взаимодействие с оригиналом.

Создание оригинала:

function loadAnimatedModel(path, s, name)
{
    var loader = new GLTFLoader();
    loader.load(path, function (gltf) {
        var mesh = gltf.scene.children[0];
        var clip = gltf.animations[0];
        mixer = new THREE.AnimationMixer(mesh);

        // установка параметров анимации (скорость воспроизведения и стартовый кадр)
        mixer.clipAction(clip, mesh).setDuration(1).startAt(0).play();

        console.log(gltf.animations);

        mesh.scale.set(s, s, s);
        
        mesh.castShadow = true;
        mesh.receiveShadow = true;

        var t = [mesh, mixer];
        models.set(name, t);
   });
}

models это Map. Попытка клонирования:

function addAnimMesh(name)
{
    var n = [];
    n = models.get(name).slice(); //здесь нужно клонировать, slice не даёт полное копирование

    var mesh = n[0];
    var mixer = n[1];

    mesh.position.x = getRandomNumber(0, N);
    mesh.position.z = getRandomNumber(0, N);
    mesh.position.y = getRandomNumber(80, 100);
    mesh.rotation.y = Math.PI / getRandomNumber(1, 360);
    mesh.userData.ID = ID;

    mixersOnScene.push(mixer);
    modelsOnScene.push(mesh);
    scene.add(mesh);

    ID++;
}

Ответы

▲ 1

Вы можете воспользоваться функцией structuredClone. Она выполняет глубокое копирование объектов в js. Массивы тоже объекты так что подойдёт для их копирования https://developer.mozilla.org/en-US/docs/Web/API/structuredClone

таким образом ваш код для копирования будет выглядеть примерно так

function addAnimMesh(name)
{
    const n = structuredClone(models.get(name)); // здесь используем глубокое копирование

    var mesh = n[0];
    var mixer = n[1];

    mesh.position.x = getRandomNumber(0, N);
    mesh.position.z = getRandomNumber(0, N);
    mesh.position.y = getRandomNumber(80, 100);
    mesh.rotation.y = Math.PI / getRandomNumber(1, 360);
    mesh.userData.ID = ID;

    mixersOnScene.push(mixer);
    modelsOnScene.push(mesh);
    scene.add(mesh);

    ID++;
}
▲ 0

Я решила не клонировать, а создавать заново новый объект, так что addAnimMesh я убрала, а loadAnimatedModel поменяла и поставила её на вызов от кнопки:

function loadAnimatedModel(path, s)
{
    var loader = new GLTFLoader();
    loader.load(path, function (gltf) {
        var mesh = gltf.scene.children[0];
        var clip = gltf.animations[0];
        mixer = new THREE.AnimationMixer(mesh);

        // установка параметров анимации (скорость воспроизведения и стартовый кадр)
        mixer.clipAction(clip, mesh).setDuration(1).startAt(0).play();

        console.log(gltf.animations);

        mesh.scale.set(s, s, s);

        mesh.position.y = getRandomNumber(80, 100);
        mesh.position.x = getRandomNumber(0, N);
        mesh.position.z = getRandomNumber(0, N);
        mesh.rotation.y = Math.PI / getRandomNumber(1, 360);
        
        mesh.castShadow = true;
        mesh.receiveShadow = true;

        mesh.userData.ID = ID;

        scene.add(mesh);
        modelsOnScene.push(mesh);
        mixersOnScene.push(mixer);
        
        ID++;
    });
}