Примитивные типы/ссылочные типы в Javascript
Я жил в предположении, что в Javascript есть примитивные типы и ссылочные типы. На повседневной основе я никогда не оказывал на меня такого влияния, но я только начинал намного больше JS и хотел обновить свое "мышление". Другими словами, я бы поставил $20, что следующее вернет 68
var my_obj = {};
var tmp_obj = {};
tmp_obj.my_int = 38;
my_obj.tmp_val = tmp_obj.my_int;
tmp_obj.my_int = 68;
alert('68 means reference, 38 means primitve: ' + my_obj.tmp_val);
но он возвращает 38.
![enter image description here]()
Являются ли все экземпляры чисел примитивными типами, даже если они существуют в контексте ссылочного типа? Если я, я действительно удивлен и нахожу это странное поведение (и не будет 20 долларов США). Или мой пример не показывает, что я думаю?
спасибо заранее
ОБНОВЛЕНИЕ # 1
Ничего себе, спасибо для всех ответов. Здесь небольшое изменение, которое помогает мне в недоумении:
var my_obj={};
var tmp_obj={};
var my_obj_2=tmp_obj;
tmp_obj.my_int=38;
my_obj.tmp_val=tmp_obj.my_int;
tmp_obj.my_int=68
alert('68 means reference, 38 means primitve: ' + my_obj.tmp_val); // 38
alert('68 means reference, 38 means primitve: ' + my_obj_2.my_int); // 68
my_obj_2.my_int=78;
alert(tmp_obj.my_int); // tmp_obj is now 78 ie two way
Ответы
Ответ 1
Вы, например, будете работать как ожидалось, если бы у вас
my_obj = tmp_obj;
Затем все свойства будут указывать на одну и ту же ссылку, поскольку будет только один объект.
Но когда вы пишете
my_obj.tmp_val = tmp_obj.my_int;
то my_obj.tmp_val
примет значение, сохраненное в tmp_obj.my_int
, но не создающее новую ссылку между двумя объектами.
Ответ 2
Если я могу использовать синтаксис, подобный Java, кажется, вы ожидали, что код будет вести себя следующим образом, где есть целочисленный объект с измененным значением.
tmp_obj.my_int = new Integer(38);
my_obj.tmp_val = tmp_obj.my_int;
tmp_obj.my_int.setValue(68);
Поскольку он не печатает 68
, вы заключаете, что целые числа должны быть примитивным типом, а не ссылочным типом. Это не обязательно следует. Рассмотрим эту альтернативную интерпретацию:
tmp_obj.my_int = new Integer(38);
my_obj.tmp_val = tmp_obj.my_int;
tmp_obj.my_int = new Integer(68);
Здесь целые числа являются ссылочными типами, но my_obj.tmp_val
по-прежнему будет содержать значение 38
, потому что назначение целому числу означает перезапись ссылок.
Вы можете думать, что целые числа являются неизменяемыми. JavaScript делает очень хорошую работу по представлению единого представления "все-есть-объект", поэтому это лучшая интерпретация результатов, чем "целые числа являются примитивными типами".
Ответ 3
Я жил в предположении, что в Javascript есть примитивные типы и ссылочные типы.
Это правда. Однако единственными ссылочными значениями являются объекты; примитивные значения не изменяются.
Являются ли все экземпляры чисел примитивными типами, даже если они существуют в контексте ссылочного типа?
Да. Их контекст не имеет значения.
Ответ 4
Да, значения, такие как числа и строки, работают как примитивные значения. Они неизменны. Присвоение нового значения переменной заменяет старое значение, оно не меняет значение, которое там.
Пример:
var x = 42;
var y = x; // y == 42
x = 1337; // this puts a new value in x, it doesn't change 42 to be 1337
alert(y); // it still 42
То же самое работает для строк:
var x = "42";
var y = x; // y == "42"
x = "1337"; // this puts a new string in x, it doesn't change "42" to be "1337"
alert(y); // it still "42"
Также, если вы используете свойства объекта,
var o = {};
o.x = 42;
o.y = o.x; // o.y == 42
o.x = 1337; // this puts a new value in o.x, it doesn't change 42 to be 1337
alert(o.y); // it still 42
Как действует значение, зависит только его тип, а не сохраняет его в обычной переменной или в свойстве объекта.
Даже если строки реализованы как объект внутри, он неизменен и работает как ценность. Копирование строки может скопировать ссылку на объект, но эффект заключается в том, что вы получаете отдельную копию, потому что ничто не может изменить значение самой строки.
Ответ 5
Я считаю, что здесь есть две ключевые вещи:
- Примитивные значения никогда не ссылаются
- Ссылки JavaScript никогда не могут быть назначены, просто скопированы.
Учитывая этот код, чтобы продемонстрировать первую точку:
var a = 10,
b = a,
c = {foo : 20}
d = c.foo;
b = 20;
d = 30;
a; // 10;
c.foo; // 20;
Итак, у вас есть "слоты" (переменные или свойства), содержащие примитивные значения, а не ссылки. Изменение значения в одном из этих слотов не повлияет на остальных.
Учитывая вторую точку:
var a = {foo: true},
b = a;
b.foo; // true
b.foo = false;
a.foo; // false;
b = {bar: false};
a; // {foo: false}
Переменная a
содержит объект, а b
- это ссылка на тот же объект. Присвоение b.foo
влияет на a
, так как b
и a
указывают на тот же самый объект. Однако эти ссылки аналогичны любым другим значениям, хранящимся в данном слоте: когда вы назначаете что-то еще в слот, ссылка просто заменяется на другое значение. Поэтому присвоение b
не влияет на a
.