var date1 = new Date();
date1.setFullYear(2011, 6, 1);
// 2011-07-01, ok
console.log(date1);
// set date2 the same date as date1
var date2 = date1;
// ...
// now I'm gonna set a new date for date2
date2.setFullYear(2011, 9, 8);
// 2011-10-08, ok
console.log(date2);
// 2011-10-08, wrong, expecting 2011-07-01
// I didn't assign a new date to date1
// WHY is date1 changed?
console.log(date1);
9条答案
按热度按时间yduiuuwa1#
日期是对象,因此它被指定为引用-简单的方法是
lsmepo6l2#
执行此操作时:
...你并没有创建一个 * new *
Date
对象,你只是从两个独立的变量指向date对象,因为只有一个对象,所以不管你查看哪个变量,你对它所做的任何修改都是显而易见的。让我们用一些ASCII艺术来描述它:
这给我们:
现在当你这样做:
我们有
date1
和date2
变量的 * value * 是Date
对象的 * reference *,而不是它的副本(所有对象都是这样工作的)。您可以将 * object reference * 看作是在内存中查找对象的内存地址(它 * 实际上 * 是什么取决于实现)。这与 * primitives * 不同,后者的变量值实际上包含基元的数据,例如:
结果
(In* theory *。实际上,字符串"primitives"的行为就好像这是真的一样,但实际上可能更像是对象。没关系,字符串是不可变的,并且字符串 * primitives * 的
==
和===
会比较它们的内容,所以我们不能真正区分它们,我们可以假装它们实际上包含在变量中。[只是为了真正让人困惑:JavaScript还有Number
和String
对象,它们的行为类似于对象。])回复您的问题如下:
在此期间,创建第二个与先前存在的javascript对象相同的javascript对象的最有效方法是什么?
JavaScript对象没有通用的"克隆"操作,因此答案因对象而异。有些对象不需要克隆,因为它们是不可变的(不能改变),所以不需要克隆(例如
String
对象)。要克隆一个 * 日期 *,很简单:
或者稍微更有效率的:
(因为
+
告诉date1
对象将其自身转换为一个数字,然后Date
构造函数使用该数字。如果没有它,date1
对象将被要求将其自身转换为一个字符串,然后Date
构造函数将解析该字符串。仍然有效,但通过数字进行优化是一个微观的--几乎可以肯定是不成熟的优化--而且可能会干扰引擎可能想要使用的任何隐藏优化。rslzwgfq3#
这两个日期变量只是对内存中同一个日期对象的引用,所以
date2
需要是date1
的克隆。改为:
ne5o7dgx4#
JavaScript对Dates*(以及所有非基元--
var o = {}; var j = o; j.foo = 1; console.log(o.foo); //1
。另一方面,对Numbers、String和Booleansvar o = 0; var j = o; j++; console.log(j); // 0
)使用通过引用传递,因此这是预期的行为。如果您需要复制日期,您可以随时
cld4siwp5#
它是对
date1
的引用。要达到预期效果,请执行以下操作:
ax6ht2ek6#
更多阅读:Date – MDN.
gc0ot86w7#
@SergeS答案的变体,但js中的Date()对象强制为number,因此不需要getTime():
并使用OP变量名重新表述:
gzszwxb48#
您需要创建
date1
的副本,当前date1
和date2
引用同一个日期对象。j5fpnvbx9#
执行此操作时:
你在第一行创建了一个Date对象,但是第二行并不创建另一个Date对象,它只是指向或引用已经创建的Date对象。这是许多面向对象编程语言的共同特征。