Изменчивость массива и сценарий переменной ссылки неясны - PullRequest
1 голос
/ 14 июня 2019

Итак, я понимаю, что массивы в JavaScript являются изменяемыми.

Это означает, что если я создаю массив a и массив b = a, то, если я изменяю массив a, модификация также виднав массиве b.

Однако в следующем сценарии я не понимаю, почему b теряет «ссылку» на массив a.

var a = [1,2,3];
var b = a;

console.log('a =', a);
console.log('b =', b);

a[0] = 4;
console.log('a =', a);
console.log('b =', b);

a = [5,5];
console.log('a =', a);
console.log('b =', b);

Ответы [ 3 ]

6 голосов
/ 14 июня 2019

a и b не являются ссылками друг на друга - они являются ссылками на тот же массив .

Когда вы делаете a = [5,5], вы устанавливаете a в полностью новый массив, в то время как b по-прежнему ссылается на старый.

3 голосов
/ 14 июня 2019

Может быть полезно думать о «переменных» в отличие от «значений».

a и b в вашем примере являются переменными.

[1,2,3], 4 и [5,5] в вашем примере являются значениями.

Несколько переменных могут ссылаться на одно и то же значение. Если это значение изменяется (мутирует), то все переменные, ссылающиеся на это значение, будут возвращать измененное значение. В приведенном ниже примере ссылки на a и b устанавливаются на одно и то же значение, затем вносятся изменения в это значение с помощью ссылки из a и ссылки из b. В результате на измененное значение все еще ссылаются обе переменные.

var a = [1,2,3]; // a references the value [1,2,3]
var b = a; // b references the value [1,2,3]
a[0] = 4; // [1,2,3] changed to [4,2,3]
b[1] = 5; // [1,2,3] changed to [4,5,3]
console.log(a); // [4,5,3]
console.log(b); // [4,5,3]

Однако вы можете изменить значение, на которое вообще ссылается переменная, «присвоив» его новому значению. Это не изменит (изменит) само значение и не изменит ссылку на любую другую переменную, которая ссылается на то же значение. В приведенном ниже примере ссылки на a и b устанавливаются на одно и то же значение, а затем изменяется на a на новое значение. В результате переменные теперь ссылаются на разные значения.

var a = [1,2,3]; // a references the value [1,2,3]
var b = a; // b references the value [1,2,3]
a = [5,5]; // a reference assigned to new value [5,5]
console.log(a); // [5,5]
console.log(b); // [1,2,3]
2 голосов
/ 14 июня 2019

Давайте посмотрим в память компьютера¹. Прежде всего, создаются две переменные, a и b. В основном это области памяти, которые заполняются значением:

 location | name²      |  value
 -------------------------------------
  1       |  a         |  undefined
  2       |  b         |  undefined

Теперь a инициализируется и создается новый массив. Этот массив, однако, не сохраняется непосредственно под переменной, а в другом месте, внутри a есть только ссылка на это место:

  location | name²      |  value
  -------------------------------------
  1        |  a         |  ➡️ 3
  2        |  b         |  undefined
  3        |            |  [1, 2, 3]

Теперь, когда вы делаете b = a ссылка копируется, вы в итоге получаете:

  location | name²      |  value
  -------------------------------------
  1        |  a         |  ➡️ 3
  2        |  b         |  ➡️ 3
  3        |            |  [1, 2, 3]

Теперь, когда вы делаете a = [5,5], создается другой массив, и a ссылается на это. b не изменился, но все еще ссылается на другой массив.

  location | name²      |  value
  -------------------------------------
  1        |  a         |  ➡️ 4
  2        |  b         |  ➡️ 3
  3        |            |  [1, 2, 3]
  4        |            |  [5, 5]

Или, если вы делаете b = {value: a}:

  location | name²      |  value
  -------------------------------------
  1        |  a         |  ➡️ 4
  2        |  b         |  ➡️ 5
  3        |            |  [1, 2, 3] // waiting for GC
  4        |            |  [5, 5]
  5        |            | { value: ➡️4 }

¹ да, JavaScript - это интерпретируемый язык, так что вы не будете точно знать, как он в итоге окажется в памяти, в зависимости от движка. Тем не менее, JS выводит свои концепции из других языков, и поэтому часто полезно думать на низком уровне.

² не существует такой вещи, как имя определенной области памяти, я просто добавил это для ясности.

...