Почему javascript date.setDate() изменяет значение других переменных даты

Когда я пытаюсь узнать функциональность setDate(), setTime() даты javascript, я столкнулся с этой проблемой.

<script>
var date1 = new Date();
var date2 = new Date(1991,4,11);
var date3 = new Date(1992,4,11);

date3 = date1;
date2 = date1;
date2.setDate(date2 .getDate() + 40);//im changing only date2 value using setDate()  

//print values

</script>   

Думаю, результат будет таким:
Пт, 04 июля 2014 г.
Ср, 13 августа 2014 г.
Пт, 04 июля 2014 г.

Но на выходе все переменные даты имеют одинаковое значение:

Ср, 13 августа 2014 г.

Ср, 13 августа 2014 г.

Ср, 13 августа 2014 г.

jsfiddle

Если я делаю аналогичный код с целочисленными переменными, они работают так, как я думаю (все переменные int имеют разные значения).

Сводка вопросов

  1. Чем отличается присвоение даты и присвоение номера?
  2. Почему и как javascript setDate() отслеживает другие переменные даты?
  3. И последнее, но не менее важное: Что мне нужно сделать, если я хочу изменить только значение date2 с помощью этих назначений?

Заранее спасибо.


person ManirajSS    schedule 04.07.2014    source источник


Ответы (3)


Вам нужно сделать копию ваших дат, например:

date3 = new Date(date1.getTime());
date2 = new Date(date1.getTime());

или просто:

date3 = new Date(date1);
date2 = new Date(date1);

вместо

date3 = date1;
date2 = date1;

В противном случае все ваши переменные указывают на один и тот же объект Date (первоначально на который ссылается date1).


EDIT (о выделении памяти)

    - Example 1:
var date1 = new Date();           // Memory allocation for an object
var date2 = new Date(1991,4,11);  // Memory allocation n°2
var date3;                        // Obviously no memory allocation here

date3 = date1;                    // No memory allocation either, date2 and date3
date2 = date1;                    // become references of the object in date1

В этом примере есть два выделения памяти, но только одно из них полезно, так как объект в date2 не используется.

Примечание. Объект, изначально находившийся в date2, все еще существует, но на него больше нет ссылок (он будет удален сборщиком мусора).


    - Example 2:
var date1 = new Date();            // Memory allocation for an object
var date2 = new Date(date1);       // Memory allocation n°2
var date3 = new Date(date1);       // Memory allocation n°3

В этом примере есть три выделения памяти для трех разных объектов. Второе и третье распределения состоят в создании новых объектов Date, содержащих копию объекта в date1.


Я надеюсь, что это более ясно с этим небольшим объяснением. Если вас интересует управление памятью в JavaScript, я предлагаю вам взглянуть на это:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management

person Tip-Sy    schedule 04.07.2014
comment
На самом деле вам не нужен .getTime(). - person Bergi; 04.07.2014
comment
@Bergi Хорошо, я не был уверен, что новая дата (дата1) была кросс-браузерным решением. - person Tip-Sy; 04.07.2014
comment
не могли бы вы объяснить что-то еще о распределении памяти в этом случае (чем отличаются оба назначения)? - person ManirajSS; 13.08.2014
comment
Мне потребовалось некоторое время, чтобы улучшить свой ответ, добавив некоторые пояснения о распределении памяти. Надеюсь, вам понравится! :) - person Tip-Sy; 12.09.2014
comment
Ха. не нуждался в объяснении, ваши первые 3 строки ответили на мой вопрос. Спасибо! - person ssaltman; 16.03.2015

Вы назначаете ссылку на объект date1, выполняя

date3 = date1;
date2 = date1;

Итак, теперь, например, при использовании date2 вы фактически ссылаетесь на объект даты, хранящийся в переменной date1.

person Jurijs Kastanovs    schedule 04.07.2014

Проще говоря, Date — это объект, а «Fri Jul 04 2014» — только его содержимое. Итак, когда вы делаете

date3 = date1;

ты говоришь:

пусть переменная date3 указывает на тот же объект, что и переменная date1. Но по-прежнему есть только один объект с одним содержанием (например, ваш «Пт, 04 июля 2014 г.»). Доступ к нему через date1.toDateString() или date3.toDateString() не имеет значения. Поэтому, когда вы меняете его с помощью date3.setDate() или date1.setDate();, это тоже не имеет значения.

Что вам нужно сделать, так это создать еще один объект с тем же содержимым:

date3 = new Date(date1.getTime());

Представьте, что есть комната с одной дверью (d1) и внутри комнаты белая кошка. Когда вы говорите d2 = d1, вы просто строите еще одну дверь в ту же комнату с тем же белым котом. Если вы звоните d2.changeCat(black), то вы входите в комнату через дверь d2 и меняете белого кота на черного. Если позже вы войдете в комнату через другую дверь (d1), то, конечно, вы просто найдете черную кошку. И вот что происходит.

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

person tomorrow    schedule 04.07.2014