为什么更改参数副本会改变参数?

时间:2013-08-15 02:02:32

标签: javascript arrays function object

我有一个函数来生成一个随机地图,给出了许多图块,一个起始图,以及要使用的网格类型(三角形,方形,十六进制)。它返回一个tile数组map,其中包含两个额外的属性:seed,使用的起始地图和adjy *。最初,map设置为等于seed。出于某种原因,map.seed不等于seed参数。相反,map.seed等于map。我发现seed已被map.push()更改。我尝试"use strict";,使用arguments[1]代替seed,并移动语句map.seed=seed;(这些没有任何效果)。代码在jsHint中没有任何错误,并且不会在控制台中抛出任何错误。

* adjy是邻接的缩写,三角形为0,正方形为1,六边形为2。

我准备了一个jsFiddle,代码也在下面:

console.clear();
var canvas=document.getElementById('canvas'),
    ctx=canvas.getContext('2d');
canvas.width=window.innerWidth;
canvas.height=window.innerHeight;
ctx.translate(canvas.width/2,canvas.height/2);
Array.prototype.equals=function(a){//array1==array2 is broken, create substitute
    return this.length==a.length&&this.every(
        function(e,i){
            return e instanceof Array?
                a[i]instanceof Array&&e.equals(a[i]):
                !(a[i]instanceof Array)&&e==a[i];
        }
    );
};
Array.prototype.includes=function(n){
    return this.some(
        function(e){
            return n instanceof Array?
                n.equals(e):
                n==e;
        }
    );
};
function Map(tiles,seed,adjy){
    if(!arguments.length)return [];
    if(arguments.length<2)
        if(tiles)seed=[[0,0]];
        else return [];
    if(arguments.length<3)
        if(tiles<seed.length)return adjy;//returns undefined
        else adjy=1;
    var map=seed,cdd=[],nos=//candidate tiles,Neighbors Of Square (or tile)
        [[[0,1,-1],[1,0,0]],//triangle
         [[0,1,0,-1],[1,0,-1,0]],//square
         [[0,1,1,0,-1,-1],[1,0,-1,-1,0,1]]][adjy];//hex
    function addAdj(p){//adds adjacent tiles to candidates (cdd)
        var c;
        for(var i=0;i<nos[0].length;i++)
            if(!cdd.includes(
               c=[p[0]+nos[0][i],p[1]+nos[1][i]])&&
               !map.includes(c))
                  cdd.push(c);
    }
    function pickR(){//pick a random tile
        var p=cdd.splice(
            ~~(Math.random()*cdd.length),1)[0];//~~ is the same as floor
        addAdj(p);
        map.push(p);//the line where the problem happens
    }
    seed.forEach(addAdj);
    while(tiles>map.length)pickR();
    map.seed=seed;
    map.adjy=adjy;
    return map;
}
function drawMap(map){
    if(!map.hasOwnProperty('adjy'))return void 0;
    function draw0(c){
        var x=c[0],y=c[1];
        ctx.beginPath();
        switch((x+y)%2){
            case 0:
                x*=5;y*=7;
                ctx.moveTo(x,y);
                ctx.lineTo(x-5,y+7);
                ctx.lineTo(x+5,y+7);
                break;
            default:
                x*=5;y*=7;
                ctx.moveTo(x,y+7);
                ctx.lineTo(x+5,y);
                ctx.lineTo(x-5,y);
        }
        ctx.closePath();
        ctx.fill();
    }
    function draw1(c){
        var x=c[0],y=c[1];
        ctx.fillRect(x*10,y*10,10,10);
    }
    function draw2(c){
        var x=c[0]*7,y=c[1];
        x+=y*3.5;
        y*=7.5;
        ctx.beginPath();
        ctx.moveTo(x,y);
        ctx.lineTo(x,y+5);
        ctx.lineTo(x+3.5,y+7.5);
        ctx.lineTo(x+7,y+5);
        ctx.lineTo(x+7,y);
        ctx.lineTo(x+3.5,y-2.5);
        ctx.closePath();
        ctx.fill();
    }
    switch(map.adjy){
        case 0:
            map.forEach(draw0);
            break;
        case 1:
            map.forEach(draw1);
            break;
        default:
            map.forEach(draw2);
    }
}
var board=new Map(37*6,[[-5,0],[5,0]],2);
console.log(board.seed);
drawMap(board);

我已经包含了所有代码,以防seedmap发生时更新{{1}},尽管我的开发人员控制台测试表明了这一点。

1 个答案:

答案 0 :(得分:3)

分配数组或对象不会 复制它。

var map = seed;

使两个变量引用相同的数组。因此,您通过一个变量对阵列所做的任何更改都将通过另一个变量看到。如果您需要副本,则必须明确地执行此操作:

var map = seed.slice(0);
相关问题