Подтвердить что ты не робот

Примитивные типы/ссылочные типы в 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
4b9b3361

Ответ 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.