JavaScript - 为什么 Array.prototype.fill 实际上填充“指针"?填充诸如“new Object()"之类的对象时的对象 [英] JavaScript - why Array.prototype.fill actually fills a "pointer" of object when filling anything like 'new Object()'

查看:24
本文介绍了JavaScript - 为什么 Array.prototype.fill 实际上填充“指针"?填充诸如“new Object()"之类的对象时的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用 Array.prototype.fill 方法来创建 anxn 2D 数组 但代码有问题,我最终发现里面的所有数组实际上都是 指针"到相同的数组.

示例:

var matrix = new Array(10).fill(new Array(10), 0);

我从概念上认为这可以创建一个 10 x 10 的二维数组.但是,如果我为矩阵 [0][0] 赋值:

矩阵[0][0] = 1;

结果实际上是:

matrix[0][0] === 1;矩阵[1][0] === 1;矩阵[2][0] === 1;矩阵[3][0] === 1;矩阵[4][0] === 1;矩阵[5][0] === 1;矩阵[6][0] === 1;矩阵[7][0] === 1;矩阵[8][0] === 1;矩阵[9][0] === 1;

并且每次如果我尝试为矩阵中的任何位置赋值,其他子数组中的所有对应位置也会发生变化.

我想知道为什么会这样?

谁能回答这个令人头疼的问题?

解决方案

我想知道为什么会这样?

Array#fill 将您提供的 value 作为第一个参数,并用该 value 的副本填充数组.>

您提供给它的值是对数组的引用,因此自然而然它返回的是一个充满该引用副本的数组.不是数组的副本,而是引用的副本.

例如,出于与此代码完全相同的原因,它会以这种方式运行:

var a = new Array(10);var b = a;

...给我们留下了 ab 都引用同一个数组(都包含相同的;对我们创建的单个数组).

让我们对它进行一些 Unicode 艺术:

此代码运行后:

var a = new Array(10);var b = a;

我们在内存中有这个(减去一些不相关的细节):

<前>a:Ref89895−−−+||+−−−−−−−−−−−−−−−−−++−−−−−−>|数组 ||+−−−−−−−−−−−−−−−−−+||长度:10 |b:Ref89895−−−+ +−−−−−−−−−−−−−−−−+

ab 包含一个引用,我在此处显示为 Ref89895,尽管我们从未看到实际值.这是b = a 复制的内容,而不是数组本身.

同样,当你这样做时:

var matrix = new Array(10).fill(new Array(10), 0);

你最终得到

<前>+−−−−−−−−−−−−−−−−−+矩阵:Ref89895−−−>|数组 |+−−−−−−−−−−−−−−−−−+|长度:10 ||0:Ref55462 |--\|1:Ref55462 |--\\|2: Ref55462 |--\\\|3: Ref55462 |--\\\\ +−−−−−−−−−−−−−−−+|4:Ref55462 |---++++++->|数组 ||5: Ref55462 |--/////+−−−−−−−−−−−−−−−+|6:Ref55462 |--////|长度:10 ||7: Ref55462 |--///+−−−−−−−−−−−−−−−+|8: Ref55462 |--//|9:Ref55462 |--/+−−−−−−−−−−−−−−−−−+

要创建一个 10 位数组,其中 10 位中的每一个本身都是 0 的 10 位数组,我可能会使用 Array.fromfill 使用 map:

//Array.fromvar matrix = Array.from({length: 10}, function() {返回新数组(10).填充(0);});//填充和映射var matrix = new Array(10).fill().map(function() {返回新数组(10).填充(0);});

或在 ES2015 中:

//Array.from让矩阵 = Array.from({length: 10}, () => new Array(10).fill(0));//填充和映射让矩阵 = new Array(10).fill().map(() => new Array(10).fill(0));

I was trying to used Array.prototype.fill method to create a n x n 2D array but the code was buggy and I eventually found out all arrays inside are actually "pointers" to the same array.

Sample:

var matrix = new Array(10).fill(new Array(10), 0);

I thought conceptually this could create a 10 x 10 2D array. However if I assign value to matrix[0][0]:

matrix[0][0] = 1;

The result will actually be:

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;

and every time if I tried to assign value to any of the position in the matrix, all corresponding positions in other sub-arrays will change as well.

I am wondering why it's happening?

Can anyone please answer this head-scratching question?

解决方案

I am wondering why it's happening?

Array#fill takes the value you give it as the first argument, and fills the array with copies of that value.

The value you're giving it is a reference to an array, so naturally what it gives you back is an array filled with copies of that reference. Not copies of the array, copies of the reference.

E.g., it behaves this way for exactly the same reason this code:

var a = new Array(10);
var b = a;

...leaves us with a and b both referring to the same array (both containing the same value; a reference to the single array we've created).

Let's throw some Unicode-art at it:

After this code runs:

var a = new Array(10);
var b = a;

we have this in memory (minus a few irrelevant details):

a:Ref89895−−−+
             |
             |      +−−−−−−−−−−−−−−−+
             +−−−−−>|     array     |
             |      +−−−−−−−−−−−−−−−+
             |      | length: 10    |
b:Ref89895−−−+      +−−−−−−−−−−−−−−−+

a and b contain a reference, which I've shown here as Ref89895 although we never see the actual value. That's what's copied by b = a, not the array itself.

Similarly, when you do:

var matrix = new Array(10).fill(new Array(10), 0);

you end up with

                   +−−−−−−−−−−−−−−−+
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   |--/
                   +−−−−−−−−−−−−−−−+

To create a 10-place array where each of the 10 places is itself a 10-place array of 0, I'd probably use either Array.from or fill with map:

// 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);
});

or in 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));

这篇关于JavaScript - 为什么 Array.prototype.fill 实际上填充“指针"?填充诸如“new Object()"之类的对象时的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆