Массив, переданный функции-конструктору в Javascript, не изменяется при вызове содержимого

#javascript

#javascript

Вопрос:

У меня есть следующий модуль, который импортируется в контексте вызова:

 function Controls(elem, viewMatrix) {

    var xD, yD;

    this.ppdX = 10;
    this.ppdY = 10;

    this.state = 0;
    var dx = 0;
    var dy = 0;

    function getXY(evt) {
        var x = evt.pageX - elem.offsetLeft;
        var y = evt.pageY - elem.offsetTop;
        return [x, y];
    }

    function onDown(evt) {
        this.state = 1;
        [xD, yD] = getXY(evt);
    }

    function onUp(evt) {
        this.state = 0;
        [dx, dy] = [0, 0];
    }

    function onMove(evt) {
        if (!this.state) return;
        var [x, y] = getXY(evt);
        [dx, dy] = [x - xD, y - yD];
    }

    this.updateView = function () {
        viewMatrix = Mtx.mult(viewMatrix, Mtx.rotY(-Mtx.DtoR * dx / this.ppdX));
        viewMatrix = Mtx.mult(viewMatrix, Mtx.rotX(-Mtx.DtoR * dy / this.ppdY));
    }

    elem.addEventListener("mousedown", onDown.bind(this));
    elem.addEventListener("mouseup", onUp.bind(this));
    elem.addEventListener("mousemove", onMove.bind(this));
}

export default Controls;
  

Вызывающий контекст выглядит следующим образом:

 import Controls from './js/controls.module.js';
...

viewMatrix = Mtx.makeIdent(4, 4);
controls = new Controls(renderer.domElement, viewMatrix);
...

function animate() {

    requestAnimationFrame(animate);

    if (controls.state) {
        controls.updateView();
        ...
        console.log(viewMatrix);
    }

...

}
  

где viewMatrix — это массив 4×4, определенный следующим образом:

 viewMatrix = [[...],[...],[...],[...]];
  

Я вижу, что, хотя viewMatrix изменяется внутри вызова UpdateView(), он не меняется в контексте вызова. Предполагается, что массивы передаются по ссылке, разве это не так в данном случае?

Я знаю, что могу вернуть матрицу из UpdateView() в вызывающий контекст и перезаписать viewMatrix там, но я хотел бы знать, почему она не обновляется, и, может быть, есть другой способ написать этот код, чтобы он обновлялся сам по себе?

РЕДАКТИРОВАТЬ код для умножения:

     mult(A, B) {
        var C = [];
        var Ar = A.length, Ac = A[0].length;
        var Br = B.length, Bc = B[0].length;
        if (Ac != Br) {
            console.log("mult(): dimentions mismatch");
            return C;
        }
        for (let ar = 0; ar < Ar; ar  ) {
            C[ar] = [];
            for (let bc = 0; bc < Bc; bc  ) {
                C[ar][bc] = 0;
                for (let ac = 0; ac < Ac; ac  ) {
                    C[ar][bc]  = A[ar][ac] * B[ac][bc]
                }
            }
        }
        return C;
    },
  

Комментарии:

1. Возможно, нам потребуется посмотреть, как mult() это реализовано, но в операторах viewMatrix = Mtx.mult(...) похоже, что значение viewMatrix просто перезаписывается, что означало бы, что ваш исходный матричный объект не будет затронут операторами. (Опять же, это зависит от того, как mult() реализовано.)

2. Вы могли бы сделать что-то вроде const temp = Mtx.mult(...) , а затем скопировать элементы temp в viewMatrix . (Это отдельная проблема, но имейте в виду, что такого рода повторяющиеся изменения матрицы могут привести к накоплению числовой ошибки, которая может стать заметной со временем.)

3. Просто используйте this.viewMatrix in updateView и выполняйте console.log(controls.viewMatrix) . Не пытайтесь заставить элементы управления манипулировать глобальным viewMatrix , это должно быть свойство экземпляра.

4. @user1481126: Очевидно, что вы можете делать все, что хотите, но могут быть аргументы (например, основанные на принципе «разделения задач» или шаблоне MVC), чтобы не делать матрицу свойством объекта «controls». Другим вариантом (который, вероятно, был бы лучше, чем мое предыдущее предложение) было бы сделать матрицу представления (и любые другие подобные данные) свойством объекта, на который объект ‘controls’ хранит ссылку. Тогда вы могли бы перезаписать матрицу, как вы делаете в настоящее время, сохраняя при этом возможность доступа к ней из другого места, независимо от объекта ‘controls’.

5. @scg: спасибо, ваше последнее предложение решило мою проблему, поскольку матрица просмотра является свойством объекта камеры, я могу передать ее элементам управления и работать оттуда. Я приму это как ответ, если вы его сделаете.