Установка переменной, равной другой переменной - PullRequest
0 голосов
/ 13 июня 2018

У меня есть несколько вопросов об установке переменной, равной другой переменной в JavaScript.

Допустим, мы создаем объект a и устанавливаем b = a.

var a = {
  fname: "Jon",
  lname: "Smith",
  age: 50
}

var b = a;

Я понимаю, что если мы изменим одно из a свойств, b также будет изменено, потому что когда мы устанавливаем b = a, мы не клонируем данные a, а скорее создаем ссылку на a 'с данными.Например, если мы установим a.fname = "Sarah", новое значение b.fname будет "Sarah".

Если мы попытаемся «очистить» a, хотя, установив a = {}, объект b будетостается неизменным.Я не понимаю, почему манипулирование объектом таким способом дает другой результат, чем в первом примере.


Также у меня есть вопрос по поводу следующего сценария.

var x = 10;
var z = x;

Если мы затем установим x = 20, значение z останется неизменным.Основываясь на поведении, описанном в моем первом вопросе, можно подумать, что новое значение z будет отражать новое значение x.Может кто-нибудь объяснить, что мне здесь не хватает?

Спасибо!

Ответы [ 3 ]

0 голосов
/ 13 июня 2018

В первом случае:

var a = {
  fname: "Jon",
  lname: "Smith",
  age: 50
}

var b = a;
a = {}

b остается неизменным, потому что это последовательность событий, происходящих в фоновом режиме:

  • Вы создаете объектпо адресу памяти 0x1234 с данными

    fname: "Jon", lname: "Smith", age: 50

  • Указатель на этот блок памяти хранится в a.

  • Затем этот указатель копируется в b

На этом этапе есть две ссылки на один и тот же бит памяти.Изменение чего-либо в этом блоке памяти повлияет на обе ссылки на него.

  • a = {} не очищает блок памяти 0x1234, но создает новый объект в другом месте памяти (0x1235) и сохраняетуказатель на этот блок в a.Память в 0x1234 остается неизменной, потому что b все еще указывает на нее.

В этом типе управления памятью есть разница между простыми переменными и объектами / указателями.Строки и числа имеют простое разнообразие и «передаются по значению», а не «передаются по ссылке» для объектов.

0 голосов
/ 13 июня 2018

Позвольте мне попытаться объяснить:

1) В вашем примере a и b являются ссылками на один и тот же объект, а a.fname (или b.fname) является атрибутомэтот объект.Таким образом, при манипулировании атрибутом он будет изменен в объекте, в то время как ссылки не будут затронуты, они по-прежнему указывают на один и тот же объект, сам объект был изменен.a = {}, с другой стороны, просто заменит ссылку на объект, не затрагивая сам объект или ссылку на него b.
Нет никакого смысла, кстати, вы только что создали новую ссылку на новый пустой объект.

2) Это не объекты, поэтому нет ссылки, что вы непосредственно манипулируете значениями.Это потому, что есть разница между объектами и примитивами, которая может запутаться, особенно в начале, если вы не привыкли работать со строгими типами.

0 голосов
/ 13 июня 2018

Действительно короткий ответ на оба ваших вопроса заключается в том, что когда вы делаете одну переменную равной другой, создается копия того, что находится в первой переменной, и сохраняется во второй переменной - нет никакой связи междудве переменные.

Но, читайте подробнее, и почему в некоторых случаях может показаться, что есть ссылка ...


JavaScript, как и многие языки, разделяет данныена две широкие категории: типы значений и ссылочные типы.Типы значений JavaScript: его примитивы :

  • строка
  • число
  • логическое значение
  • ноль
  • undefined
  • символ

Когда вы присваиваете какой-либо из этих типов переменной, фактические данные сохраняются в этой переменной, и если вы установите одну переменную, равнуюдругая, копия (не связывание) примитива создается и сохраняется в новой переменной:

var a = 10;  // Store the actual number 10 in the a variable
var b = a;   // Store a COPY of the actual number stored in a (10) in the b variable
a = 50;      // Change the actual data stored in a to 50 (no change to b here)
console.log(b);  // 10

Когда вы работаете с ссылочными типами , происходит что-то немного другое.Присвоение переменной ссылочному типу означает, что переменная содержит только ссылку на область памяти, где фактически хранится объект, а не сам объект.Таким образом, когда вы делаете это:

var a = {foo:"bar"};

a на самом деле не хранит сам объект, он только сохраняет место в памяти, где можно найти объект (то есть 0x3C41A).

Но что касается установки другой переменной, равной первой, то она все еще работает так же, как и с примитивами - копия того, что в первой переменной, сделано и передановторая переменная.

Вот пример:

// An object is instantiated in memory and a is given the address of it (for example 0x3C41A)
var a = {}; 
 
// The contents of a (the memory location of an object) is COPIED into b.
// Now, both a and b hold the same memory location of the object (0x3C41A)
var b = a;

// Regardless of whether a or b is used, the same underlying object
// will be affected:
a.foo = "test";
console.log(b.foo); // "test"

// If one of the variables takes on a new value, it won't change
// what the other variable holds:
a = "something else";
console.log(b);   // The object stored in memory location (0x3C41A)

Итак, в ваших первых тестах у вас просто есть два способа доступа к одному объекту, а затем вы меняете то, что удерживает a (место в памяти объекта) к другому объекту и, следовательно, теперь у вас есть только один способ доступа к исходному объекту: b.


Если мы попытаемся «очистить» a, установивa = {}, объект b останется неизменным.Я не понимаю, почему манипулирование объектом таким способом приводит к другому результату, чем в первом примере.

Потому что теперь мы знаем, что a = {} не очищает объект.Он просто указывает a на что-то еще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...