Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/444.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript-为什么Array.prototype.fill实际上填充了一个“;指针;填充类似';新对象()';_Javascript_Arrays - Fatal编程技术网

JavaScript-为什么Array.prototype.fill实际上填充了一个“;指针;填充类似';新对象()';

JavaScript-为什么Array.prototype.fill实际上填充了一个“;指针;填充类似';新对象()';,javascript,arrays,Javascript,Arrays,我试图使用Array.prototype.fill方法创建一个nxn2D数组,但代码有缺陷,我最终发现里面的所有数组实际上都是指向同一数组的“指针” 样本: var matrix = new Array(10).fill(new Array(10), 0); 我认为从概念上来说,这可以创建一个10 x 10的2D阵列。但是,如果我为矩阵[0][0]赋值: matrix[0][0] = 1; 结果实际上是: matrix[0][0] === 1; matrix[1][0] === 1; mat

我试图使用Array.prototype.fill方法创建一个nxn2D数组,但代码有缺陷,我最终发现里面的所有数组实际上都是指向同一数组的“指针”

样本:

var matrix = new Array(10).fill(new Array(10), 0);
我认为从概念上来说,这可以创建一个10 x 10的2D阵列。但是,如果我为矩阵[0][0]赋值:

matrix[0][0] = 1;
结果实际上是:

matrix[0][0] === 1;
matrix[1][0] === 1;
matrix[2][0] === 1;
matrix[3][0] === 1;
matrix[4][0] === 1;
matrix[5][0] === 1;
matrix[6][0] === 1;
matrix[7][0] === 1;
matrix[8][0] === 1;
matrix[9][0] === 1;
每次我试图给矩阵中的任何一个位置赋值时,其他子数组中的所有对应位置也会改变

我想知道为什么会这样


有人能回答这个令人挠头的问题吗?

这是因为当您调用
array.fill()
时,您只传递一个
新数组()
值。这就是用单个值填充数组的要点

如果要获取现有数组并为每个索引分配新实例,可以使用
.map()

要以嵌套方式执行此操作,您可以映射两次

// the callback function's item, index and array properties are optional
var matrix = new Array(10).fill().map(function(item, index, arr) {
    return new Array(10).fill(0);
});
如果您使用的是ES6,则可以进一步简化为一行程序

var matrix = new Array(10).fill().map(() => new Array(10).fill(0));
之所以
.map()
有效,是因为它为数组中的每个项调用提供的回调函数

<空白> <代码> .FILE()/<代码> <代码> > MAP()/代码>是用值填充数组。默认情况下,为每个项目指定大小的新数组都有
未定义的
.fill()
将临时填充数组,以便对其进行映射

我想知道为什么会这样

Array#fill
将给定的值作为第一个参数,并用该值的副本填充数组

你给它的值是一个数组的引用,所以它给你的是一个数组,里面充满了引用的副本。不是数组的副本,而是引用的副本

例如,其行为方式与此代码的原因完全相同:

var a = new Array(10);
var b = a;
…留给我们的
a
b
都引用了相同的数组(都包含相同的值;引用了我们创建的单个数组)

让我们来看看Unicode的艺术:

此代码运行后:

var a = new Array(10);
var b = a;
我们已经记住了这一点(减去一些不相关的细节):

你最终得到的是

+−−−−−−−−−−−−−−−+ matrix:Ref89895−−−>| array | +−−−−−−−−−−−−−−−+ | length: 10 | | 0: Ref55462 |--\ | 1: Ref55462 |--\\ | 2: Ref55462 |--\\\ | 3: Ref55462 |--\\\\ +−−−−−−−−−−−−−−−+ | 4: Ref55462 |---+++++->| array | | 5: Ref55462 |--///// +−−−−−−−−−−−−−−−+ | 6: Ref55462 |--//// | length: 10 | | 7: Ref55462 |--/// +−−−−−−−−−−−−−−−+ | 8: Ref55462 |--// | 9: Ref55462 |--/ +−−−−−−−−−−−−−−−+ 或在ES2015中:

// Array.from
let matrix = Array.from({length: 10}, () => new Array(10).fill(0));

// fill and map
let matrix = new Array(10).fill().map(() => new Array(10).fill(0));

在您的特定情况下,由于
Array.prototype.fill()
fills使用单个值,并且在JS对象(例如数组)中是引用类型,因此所有索引都包含对第一个索引的引用。在JS中,创建ND数组可能不像看上去那么简单,因为数组将通过引用进行复制。对于一般用途的
arrayND
函数,您需要一个数组克隆实用程序函数。让我们看看

Array.prototype.clone=function(){
返回此.map(e=>Array.isArray(e)?e.clone():e);
};
函数arrayND(…n){
返回n.reduceRight((p,c)=>c=(新数组(c)).fill().map(e=>Array.isArray(p)→p.clone():p));
}
var array3D=arrayND(5,5,5,“五”);
阵列3d[0][1][2]=5;

控制台日志(array3D)使用递归,您可以生成更多维度;)

const range=r=>Array(r).fill().map((v,i)=>i);
常量range2d=(x,y)=>范围(x).map(i=>范围(y));
常数范围矩阵=(…范围)=>(函数范围(范围){
返回ranges.length?ranger(range(ranges.pop()).map(i=>range)):range
})(range(ranges.pop());
设arr10x10=range2d(10,10);
设arr3x5=range2d(3,2);
设arr4x3=范围矩阵(4,3);
设arr4x3x2=范围矩阵(4,3,2);
设arr4x3x2x5=范围矩阵(4,3,2,5);
控制台日志(arr10x10);
控制台日志(arr3x5);
控制台日志(arr4x3);
控制台日志(arr4x3x2);

控制台日志(arr4x3x2x5)@Soviut:是的,很好,而且更干净。顺便说一句,你错过了一个,我把它添加到了你的答案中。这太棒了!非常感谢您为绘制图表所做的努力,这对您帮助很大!我认为这个错误是因为我对C++更熟悉,而不是非常熟悉JavaScript。(是的,C++确实有一些JavaScript没有的自动对象复制语义,所以取决于我们假设的数组γ填充> /Copy>在C++中是如何写的,它可能只复制引用,或者它可能复制对象。)是的,我完全同意它很棘手(或者我只是不太熟悉它)。谢谢你的回答!属于
var matrix = new Array(10).fill(new Array(10), 0);
+−−−−−−−−−−−−−−−+ matrix:Ref89895−−−>| array | +−−−−−−−−−−−−−−−+ | length: 10 | | 0: Ref55462 |--\ | 1: Ref55462 |--\\ | 2: Ref55462 |--\\\ | 3: Ref55462 |--\\\\ +−−−−−−−−−−−−−−−+ | 4: Ref55462 |---+++++->| array | | 5: Ref55462 |--///// +−−−−−−−−−−−−−−−+ | 6: Ref55462 |--//// | length: 10 | | 7: Ref55462 |--/// +−−−−−−−−−−−−−−−+ | 8: Ref55462 |--// | 9: Ref55462 |--/ +−−−−−−−−−−−−−−−+
// Array.from
var matrix = Array.from({length: 10}, function() {
    return new Array(10).fill(0);
});

// fill and map
var matrix = new Array(10).fill().map(function() {
    return new Array(10).fill(0);
});
// Array.from
let matrix = Array.from({length: 10}, () => new Array(10).fill(0));

// fill and map
let matrix = new Array(10).fill().map(() => new Array(10).fill(0));