我有一个函数返回一个对象,其中一个属性是作为参数(参数)传递给它的日期对象的值。
当从循环中调用此函数时,改变发送到它的日期参数并将所有返回的对象添加到数组中 - 我注意到数组中的所有对象都以相同的值结束对于日期对象 - 这是循环内日期的最终值。
为了演示,我有一个函数(theFunction
),它返回字符串表示以及date参数本身作为返回对象的两个属性。
从另一个函数(theLoop
)调用此函数,该函数使用循环内的不同日期值调用theFunction
并将函数调用的结果存储到数组中。
var theFunction = function (inputDate) {
/* The string representation and the date itself as properties on the returned object */
return {
string: inputDate.toLocaleString(),
original: inputDate
};
};
var theLoop = function (startDate) {
// declare an array for the output
var dates = [];
for (var minute = 0; minute < 1440; minute = minute + 30) {
var newHour = minute % 60,
newMinute = minute - newHour * 60;
// loop and increment the time by a half-hour starting from midnight until minutes < 1440
startDate.setHours(newHour, newMinute);
// record the output from theFunction into the array
dates.push(theFunction(startDate));
}
// return the array
return dates;
};
// get the array
var datesArray = theLoop(new Date());
// console.log the array
console.log(datesArray);
请参阅this fiddle以运行上述代码。
问题1:为什么从名为theFunction
的函数中返回的对象持有对theLoop
中循环内递增的日期变量的引用?
问题2:如何更改theFunction
以便它返回传递给它的日期的副本?
答案 0 :(得分:2)
问题1 :Javascript中的Date
是Object
;在Javascript Object
中,Function
是指针,因此,对象值只是一个指针。当您将对象(或函数)作为参数传递(或将对象值分配给另一个变量)时,您传递(或分配)指向内存中“真实”对象的指针。在这种情况下:
//get the array
var datesArray = theLoop(new Date());
您通过new Date()
作为参数调用theLoop
,您刚刚传递了一个指针,您没有传递该对象的新副本。因此,修改“几个”日期只是通过其指针的几个副本修改一个内存位置中的一个日期。
问题2 :要解决此问题,只需在theLoop
中添加一点:
var theLoop = function (startDate) { // 'startDate' should be renamed, but I still use this for ease of explain.
...
for (...) {
startDate = new Date(startDate); // HERE!!
...
}
return dates;
}
因为new Date(startDate)
会创建原始日期的新副本。有关更多详细信息:Javascript中的Date
包含一个名为timestamp的无符号整数;在这种情况下,new Date(startDate)
完全等同于new Date(parseInt(startDate))
或new Date(startDate.valueOf())
。
重要:同样,Javascript参数不是通过引用传递的,这是错误的,它们总是通过值传递任何类型的值。使用对象(或函数),它们也不会通过引用传递!相反,它们是指针,让我们说指针(对象)是通过值传递的。
此外,现在您可能知道运算符new
实际意味着什么。我认为,就像C ++一样,它意味着“创建指向已分配内存区域的指针”。
答案 1 :(得分:1)
因为每个对象仍然引用相同的startDate
对象。因此,当startDate发生更改时,每个对象都会受到该更改的影响。
将您的循环更改为此
var theLoop = function (startDate) {
// declare an array for the output
var dates = [];
for (var minute = 0; minute < 1440; minute = minute + 30) {
var newHour = minute % 60,
newMinute = minute - newHour * 60;
// loop and increment the time by a half-hour starting from midnight until minutes < 1440
startDate.setHours(newHour, newMinute);
var newDate = new Date(startDate.getTime());
// record the output from theFunction into the array
dates.push(theFunction(newDate));
}
// return the array
return dates;
};
答案 2 :(得分:1)
您有一个Date对象(startDate
),您可以使用setHours
进行修改,并在每次迭代中将引用传递给theFunction。
要解决此问题,请从inputDate
(updated fiddle)创建新日期:
var theFunction = function (inputDate) {
/* The string representation and the date itself as properties on the returned object */
var inputDateClone = new Date(inputDate.getTime()); // the cloned date
return {
string: inputDateClone.toLocaleString(),
original: inputDateClone
};
};