使用相同的覆盖变量的 JavaScript 对象

javascript objects using the same overwritten variable

本文关键字:变量 JavaScript 对象 覆盖      更新时间:2023-09-26

我有一个正在使用的javascript对象。我有一个我想保持原样的顶点数组(称为顶点的变量)。在对象中,我有一个setScalar()方法,它将采用这个顶点矩阵并应用一个标量(jus一个简单的for循环乘以每个值)。当我创建一个新对象时,我应用了我的标量,但是当我创建一个新对象时,我没有引用原始顶点数组,它似乎将标量应用于之前对象中使用的缩放顶点。

下面是 verts 数组:

var verts = [
            // Front face
            -1.0, -1.0,  1.0,
             1.0, -1.0,  1.0,
             1.0,  1.0,  1.0,
            -1.0,  1.0,  1.0,
            // Back face
            -1.0, -1.0, -1.0,
            -1.0,  1.0, -1.0,
             1.0,  1.0, -1.0,
             1.0, -1.0, -1.0,
            // Top face
            -1.0,  1.0, -1.0,
            -1.0,  1.0,  1.0,
             1.0,  1.0,  1.0,
             1.0,  1.0, -1.0,
            // Bottom face
            -1.0, -1.0, -1.0,
             1.0, -1.0, -1.0,
             1.0, -1.0,  1.0,
            -1.0, -1.0,  1.0,
            // Right face
             1.0, -1.0, -1.0,
             1.0,  1.0, -1.0,
             1.0,  1.0,  1.0,
             1.0, -1.0,  1.0,
            // Left face
            -1.0, -1.0, -1.0,
            -1.0, -1.0,  1.0,
            -1.0,  1.0,  1.0,
            -1.0,  1.0, -1.0
        ];

这是我在对象中设置它的方式。

//Cube object
    function Cube(name, vertices, cubeVertInd, color, scale, positionX, positionY, positionZ) 
    {
        this.name = name;
        this.vertices = vertices;
        this.cubeVertexIndices = cubeVertInd;
        this.positionX = positionX;
        this.positionY = positionY;
        this.positionZ = positionZ;
        this.setColor(color);
        this.setScale(vertices, scale);
    }

这是设置缩放方法

Cube.prototype.setScale = function(vertices, scale) 
    {
        var length = vertices.length;
        for( var i = 0; i < length; i++)
        {
            vertices[i] *= scale; 
        }
    }

我知道这就是发生的事情,因为当我在 webgl 中使用它时,我会根据我制作第一个对象的大小获得不同的大小。如果我将对象设置为缩放 2,则将下一个对象设置为缩放 0.1,即使原始顶点都是 1,我也得到 0.2 作为第二个对象缩放。这表明正在使用我在第一个对象中设置的比例,而不是顶点

你必须

克隆你的vertices数组,否则它总是对原始vert数组的引用。

试试这个:

//Cube object
    function Cube(name, vertices, cubeVertInd, color, scale, positionX, positionY, positionZ) 
    {
        // make a copy of the vertices
        vertices = vertices.slice();
        this.name = name;
        this.vertices = vertices;
        this.cubeVertexIndices = cubeVertInd;
        this.positionX = positionX;
        this.positionY = positionY;
        this.positionZ = positionZ;
        this.setColor(color);
        this.setScale(vertices, scale);
    }

如果仅将setScale()用于此目的,则可以使用Array.prototype.map()方法并删除函数setScale()

在这种情况下,将创建、缩放另一个新对象并将其分配给this.vertices

function Cube(name, vertices, cubeVertInd, color, scale, positionX, positionY, positionZ) 
    {
        this.name = name;
        this.vertices = vertices.map(function(value){
                             return value*scale;
                        });
        this.cubeVertexIndices = cubeVertInd;
        this.positionX = positionX;
        this.positionY = positionY;
        this.positionZ = positionZ;
        this.setColor(color);
    }
这是

a similar thing happens when i set the positions is there anyway I can make these unique to each iteration of the object?的回答

此问题的通用解决方案是拥有一个克隆函数,该函数可以返回对象的克隆(而不是引用)。因此,假设如果您有一个包含 {verts: [1,2,3..], positionX: 5, ...} 等的基本对象,则创建新对象时要执行的操作是newObj = clone(baseObj), then newObj.setScale(-1)

以及所述克隆函数的一个实现:

var clone = function(obj,visited){
    if (obj === null || typeof(obj) !== "object"){ // primitives and functions
        return obj;
    }
    visited = visited || [];
    if (visited.indexOf(obj)===-1){ // enable cloning objects with circular references at cost of linear search;
        visited.push(obj);
        if (obj instanceof RegExp){
            return new RegExp(obj);
        } else if (obj instanceof Date){
            return new Date(obj);
        } else if (Array.isArray(obj)){ // the [[Class]] of arrays can only be set by using Array constructor or [];
            var newObj = [];
        } else if (obj.constructor !== undefined){
            newObj = Object.create(obj.constructor.prototype);
        } else {
            throw new TypeError("How to clone object: "+obj+" is undefined.", obj);
        }
    } else { // if object already seen/ circular reference; just return reference to it
        return obj;
    }
    for(var key in obj) { // recursive call itself;
        if(obj.hasOwnProperty(key)) {
            newObj[key] = clone(obj[key],visited);
        }
    }
    return newObj;
};